Add abstraction method of processTxs to StateDB

- Update GHA lint.yml increasing timeout time to avoid GHA Lint errors
- Update common.BatchNum & common.Idx & common.Nonce usage in StateDB
- Add abstraction method of processTxs to StateDB
    - Which will be used by Synchronizer & BatchBuilder
This commit is contained in:
arnaucube
2020-08-24 13:01:31 +02:00
parent 118ebf70b7
commit b4044a2ef7
15 changed files with 149 additions and 85 deletions

View File

@@ -17,7 +17,7 @@ const NLEAFELEMS = 4
// Account is a struct that gives information of the holdings of an address and a specific token. Is the data structure that generates the Value stored in the leaf of the MerkleTree
type Account struct {
TokenID TokenID
Nonce uint64 // max of 40 bits used
Nonce Nonce // max of 40 bits used
Balance *big.Int // max of 192 bits used
PublicKey *babyjub.PublicKey
EthAddr ethCommon.Address
@@ -44,8 +44,10 @@ func (a *Account) Bytes() ([32 * NLEAFELEMS]byte, error) {
return b, fmt.Errorf("%s Balance", ErrNumOverflow)
}
var nonceBytes [8]byte
binary.LittleEndian.PutUint64(nonceBytes[:], a.Nonce)
nonceBytes, err := a.Nonce.Bytes()
if err != nil {
return b, err
}
copy(b[0:4], a.TokenID.Bytes())
copy(b[4:9], nonceBytes[:])
@@ -107,9 +109,9 @@ func AccountFromBigInts(e [NLEAFELEMS]*big.Int) (*Account, error) {
// AccountFromBytes returns a Account from a byte array
func AccountFromBytes(b [32 * NLEAFELEMS]byte) (*Account, error) {
tokenID := binary.LittleEndian.Uint32(b[0:4])
var nonceBytes [8]byte
copy(nonceBytes[:], b[4:9])
nonce := binary.LittleEndian.Uint64(nonceBytes[:])
var nonceBytes5 [5]byte
copy(nonceBytes5[:], b[4:9])
nonce := NonceFromBytes(nonceBytes5)
sign := b[10] == 1
balance := new(big.Int).SetBytes(SwapEndianness(b[32:56])) // b[32:56], as Balance is 192 bits (24 bytes)
if !bytes.Equal(b[56:64], []byte{0, 0, 0, 0, 0, 0, 0, 0}) {

View File

@@ -23,7 +23,7 @@ func TestAccount(t *testing.T) {
account := &Account{
TokenID: TokenID(1),
Nonce: uint64(1234),
Nonce: Nonce(1234),
Balance: big.NewInt(1000),
PublicKey: pk,
EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
@@ -66,7 +66,7 @@ func TestAccountLoop(t *testing.T) {
account := &Account{
TokenID: TokenID(i),
Nonce: uint64(i),
Nonce: Nonce(i),
Balance: big.NewInt(1000),
PublicKey: pk,
EthAddr: address,
@@ -98,7 +98,7 @@ func TestAccountHashValue(t *testing.T) {
account := &Account{
TokenID: TokenID(1),
Nonce: uint64(1234),
Nonce: Nonce(1234),
Balance: big.NewInt(1000),
PublicKey: pk,
EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
@@ -142,7 +142,7 @@ func TestAccountErrNumOverflowNonce(t *testing.T) {
// check limit
account := &Account{
TokenID: TokenID(1),
Nonce: uint64(math.Pow(2, 40) - 1),
Nonce: Nonce(math.Pow(2, 40) - 1),
Balance: big.NewInt(1000),
PublicKey: pk,
EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
@@ -151,7 +151,7 @@ func TestAccountErrNumOverflowNonce(t *testing.T) {
assert.Nil(t, err)
// force value overflow
account.Nonce = uint64(math.Pow(2, 40))
account.Nonce = Nonce(math.Pow(2, 40))
b, err := account.Bytes()
assert.NotNil(t, err)
assert.Equal(t, fmt.Errorf("%s Nonce", ErrNumOverflow), err)
@@ -169,7 +169,7 @@ func TestAccountErrNumOverflowBalance(t *testing.T) {
// check limit
account := &Account{
TokenID: TokenID(1),
Nonce: uint64(math.Pow(2, 40) - 1),
Nonce: Nonce(math.Pow(2, 40) - 1),
Balance: new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil), big.NewInt(1)),
PublicKey: pk,
EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),

View File

@@ -1,6 +1,8 @@
package common
import (
"encoding/binary"
"fmt"
"math/big"
ethCommon "github.com/ethereum/go-ethereum/common"
@@ -26,3 +28,19 @@ type Batch struct {
// BatchNum identifies a batch
type BatchNum uint32
// Bytes returns a byte array of length 4 representing the BatchNum
func (bn BatchNum) Bytes() []byte {
var batchNumBytes [4]byte
binary.LittleEndian.PutUint32(batchNumBytes[:], uint32(bn))
return batchNumBytes[:]
}
// BatchNumFromBytes returns BatchNum from a []byte
func BatchNumFromBytes(b []byte) (BatchNum, error) {
if len(b) != 4 {
return 0, fmt.Errorf("can not parse BatchNumFromBytes, bytes len %d, expected 4", len(b))
}
batchNum := binary.LittleEndian.Uint32(b[:4])
return BatchNum(batchNum), nil
}

View File

@@ -31,7 +31,6 @@ func (tx *L1Tx) Tx() *Tx {
TxID: tx.TxID,
FromIdx: tx.FromIdx,
ToIdx: tx.ToIdx,
TokenID: tx.TokenID,
Amount: tx.Amount,
Nonce: 0,
Fee: 0,

View File

@@ -18,3 +18,15 @@ type L2Tx struct {
// Extra metadata, may be uninitialized
Type TxType `meddler:"-"` // optional, descrives which kind of tx it's
}
func (tx *L2Tx) Tx() *Tx {
return &Tx{
TxID: tx.TxID,
FromIdx: tx.FromIdx,
ToIdx: tx.ToIdx,
Amount: tx.Amount,
Nonce: tx.Nonce,
Fee: tx.Fee,
Type: tx.Type,
}
}

View File

@@ -27,11 +27,12 @@ func (n Nonce) Bytes() ([5]byte, error) {
return b, nil
}
func NonceFromBytes(b [5]byte) (Nonce, error) {
// NonceFromBytes returns Nonce from a [5]byte
func NonceFromBytes(b [5]byte) Nonce {
var nonceBytes [8]byte
copy(nonceBytes[:], b[:5])
nonce := binary.LittleEndian.Uint64(nonceBytes[:])
return Nonce(nonce), nil
return Nonce(nonce)
}
// PoolL2Tx is a struct that represents a L2Tx sent by an account to the coordinator hat is waiting to be forged
@@ -171,12 +172,24 @@ func (tx *PoolL2Tx) VerifySignature(pk *babyjub.PublicKey) bool {
return pk.VerifyPoseidon(h, tx.Signature)
}
func (tx *PoolL2Tx) L2Tx() *L2Tx {
return &L2Tx{
TxID: tx.TxID,
BatchNum: tx.BatchNum,
FromIdx: tx.FromIdx,
ToIdx: tx.ToIdx,
Amount: tx.Amount,
Fee: tx.Fee,
Nonce: tx.Nonce,
Type: tx.Type,
}
}
func (tx *PoolL2Tx) Tx() *Tx {
return &Tx{
TxID: tx.TxID,
FromIdx: tx.FromIdx,
ToIdx: tx.ToIdx,
TokenID: tx.TokenID,
Amount: tx.Amount,
Nonce: tx.Nonce,
Fee: tx.Fee,
@@ -184,6 +197,14 @@ func (tx *PoolL2Tx) Tx() *Tx {
}
}
func PoolL2TxsToL2Txs(txs []*PoolL2Tx) []*L2Tx {
var r []*L2Tx
for _, tx := range txs {
r = append(r, tx.L2Tx())
}
return r
}
// PoolL2TxState is a struct that represents the status of a L2 transaction
type PoolL2TxState string

View File

@@ -16,8 +16,7 @@ func TestNonceParser(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, 5, len(nBytes))
assert.Equal(t, "0100000000", hex.EncodeToString(nBytes[:]))
n2, err := NonceFromBytes(nBytes)
assert.Nil(t, err)
n2 := NonceFromBytes(nBytes)
assert.Equal(t, n, n2)
// value before overflow
@@ -26,8 +25,7 @@ func TestNonceParser(t *testing.T) {
assert.Nil(t, err)
assert.Equal(t, 5, len(nBytes))
assert.Equal(t, "ffffffffff", hex.EncodeToString(nBytes[:]))
n2, err = NonceFromBytes(nBytes)
assert.Nil(t, err)
n2 = NonceFromBytes(nBytes)
assert.Equal(t, n, n2)
// expect value overflow
@@ -35,8 +33,6 @@ func TestNonceParser(t *testing.T) {
nBytes, err = n.Bytes()
assert.NotNil(t, err)
assert.Equal(t, ErrNonceOverflow, err)
_, err = NonceFromBytes(nBytes)
assert.Nil(t, err)
}
func TestTxCompressedData(t *testing.T) {

View File

@@ -2,6 +2,7 @@ package common
import (
"encoding/binary"
"fmt"
"math/big"
)
@@ -20,6 +21,15 @@ func (idx Idx) BigInt() *big.Int {
return big.NewInt(int64(idx))
}
// IdxFromBytes returns Idx from a byte array
func IdxFromBytes(b []byte) (Idx, error) {
if len(b) != 4 {
return 0, fmt.Errorf("can not parse Idx, bytes len %d, expected 4", len(b))
}
idx := binary.LittleEndian.Uint32(b[:4])
return Idx(idx), nil
}
// IdxFromBigInt converts a *big.Int to Idx type
func IdxFromBigInt(b *big.Int) (Idx, error) {
if b.Int64() > 0xffffffff { // 2**32-1
@@ -64,7 +74,6 @@ type Tx struct {
TxID TxID
FromIdx Idx // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
ToIdx Idx // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositTransfer
TokenID TokenID
Amount *big.Int
Nonce Nonce // effective 40 bits used
Fee FeeSelector

View File

@@ -58,3 +58,7 @@ type ZKInputs struct {
type CallDataForge struct {
// TBD
}
type ExitTreeLeaf struct {
// TBD
}