Update TxID to avoid collisions on DB (fix #503)

This commit is contained in:
arnaucube
2021-01-27 22:41:18 +01:00
parent a899f43914
commit aade6220d4
14 changed files with 220 additions and 59 deletions

View File

@@ -1,6 +1,7 @@
package common
import (
"crypto/sha256"
"encoding/binary"
"fmt"
"math/big"
@@ -111,26 +112,39 @@ func (tx *L1Tx) SetType() error {
// SetID sets the ID of the transaction. For L1UserTx uses (ToForgeL1TxsNum,
// Position), for L1CoordinatorTx uses (BatchNum, Position).
func (tx *L1Tx) SetID() error {
var b []byte
if tx.UserOrigin {
if tx.ToForgeL1TxsNum == nil {
return tracerr.Wrap(fmt.Errorf("L1Tx.UserOrigin == true && L1Tx.ToForgeL1TxsNum == nil"))
}
tx.TxID[0] = TxIDPrefixL1UserTx
var toForgeL1TxsNumBytes [8]byte
binary.BigEndian.PutUint64(toForgeL1TxsNumBytes[:], uint64(*tx.ToForgeL1TxsNum))
copy(tx.TxID[1:9], toForgeL1TxsNumBytes[:])
b = append(b, toForgeL1TxsNumBytes[:]...)
} else {
if tx.BatchNum == nil {
return tracerr.Wrap(fmt.Errorf("L1Tx.UserOrigin == false && L1Tx.BatchNum == nil"))
}
tx.TxID[0] = TxIDPrefixL1CoordTx
var batchNumBytes [8]byte
binary.BigEndian.PutUint64(batchNumBytes[:], uint64(*tx.BatchNum))
copy(tx.TxID[1:9], batchNumBytes[:])
b = append(b, batchNumBytes[:]...)
}
var positionBytes [2]byte
binary.BigEndian.PutUint16(positionBytes[:], uint16(tx.Position))
copy(tx.TxID[9:11], positionBytes[:])
b = append(b, positionBytes[:]...)
// calculate hash
h := sha256.New()
_, err := h.Write(b[:])
if err != nil {
return tracerr.Wrap(err)
}
r := h.Sum(nil)
copy(tx.TxID[1:], r)
return nil
}

View File

@@ -29,7 +29,7 @@ func TestNewL1UserTx(t *testing.T) {
}
l1Tx, err := NewL1Tx(l1Tx)
assert.NoError(t, err)
assert.Equal(t, "0x00000000000001e240004700", l1Tx.TxID.String())
assert.Equal(t, "0x00eb5e95e1ce5e9f6c4ed402d415e8d0bdd7664769cfd2064d28da04a2c76be432", l1Tx.TxID.String())
}
func TestNewL1CoordinatorTx(t *testing.T) {
@@ -46,7 +46,7 @@ func TestNewL1CoordinatorTx(t *testing.T) {
}
l1Tx, err := NewL1Tx(l1Tx)
assert.NoError(t, err)
assert.Equal(t, "0x01000000000000cafe005800", l1Tx.TxID.String())
assert.Equal(t, "0x01b8ae2bf60cb8f7c2315a27f13c8863fa2370d15ccc2e68490e197030ba22b97e", l1Tx.TxID.String())
}
func TestL1TxCompressedData(t *testing.T) {
@@ -279,3 +279,69 @@ func TestL1CoordinatorTxByteParsersCompatibility(t *testing.T) {
assert.Equal(t, expected, encodeData)
}
func TestL1TxID(t *testing.T) {
// L1UserTx
i64_1 := int64(1)
i64_2 := int64(2)
tx0 := L1Tx{
UserOrigin: true,
ToForgeL1TxsNum: &i64_1,
Position: 1,
}
err := tx0.SetID()
require.NoError(t, err)
assert.Equal(t, TxIDPrefixL1UserTx, tx0.TxID[0])
// differ ToForgeL1TxsNum
tx1 := L1Tx{
UserOrigin: true,
ToForgeL1TxsNum: &i64_2,
Position: 1,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
// differ Position
tx1 = L1Tx{
UserOrigin: true,
ToForgeL1TxsNum: &i64_1,
Position: 2,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
// L1CoordinatorTx
bn1 := BatchNum(1)
bn2 := BatchNum(2)
tx0 = L1Tx{
UserOrigin: false,
BatchNum: &bn1,
Position: 1,
}
err = tx0.SetID()
require.NoError(t, err)
assert.Equal(t, TxIDPrefixL1CoordTx, tx0.TxID[0])
// differ BatchNum
tx1 = L1Tx{
UserOrigin: false,
BatchNum: &bn2,
Position: 1,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
// differ Position
tx1 = L1Tx{
UserOrigin: false,
BatchNum: &bn1,
Position: 2,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
}

View File

@@ -1,6 +1,7 @@
package common
import (
"crypto/sha256"
"fmt"
"math/big"
@@ -66,18 +67,53 @@ func (tx *L2Tx) SetType() error {
// SetID sets the ID of the transaction
func (tx *L2Tx) SetID() error {
tx.TxID[0] = TxIDPrefixL2Tx
txID, err := tx.CalculateTxID()
if err != nil {
return err
}
tx.TxID = txID
return nil
}
// CalculateTxID returns the TxID of the transaction. This method is used to
// set the TxID for L2Tx and for PoolL2Tx.
func (tx L2Tx) CalculateTxID() ([TxIDLen]byte, error) {
var txID TxID
var b []byte
// FromIdx
fromIdxBytes, err := tx.FromIdx.Bytes()
if err != nil {
return tracerr.Wrap(err)
return txID, tracerr.Wrap(err)
}
copy(tx.TxID[1:7], fromIdxBytes[:])
b = append(b, fromIdxBytes[:]...)
// TokenID
b = append(b, tx.TokenID.Bytes()[:]...)
// Amount
amountFloat16, err := NewFloat16(tx.Amount)
if err != nil {
return txID, tracerr.Wrap(fmt.Errorf("%s: %d", err, tx.Amount))
}
b = append(b, amountFloat16.Bytes()...)
// Nonce
nonceBytes, err := tx.Nonce.Bytes()
if err != nil {
return tracerr.Wrap(err)
return txID, tracerr.Wrap(err)
}
copy(tx.TxID[7:12], nonceBytes[:])
return nil
b = append(b, nonceBytes[:]...)
// Fee
b = append(b, byte(tx.Fee))
// calculate hash
h := sha256.New()
_, err = h.Write(b)
if err != nil {
return txID, tracerr.Wrap(err)
}
r := h.Sum(nil)
txID[0] = TxIDPrefixL2Tx
copy(txID[1:], r)
return txID, nil
}
// Tx returns a *Tx from the L2Tx

View File

@@ -13,12 +13,13 @@ func TestNewL2Tx(t *testing.T) {
l2Tx := &L2Tx{
FromIdx: 87654,
ToIdx: 300,
TokenID: 5,
Amount: big.NewInt(4),
Nonce: 144,
}
l2Tx, err := NewL2Tx(l2Tx)
assert.NoError(t, err)
assert.Equal(t, "0x020000000156660000000090", l2Tx.TxID.String())
assert.Equal(t, "0x024f67ec893467419cdfacfc9152e55dc7ce16088952bf2b3442732fd046bd031c", l2Tx.TxID.String())
}
func TestL2TxByteParsers(t *testing.T) {

View File

@@ -102,19 +102,13 @@ func (tx *PoolL2Tx) SetType() error {
return nil
}
// SetID sets the ID of the transaction. Uses (FromIdx, Nonce).
// SetID sets the ID of the transaction
func (tx *PoolL2Tx) SetID() error {
tx.TxID[0] = TxIDPrefixL2Tx
fromIdxBytes, err := tx.FromIdx.Bytes()
txID, err := tx.L2Tx().CalculateTxID()
if err != nil {
return tracerr.Wrap(err)
}
copy(tx.TxID[1:7], fromIdxBytes[:])
nonceBytes, err := tx.Nonce.Bytes()
if err != nil {
return tracerr.Wrap(err)
}
copy(tx.TxID[7:12], nonceBytes[:])
tx.TxID = txID
return nil
}

View File

@@ -21,7 +21,7 @@ func TestNewPoolL2Tx(t *testing.T) {
}
poolL2Tx, err := NewPoolL2Tx(poolL2Tx)
assert.NoError(t, err)
assert.Equal(t, "0x020000000156660000000090", poolL2Tx.TxID.String())
assert.Equal(t, "0x024f67ec893467419cdfacfc9152e55dc7ce16088952bf2b3442732fd046bd031c", poolL2Tx.TxID.String())
}
func TestTxCompressedData(t *testing.T) {
@@ -170,3 +170,53 @@ func TestDecompressEmptyBJJComp(t *testing.T) {
assert.Equal(t, "2957874849018779266517920829765869116077630550401372566248359756137677864698", pk.X.String())
assert.Equal(t, "0", pk.Y.String())
}
func TestPoolL2TxID(t *testing.T) {
tx0 := PoolL2Tx{
FromIdx: 5,
ToIdx: 5,
Amount: big.NewInt(5),
Fee: 126,
TokenID: 5,
Nonce: 5,
}
err := tx0.SetID()
require.NoError(t, err)
// differ TokenID
tx1 := PoolL2Tx{
FromIdx: 5,
ToIdx: 5,
Amount: big.NewInt(5),
Fee: 126,
TokenID: 4,
Nonce: 5,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
// differ Nonce
tx1 = PoolL2Tx{
FromIdx: 5,
ToIdx: 5,
Amount: big.NewInt(5),
Fee: 126,
TokenID: 5,
Nonce: 4,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
// differ Fee
tx1 = PoolL2Tx{
FromIdx: 5,
ToIdx: 5,
Amount: big.NewInt(5),
Fee: 124,
TokenID: 5,
Nonce: 5,
}
err = tx1.SetID()
require.NoError(t, err)
assert.NotEqual(t, tx0.TxID, tx1.TxID)
}

View File

@@ -31,7 +31,7 @@ const (
TxIDPrefixL2Tx = byte(2)
// TxIDLen is the length of the TxID byte array
TxIDLen = 12
TxIDLen = 33
)
var (

View File

@@ -21,8 +21,9 @@ func TestSignatureConstant(t *testing.T) {
func TestTxIDScannerValue(t *testing.T) {
txid0 := &TxID{}
txid1 := &TxID{}
txid0B := [12]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
txid1B := [12]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
txid0B := [TxIDLen]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}
txid1B := [TxIDLen]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
copy(txid0[:], txid0B[:])
copy(txid1[:], txid1B[:])
@@ -37,7 +38,7 @@ func TestTxIDScannerValue(t *testing.T) {
}
func TestTxIDMarshalers(t *testing.T) {
h := []byte("0x00000000000001e240004700")
h := []byte("0x02f8b4197b990fcef7ab11021675b4532e584b2c6b3f32562a5128ff00dceb9a5b")
var txid TxID
err := txid.UnmarshalText(h)
assert.NoError(t, err)