Skip to content
Snippets Groups Projects
Commit be5848e6 authored by lunfardo314's avatar lunfardo314
Browse files

- fixed bug of non-deterministic NewOutputs function

- added function to sort slice of addresses
- minor edits
parent 2173a9dd
No related branches found
No related tags found
No related merge requests found
package address
import (
"bytes"
"sort"
)
type sortedAddresses []Address
func (s sortedAddresses) Len() int {
return len(s)
}
func (s sortedAddresses) Less(i, j int) bool {
return bytes.Compare(s[i][:], s[j][:]) < 0
}
func (s sortedAddresses) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Sort function sorts the slice of addresses
func Sort(addresses []Address) {
sort.Sort(sortedAddresses(addresses))
}
......@@ -16,11 +16,17 @@ type Outputs struct {
// 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) {
result = &Outputs{orderedmap.New()}
for address, balances := range outputs {
result.Add(address, balances)
// sorting outputs first before adding to the ordered map to have a deterministic order
toSort := make([]address.Address, 0, len(outputs))
for a := range outputs {
toSort = append(toSort, a)
}
address.Sort(toSort)
result = &Outputs{orderedmap.New()}
for _, addr := range toSort {
result.Add(addr, outputs[addr])
}
return
}
......@@ -49,7 +55,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
// iterate the corresponding times and collect addresses + their details
for i := uint32(0); i < addressCount; i++ {
// read address
address, addressErr := address.Parse(marshalUtil)
addr, addressErr := address.Parse(marshalUtil)
if addressErr != nil {
err = addressErr
......@@ -78,7 +84,7 @@ func OutputsFromBytes(bytes []byte, optionalTargetObject ...*Outputs) (result *O
}
// add the gathered information as an output
result.Add(address, coloredBalances)
result.Add(addr, coloredBalances)
}
// return the number of bytes we processed
......@@ -117,8 +123,8 @@ func (outputs *Outputs) Bytes() []byte {
marshalUtil.WriteBytes(address.Bytes())
marshalUtil.WriteUint32(uint32(len(balances)))
for _, balance := range balances {
marshalUtil.WriteBytes(balance.Bytes())
for _, bal := range balances {
marshalUtil.WriteBytes(bal.Bytes())
}
return true
......@@ -141,10 +147,10 @@ func (outputs *Outputs) String() string {
result += " " + address.String() + ": [\n"
balancesEmpty := true
for _, balance := range balances {
for _, bal := range balances {
balancesEmpty = false
result += " " + balance.String() + ",\n"
result += " " + bal.String() + ",\n"
}
if balancesEmpty {
......
package transaction
import (
"bytes"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/address"
"github.com/iotaledger/goshimmer/dapps/valuetransfers/packages/balance"
"github.com/magiconair/properties/assert"
"golang.org/x/crypto/blake2b"
"testing"
)
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)
//t.Logf("%s", out1.String())
//t.Logf("%s", out2.String())
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.Equal(t, err, nil)
h.Write(out.Bytes())
return h.Sum(nil)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment