Skip to content
Snippets Groups Projects
Unverified Commit 3ab6f173 authored by lunfardo314's avatar lunfardo314 Committed by GitHub
Browse files

Merge pull request #435 from lunfardo314/develop

Misc improvements of value transaction and address packages.
parents b04e7aea d15ae794
No related branches found
No related tags found
No related merge requests found
...@@ -95,7 +95,7 @@ func (sigscheme *blsSignatureScheme) Sign(data []byte) Signature { ...@@ -95,7 +95,7 @@ func (sigscheme *blsSignatureScheme) Sign(data []byte) Signature {
if err != nil { if err != nil {
panic(err) panic(err)
} }
return newBLSSignature(pubKeyBin, sig) return NewBLSSignature(pubKeyBin, sig)
} }
func (sigscheme *blsSignatureScheme) String() string { func (sigscheme *blsSignatureScheme) String() string {
...@@ -136,7 +136,8 @@ func BLSSignatureFromBytes(data []byte) (result *BLSSignature, consumedBytes int ...@@ -136,7 +136,8 @@ func BLSSignatureFromBytes(data []byte) (result *BLSSignature, consumedBytes int
return return
} }
func newBLSSignature(pubKey, signature []byte) *BLSSignature { // NewBLSSignature creates BLS signature from raw public key and signature data
func NewBLSSignature(pubKey, signature []byte) *BLSSignature {
var ret BLSSignature var ret BLSSignature
ret[0] = address.VersionBLS ret[0] = address.VersionBLS
copy(ret.pubKey(), pubKey) copy(ret.pubKey(), pubKey)
...@@ -223,7 +224,7 @@ func AggregateBLSSignatures(sigs ...Signature) (Signature, error) { ...@@ -223,7 +224,7 @@ func AggregateBLSSignatures(sigs ...Signature) (Signature, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newBLSSignature(pubKeyBin, sigBin), nil return NewBLSSignature(pubKeyBin, sigBin), nil
} }
// interface contract (allow the compiler to check if the implementation has all of the required methods). // interface contract (allow the compiler to check if the implementation has all of the required methods).
......
package transaction package transaction
import ( import (
"bytes"
"github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/hive.go/marshalutil"
"sort"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address" "github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/packages/binary/datastructure/orderedmap" "github.com/iotaledger/goshimmer/packages/binary/datastructure/orderedmap"
...@@ -16,11 +18,20 @@ type Outputs struct { ...@@ -16,11 +18,20 @@ type Outputs struct {
// NewOutputs is the constructor of the Outputs struct and creates the list of Outputs from the given details. // NewOutputs is the constructor of the Outputs struct and creates the list of Outputs from the given details.
func NewOutputs(outputs map[address.Address][]*balance.Balance) (result *Outputs) { func NewOutputs(outputs map[address.Address][]*balance.Balance) (result *Outputs) {
result = &Outputs{orderedmap.New()} // sorting outputs first before adding to the ordered map to have a deterministic order
for address, balances := range outputs { toSort := make([]address.Address, 0, len(outputs))
result.Add(address, balances) for a := range outputs {
toSort = append(toSort, a)
} }
sort.Slice(toSort, func(i, j int) bool {
return bytes.Compare(toSort[i][:], toSort[j][:]) < 0
})
result = &Outputs{orderedmap.New()}
for _, addr := range toSort {
result.Add(addr, outputs[addr])
}
return return
} }
...@@ -49,7 +60,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O ...@@ -49,7 +60,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
// iterate the corresponding times and collect addresses + their details // iterate the corresponding times and collect addresses + their details
for i := uint32(0); i < addressCount; i++ { for i := uint32(0); i < addressCount; i++ {
// read address // read address
address, addressErr := address.Parse(marshalUtil) addr, addressErr := address.Parse(marshalUtil)
if addressErr != nil { if addressErr != nil {
err = addressErr err = addressErr
...@@ -78,7 +89,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O ...@@ -78,7 +89,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
} }
// add the gathered information as an output // add the gathered information as an output
result.Add(address, coloredBalances) result.Add(addr, coloredBalances)
} }
// return the number of bytes we processed // return the number of bytes we processed
...@@ -117,8 +128,8 @@ func (outputs *Outputs) Bytes() []byte { ...@@ -117,8 +128,8 @@ func (outputs *Outputs) Bytes() []byte {
marshalUtil.WriteBytes(address.Bytes()) marshalUtil.WriteBytes(address.Bytes())
marshalUtil.WriteUint32(uint32(len(balances))) marshalUtil.WriteUint32(uint32(len(balances)))
for _, balance := range balances { for _, bal := range balances {
marshalUtil.WriteBytes(balance.Bytes()) marshalUtil.WriteBytes(bal.Bytes())
} }
return true return true
...@@ -141,10 +152,10 @@ func (outputs *Outputs) String() string { ...@@ -141,10 +152,10 @@ func (outputs *Outputs) String() string {
result += " " + address.String() + ": [\n" result += " " + address.String() + ": [\n"
balancesEmpty := true balancesEmpty := true
for _, balance := range balances { for _, bal := range balances {
balancesEmpty = false balancesEmpty = false
result += " " + balance.String() + ",\n" result += " " + bal.String() + ",\n"
} }
if balancesEmpty { if balancesEmpty {
......
package transaction
import (
"bytes"
"github.com/stretchr/testify/assert"
"testing"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
"golang.org/x/crypto/blake2b"
)
func TestOutputs(t *testing.T) {
rndAddrs := make([]address.Address, 15)
for i := range rndAddrs {
rndAddrs[i] = address.RandomOfType(address.VersionED25519)
}
theMap1 := make(map[address.Address][]*balance.Balance)
for i := 0; i < len(rndAddrs); i++ {
theMap1[rndAddrs[i]] = []*balance.Balance{balance.New(balance.ColorIOTA, int64(i))}
}
out1 := NewOutputs(theMap1)
theMap2 := make(map[address.Address][]*balance.Balance)
for i := len(rndAddrs) - 1; i >= 0; i-- {
theMap2[rndAddrs[i]] = []*balance.Balance{balance.New(balance.ColorIOTA, int64(i))}
}
out2 := NewOutputs(theMap2)
h1 := hashOutputs(t, out1)
h2 := hashOutputs(t, out2)
assert.Equal(t, bytes.Equal(h1, h2), true)
}
func hashOutputs(t *testing.T, out *Outputs) []byte {
h, err := blake2b.New256(nil)
assert.NoError(t, err)
h.Write(out.Bytes())
return h.Sum(nil)
}
package transaction package transaction
import ( import (
"errors"
"fmt" "fmt"
"sync" "sync"
...@@ -277,6 +278,16 @@ func (transaction *Transaction) Sign(signature signaturescheme.SignatureScheme) ...@@ -277,6 +278,16 @@ func (transaction *Transaction) Sign(signature signaturescheme.SignatureScheme)
return transaction return transaction
} }
// PutSignature validates and adds signature to the transaction
func (transaction *Transaction) PutSignature(signature signaturescheme.Signature) error {
if !signature.IsValid(transaction.EssenceBytes()) {
return errors.New("PutSignature: invalid signature")
}
transaction.signatures.Add(signature.Address(), signature)
return nil
}
// String returns a human readable version of this Transaction (for debug purposes). // String returns a human readable version of this Transaction (for debug purposes).
func (transaction *Transaction) String() string { func (transaction *Transaction) String() string {
id := transaction.ID() id := transaction.ID()
......
...@@ -38,7 +38,7 @@ func TestShortDataPayload(t *testing.T) { ...@@ -38,7 +38,7 @@ func TestShortDataPayload(t *testing.T) {
dataPayload := []byte("data payload test") dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload) err := tx.SetDataPayload(dataPayload)
assert.Equal(t, nil, err) assert.NoError(t, err)
dpBack := tx.GetDataPayload() dpBack := tx.GetDataPayload()
assert.Equal(t, true, bytes.Equal(dpBack, dataPayload)) assert.Equal(t, true, bytes.Equal(dpBack, dataPayload))
...@@ -52,7 +52,7 @@ func TestShortDataPayload(t *testing.T) { ...@@ -52,7 +52,7 @@ func TestShortDataPayload(t *testing.T) {
tx.essenceBytes = nil tx.essenceBytes = nil
dataPayload[2] = '?' dataPayload[2] = '?'
err = tx.SetDataPayload(dataPayload) err = tx.SetDataPayload(dataPayload)
assert.Equal(t, nil, err) assert.NoError(t, err)
// expect signature is not valid // expect signature is not valid
check = tx.SignaturesValid() check = tx.SignaturesValid()
...@@ -70,7 +70,7 @@ func TestTooLongDataPayload(t *testing.T) { ...@@ -70,7 +70,7 @@ func TestTooLongDataPayload(t *testing.T) {
dataPayload := []byte(strings.Repeat("1", MaxDataPayloadSize+1)) dataPayload := []byte(strings.Repeat("1", MaxDataPayloadSize+1))
err := tx.SetDataPayload(dataPayload) err := tx.SetDataPayload(dataPayload)
assert.Equal(t, true, err != nil) assert.Error(t, err)
} }
func TestMarshalingEmptyDataPayload(t *testing.T) { func TestMarshalingEmptyDataPayload(t *testing.T) {
...@@ -90,9 +90,8 @@ func TestMarshalingEmptyDataPayload(t *testing.T) { ...@@ -90,9 +90,8 @@ func TestMarshalingEmptyDataPayload(t *testing.T) {
tx1 := Transaction{} tx1 := Transaction{}
_, err := tx1.UnmarshalObjectStorageValue(v) _, err := tx1.UnmarshalObjectStorageValue(v)
if err != nil { assert.NoError(t, err)
assert.Error(t, err)
}
assert.Equal(t, true, tx1.SignaturesValid()) assert.Equal(t, true, tx1.SignaturesValid())
assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes())) assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes()))
} }
...@@ -108,7 +107,7 @@ func TestMarshalingDataPayload(t *testing.T) { ...@@ -108,7 +107,7 @@ func TestMarshalingDataPayload(t *testing.T) {
dataPayload := []byte("data payload test") dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload) err := tx.SetDataPayload(dataPayload)
assert.Equal(t, nil, err) assert.NoError(t, err)
tx.Sign(sigScheme) tx.Sign(sigScheme)
check := tx.SignaturesValid() check := tx.SignaturesValid()
...@@ -119,8 +118,73 @@ func TestMarshalingDataPayload(t *testing.T) { ...@@ -119,8 +118,73 @@ func TestMarshalingDataPayload(t *testing.T) {
tx1 := Transaction{} tx1 := Transaction{}
_, err = tx1.UnmarshalObjectStorageValue(v) _, err = tx1.UnmarshalObjectStorageValue(v)
assert.Equal(t, nil, err) assert.NoError(t, err)
assert.Equal(t, true, tx1.SignaturesValid()) assert.Equal(t, true, tx1.SignaturesValid())
assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes())) assert.Equal(t, true, bytes.Equal(tx1.ID().Bytes(), tx.ID().Bytes()))
} }
func TestPutSignatureValid(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
signature := sigScheme.Sign(tx.EssenceBytes())
assert.Equal(t, signature.IsValid(tx.EssenceBytes()), true)
err = tx.PutSignature(signature)
assert.NoError(t, err)
check := tx.SignaturesValid()
assert.Equal(t, true, check)
}
func TestPutSignatureInvalid(t *testing.T) {
sigScheme := signaturescheme.RandBLS()
addr := sigScheme.Address()
o1 := NewOutputID(addr, RandomID())
inputs := NewInputs(o1)
bal := balance.New(balance.ColorIOTA, 1)
outputs := NewOutputs(map[address.Address][]*balance.Balance{addr: {bal}})
tx := New(inputs, outputs)
dataPayload := []byte("data payload test")
err := tx.SetDataPayload(dataPayload)
assert.NoError(t, err)
signatureValid := sigScheme.Sign(tx.EssenceBytes())
assert.Equal(t, true, signatureValid.IsValid(tx.EssenceBytes()))
sigBytes := make([]byte, len(signatureValid.Bytes()))
copy(sigBytes, signatureValid.Bytes())
// inverse last byte --> corrupt the signatureValid
sigBytes[len(sigBytes)-1] = ^sigBytes[len(sigBytes)-1]
sigCorrupted, consumed, err := signaturescheme.BLSSignatureFromBytes(sigBytes)
assert.NoError(t, err)
assert.Equal(t, consumed, len(sigBytes))
assert.Equal(t, false, sigCorrupted.IsValid(tx.EssenceBytes()))
err = tx.PutSignature(sigCorrupted)
// error expected
assert.Error(t, err)
// 0 signatures is not valid
assert.Equal(t, true, !tx.SignaturesValid())
err = tx.PutSignature(signatureValid)
// no error expected
assert.NoError(t, err)
// valid signatures expected
assert.Equal(t, true, tx.SignaturesValid())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment