-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #144 from ElrondNetwork/merge-rc-v140-freeze-account
Merge rc v140 freeze account
- Loading branch information
Showing
6 changed files
with
239 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package transaction | ||
|
||
import ( | ||
"bytes" | ||
"sort" | ||
|
||
"github.com/ElrondNetwork/elrond-go-core/data" | ||
"github.com/ElrondNetwork/elrond-go-core/hashing" | ||
) | ||
|
||
// SortTransactionsBySenderAndNonceWithFrontRunningProtection - sorts the transactions by address and randomness source to protect from front running | ||
func SortTransactionsBySenderAndNonceWithFrontRunningProtection(transactions []data.TransactionHandler, hasher hashing.Hasher, randomness []byte) { | ||
// make sure randomness is 32bytes and uniform | ||
randSeed := hasher.Compute(string(randomness)) | ||
xoredAddresses := make(map[string][]byte) | ||
|
||
for _, tx := range transactions { | ||
xoredBytes := xorBytes(tx.GetSndAddr(), randSeed) | ||
xoredAddresses[string(tx.GetSndAddr())] = hasher.Compute(string(xoredBytes)) | ||
} | ||
|
||
sorter := func(i, j int) bool { | ||
txI := transactions[i] | ||
txJ := transactions[j] | ||
|
||
delta := bytes.Compare(xoredAddresses[string(txI.GetSndAddr())], xoredAddresses[string(txJ.GetSndAddr())]) | ||
if delta == 0 { | ||
delta = int(txI.GetNonce()) - int(txJ.GetNonce()) | ||
} | ||
|
||
return delta < 0 | ||
} | ||
|
||
sort.Slice(transactions, sorter) | ||
} | ||
|
||
// TODO remove duplicated function when will use the version of elrond-go which exports transaction order during processing | ||
|
||
// SortTransactionsBySenderAndNonceWithFrontRunningProtectionExtendedTransactions - sorts the transactions by address and randomness source to protect from front running | ||
func SortTransactionsBySenderAndNonceWithFrontRunningProtectionExtendedTransactions(transactions []data.TransactionHandlerWithGasUsedAndFee, hasher hashing.Hasher, randomness []byte) { | ||
// make sure randomness is 32bytes and uniform | ||
randSeed := hasher.Compute(string(randomness)) | ||
xoredAddresses := make(map[string][]byte) | ||
|
||
for _, tx := range transactions { | ||
xoredBytes := xorBytes(tx.GetSndAddr(), randSeed) | ||
xoredAddresses[string(tx.GetSndAddr())] = hasher.Compute(string(xoredBytes)) | ||
} | ||
|
||
sorter := func(i, j int) bool { | ||
txI := transactions[i] | ||
txJ := transactions[j] | ||
|
||
delta := bytes.Compare(xoredAddresses[string(txI.GetSndAddr())], xoredAddresses[string(txJ.GetSndAddr())]) | ||
if delta == 0 { | ||
delta = int(txI.GetNonce()) - int(txJ.GetNonce()) | ||
} | ||
|
||
return delta < 0 | ||
} | ||
|
||
sort.Slice(transactions, sorter) | ||
} | ||
|
||
// SortTransactionsBySenderAndNonce - sorts the transactions by address without the front running protection | ||
func SortTransactionsBySenderAndNonce(transactions []data.TransactionHandler) { | ||
sorter := func(i, j int) bool { | ||
txI := transactions[i] | ||
txJ := transactions[j] | ||
|
||
delta := bytes.Compare(txI.GetSndAddr(), txJ.GetSndAddr()) | ||
if delta == 0 { | ||
delta = int(txI.GetNonce()) - int(txJ.GetNonce()) | ||
} | ||
|
||
return delta < 0 | ||
} | ||
|
||
sort.Slice(transactions, sorter) | ||
} | ||
|
||
// SortTransactionsBySenderAndNonceExtendedTransactions - sorts the transactions by address without the front running protection | ||
func SortTransactionsBySenderAndNonceExtendedTransactions(transactions []data.TransactionHandlerWithGasUsedAndFee) { | ||
sorter := func(i, j int) bool { | ||
txI := transactions[i] | ||
txJ := transactions[j] | ||
|
||
delta := bytes.Compare(txI.GetSndAddr(), txJ.GetSndAddr()) | ||
if delta == 0 { | ||
delta = int(txI.GetNonce()) - int(txJ.GetNonce()) | ||
} | ||
|
||
return delta < 0 | ||
} | ||
|
||
sort.Slice(transactions, sorter) | ||
} | ||
|
||
// parameters need to be of the same len, otherwise it will panic (if second slice shorter) | ||
func xorBytes(a, b []byte) []byte { | ||
res := make([]byte, len(a)) | ||
for i := range a { | ||
res[i] = a[i] ^ b[i] | ||
} | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package transaction | ||
|
||
import ( | ||
"encoding/hex" | ||
"fmt" | ||
"math/big" | ||
"testing" | ||
|
||
"github.com/ElrondNetwork/elrond-go-core/core/mock" | ||
"github.com/ElrondNetwork/elrond-go-core/data" | ||
"github.com/ElrondNetwork/elrond-go-core/data/outport" | ||
"github.com/ElrondNetwork/elrond-go-core/data/transaction" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_SortTransactionsBySenderAndNonceWithFrontRunningProtection(t *testing.T) { | ||
randomness := "randomness" | ||
nbSenders := 5 | ||
|
||
hasher := &mock.HasherStub{ | ||
ComputeCalled: func(s string) []byte { | ||
if s == randomness { | ||
return []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} | ||
} | ||
|
||
return []byte(s) | ||
}, | ||
} | ||
|
||
usedRandomness := hasher.Compute(randomness) | ||
senders := make([][]byte, 0) | ||
for i := 0; i < nbSenders; i++ { | ||
sender := make([]byte, len(usedRandomness)) | ||
copy(sender, usedRandomness) | ||
sender[len(usedRandomness)-1-i] = 0 | ||
senders = append(senders, sender) | ||
} | ||
|
||
txs := []data.TransactionHandler{ | ||
&transaction.Transaction{Nonce: 1, SndAddr: senders[0]}, | ||
&transaction.Transaction{Nonce: 2, SndAddr: senders[2]}, | ||
&transaction.Transaction{Nonce: 1, SndAddr: senders[2]}, | ||
&transaction.Transaction{Nonce: 2, SndAddr: senders[0]}, | ||
&transaction.Transaction{Nonce: 7, SndAddr: senders[1]}, | ||
&transaction.Transaction{Nonce: 6, SndAddr: senders[1]}, | ||
&transaction.Transaction{Nonce: 1, SndAddr: senders[4]}, | ||
&transaction.Transaction{Nonce: 3, SndAddr: senders[3]}, | ||
&transaction.Transaction{Nonce: 3, SndAddr: senders[2]}, | ||
} | ||
wrappedTxs := make([]data.TransactionHandlerWithGasUsedAndFee, 0, len(txs)) | ||
for _, tx := range txs { | ||
wrappedTxs = append(wrappedTxs, outport.NewTransactionHandlerWithGasAndFee(tx, 0, big.NewInt(0))) | ||
} | ||
|
||
SortTransactionsBySenderAndNonceWithFrontRunningProtection(txs, hasher, []byte(randomness)) | ||
SortTransactionsBySenderAndNonceWithFrontRunningProtectionExtendedTransactions(wrappedTxs, hasher, []byte(randomness)) | ||
|
||
expectedOutput := []string{ | ||
"1 ffffffffffffffffffffffffffffff00", | ||
"2 ffffffffffffffffffffffffffffff00", | ||
"6 ffffffffffffffffffffffffffff00ff", | ||
"7 ffffffffffffffffffffffffffff00ff", | ||
"1 ffffffffffffffffffffffffff00ffff", | ||
"2 ffffffffffffffffffffffffff00ffff", | ||
"3 ffffffffffffffffffffffffff00ffff", | ||
"3 ffffffffffffffffffffffff00ffffff", | ||
"1 ffffffffffffffffffffff00ffffffff", | ||
} | ||
|
||
for i, item := range txs { | ||
assert.Equal(t, expectedOutput[i], fmt.Sprintf("%d %s", item.GetNonce(), hex.EncodeToString(item.GetSndAddr()))) | ||
assert.Equal(t, expectedOutput[i], fmt.Sprintf("%d %s", wrappedTxs[i].GetNonce(), hex.EncodeToString(wrappedTxs[i].GetSndAddr()))) | ||
} | ||
} | ||
|
||
func Test_SortTransactionsBySenderAndNonceLegacy(t *testing.T) { | ||
txs := []data.TransactionHandler{ | ||
&transaction.Transaction{Nonce: 3, SndAddr: []byte("bbbb")}, | ||
&transaction.Transaction{Nonce: 1, SndAddr: []byte("aaaa")}, | ||
&transaction.Transaction{Nonce: 5, SndAddr: []byte("bbbb")}, | ||
&transaction.Transaction{Nonce: 2, SndAddr: []byte("aaaa")}, | ||
&transaction.Transaction{Nonce: 7, SndAddr: []byte("aabb")}, | ||
&transaction.Transaction{Nonce: 6, SndAddr: []byte("aabb")}, | ||
&transaction.Transaction{Nonce: 3, SndAddr: []byte("ffff")}, | ||
&transaction.Transaction{Nonce: 3, SndAddr: []byte("eeee")}, | ||
} | ||
wrappedTxs := make([]data.TransactionHandlerWithGasUsedAndFee, 0, len(txs)) | ||
for _, tx := range txs { | ||
wrappedTxs = append(wrappedTxs, outport.NewTransactionHandlerWithGasAndFee(tx, 0, big.NewInt(0))) | ||
} | ||
|
||
SortTransactionsBySenderAndNonce(txs) | ||
SortTransactionsBySenderAndNonceExtendedTransactions(wrappedTxs) | ||
|
||
expectedOutput := []string{ | ||
"1 aaaa", | ||
"2 aaaa", | ||
"6 aabb", | ||
"7 aabb", | ||
"3 bbbb", | ||
"5 bbbb", | ||
"3 eeee", | ||
"3 ffff", | ||
} | ||
|
||
for i, item := range txs { | ||
assert.Equal(t, expectedOutput[i], fmt.Sprintf("%d %s", item.GetNonce(), string(item.GetSndAddr()))) | ||
assert.Equal(t, expectedOutput[i], fmt.Sprintf("%d %s", wrappedTxs[i].GetNonce(), string(wrappedTxs[i].GetSndAddr()))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters