arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
Merge pull request #215 from hermeznetwork/feature/til-update

Feature/til update
Eduard S eduard@iden3.io
Wed, 21 Oct 2020 15:52:07 +0200
commit

efed84f1e8476aa46065e7cf4dc7eeb2b5b63cf0

parent

4ca2124cf96a39cc698865e177ab2b59e97a50e0

M db/statedb/txprocessors_test.go → db/statedb/txprocessors_test.go

@@ -7,7 +7,7 @@ "testing"

"github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/eth" - "github.com/hermeznetwork/hermez-node/test/transakcio" + "github.com/hermeznetwork/hermez-node/test/til" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" )

@@ -24,8 +24,8 @@ sdb, err := NewStateDB(dir, TypeSynchronizer, 32)

assert.Nil(t, err) // generate test transactions from test.SetTest0 code - tc := transakcio.NewTestContext(eth.RollupConstMaxL1UserTx) - blocks, err := tc.GenerateBlocks(transakcio.SetBlockchain0) + tc := til.NewContext(eth.RollupConstMaxL1UserTx) + blocks, err := tc.GenerateBlocks(til.SetBlockchain0) require.Nil(t, err) assert.Equal(t, 29, len(blocks[0].L1UserTxs))

@@ -89,8 +89,8 @@ sdb, err := NewStateDB(dir, TypeBatchBuilder, 32)

assert.Nil(t, err) // generate test transactions from test.SetTest0 code - tc := transakcio.NewTestContext() - blocks := tc.GenerateBlocks(transakcio.SetBlockchain0) + tc := til.NewContext() + blocks := tc.GenerateBlocks(til.SetBlockchain0) assert.Equal(t, 29, len(blocks[0].Batches[0].L1UserTxs)) assert.Equal(t, 0, len(blocks[0].Batches[0].L1CoordinatorTxs))

@@ -139,8 +139,8 @@ sdb, err := NewStateDB(dir, TypeBatchBuilder, 32)

assert.Nil(t, err) // generate test transactions from test.SetTest0 code - tc := transakcio.NewTestContext() - blocks := tc.GenerateBlocks(transakcio.SetBlockchain0) + tc := til.NewContext() + blocks := tc.GenerateBlocks(til.SetBlockchain0) assert.Equal(t, 29, len(blocks[0].Batches[0].L1UserTxs)) assert.Equal(t, 0, len(blocks[0].Batches[0].L1CoordinatorTxs)) assert.Equal(t, 21, len(blocks[0].Batches[0].L2Txs))
M synchronizer/synchronizer_test.go → synchronizer/synchronizer_test.go

@@ -60,7 +60,7 @@ blocks, err := s.historyDB.GetBlocks(0, 9999)

require.Nil(t, err) assert.Equal(t, int64(1), blocks[0].EthBlockNum) - // TODO once transakcio is completed + // TODO once Til is completed /* // Test Sync for a block with new Tokens and L1UserTxs // accounts := test.GenerateKeys(t, []string{"A", "B", "C", "D"})
A test/til/README.md

@@ -0,0 +1,115 @@

+# Til (Test instructions language) +Language to define sets of instructions to simulate Hermez transactions (L1 & L2) with real data. + +## Syntax +### Global +- Set type definition + - Blockchain: generate the transactions that would come from the Hermez smart contract on the blockchain. + ``` + Type: Blockchain + ``` + - PoolL2: generate the transactions that would come from the Pool of L2Txs + ``` + Type: PoolL2 + ``` + +### Blockchain set of instructions +Available instructions: +```go +Type: Blockchain + +// register the TokenID: +RegisterToken(1) + +// deposit of TokenID=1, on the account of tokenID=1 for the user A, of an +// amount of 50 units +CreateAccountDeposit(1) A: 50 + +// create the account of TokenID=1 for the user B, deposit of TokenID=1, on the +// account of tokenID=1 for the user B, of an amount of 40 units and atomically +// transfer 10 units to account of tokenID=1 for the user A, paying a fee of 2 +CreateAccountDepositTransfer(1) B-A: 40, 10 (2) + +// transaction generated by the Coordinator, create account for user User0 for +// the TokenID=2, with a deposit of 0 +CreateAccountDepositCoordinator(2) User0 + + +// deposit of TokenID=1, at the account A, of 6 units +Deposit(1) A: 6 + +// deposit of TokenID=1, on the account of tokenID=1 for the user B, of an +// amount of 6 units and atomically transfer 10 units to account of tokenID=1 for +// the user A, paying a fee of 2 +DepositTransfer(1) B-A: 6, 4 (2) + +// transfer of TokenID=1, from the account A to B (for that token), of 6 units, +// paying a fee of 3. Transaction will be a L2Tx +Transfer(1) A-B: 6 (3) + +// exit of TokenID=1, from the account A (for that token), of 5 units. +// Transaction will be a L2Tx +Exit(1) A: 5 + +// force-transfer of TokenID=1, from the account A to B (for that token), of 6 +// units, paying a fee of 3. Transaction will be L1UserTx of ForceTransfer type +ForceTransfer(1) A-B: 6 (3) + +// force-exit of TokenID=1, from the account A (for that token), of 5 units. +// Transaction will be L1UserTx of ForceExit type +ForceExit(1) A: 5 + +// advance one batch, forging without L1UserTxs, only can contain L2Txs and +// L1CoordinatorTxs +> batch + +// advance one batch, forging with L1UserTxs (and L2Txs and L1CoordinatorTxs) +> batchL1 + +// advance an ethereum block +> block +``` + +### PoolL2 set of instructions +Available instructions: +```go +Type: PoolL2 + +// transfer of TokenID=1, from the account A to B (for that token), of 6 units, +// paying a fee of 4 +PoolTransfer(1) A-B: 6 (4) + +// exit of TokenID=1, from the account A (for that token), of 3 units +PoolExit(1) A: 3 +``` + +## Usage +```go +// create a new til.Context +tc := til.NewContext(eth.RollupConstMaxL1UserTx) + +// generate Blockchain blocks data from the common.SetBlockcahin0 instructions set +blocks, err = tc.GenerateBlocks(common.SetBlockchain0) +assert.Nil(t, err) + +// generate PoolL2 transactions data from the common.SetPool0 instructions set +poolL2Txs, err = tc.GenerateBlocks(common.SetPool0) +assert.Nil(t, err) +``` + +Where `blocks` will contain: +```go +// BatchData contains the information of a Batch +type BatchData struct { + L1CoordinatorTxs []common.L1Tx + L2Txs []common.L2Tx + CreatedAccounts []common.Account +} + +// BlockData contains the information of a Block +type BlockData struct { + L1UserTxs []common.L1Tx + Batches []BatchData + RegisteredTokens []common.Token +} +```
M test/transakcio/lang.go → test/til/lang.go

@@ -1,4 +1,4 @@

-package transakcio +package til import ( "bufio"
M test/transakcio/lang_test.go → test/til/lang_test.go

@@ -1,4 +1,4 @@

-package transakcio +package til import ( "fmt"
M test/transakcio/sets.go → test/til/sets.go

@@ -1,4 +1,4 @@

-package transakcio +package til // sets of instructions to be used in tests of other packages
M test/transakcio/sets_test.go → test/til/sets_test.go

@@ -1,4 +1,4 @@

-package transakcio +package til import ( "strings"

@@ -16,7 +16,7 @@ parser = newParser(strings.NewReader(SetPool0))

_, err = parser.parse() assert.Nil(t, err) - tc := NewTestContext(eth.RollupConstMaxL1UserTx) + tc := NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(SetBlockchain0) assert.Nil(t, err) _, err = tc.GenerateBlocks(SetPool0)
M test/transakcio/txs.go → test/til/txs.go

@@ -1,4 +1,4 @@

-package transakcio +package til import ( "crypto/ecdsa"

@@ -15,8 +15,8 @@ "github.com/hermeznetwork/hermez-node/log"

"github.com/iden3/go-iden3-crypto/babyjub" ) -// TestContext contains the data of the test -type TestContext struct { +// Context contains the data of the test +type Context struct { Instructions []instruction accountsNames []string Users map[string]*User

@@ -35,9 +35,9 @@ toForgeNum int

openToForge int } -// NewTestContext returns a new TestContext -func NewTestContext(rollupConstMaxL1UserTx int) *TestContext { - return &TestContext{ +// NewContext returns a new Context +func NewContext(rollupConstMaxL1UserTx int) *Context { + return &Context{ Users: make(map[string]*User), l1CreatedAccounts: make(map[string]*Account), lastRegisteredTokenID: 0,

@@ -82,8 +82,7 @@ testL1CoordinatorTxs []L1Tx

L2Txs []common.L2Tx // testL2Tx are L2Txs without the Idx&EthAddr&BJJ setted, but with the // string that represents the account - testL2Txs []L2Tx - CreatedAccounts []common.Account + testL2Txs []L2Tx } // L1Tx is the data structure used internally for transaction test generation,

@@ -109,8 +108,8 @@ L2Tx common.L2Tx

} // GenerateBlocks returns an array of BlockData for a given set. It uses the -// accounts (keys & nonces) of the TestContext. -func (tc *TestContext) GenerateBlocks(set string) ([]BlockData, error) { +// accounts (keys & nonces) of the Context. +func (tc *Context) GenerateBlocks(set string) ([]BlockData, error) { parser := newParser(strings.NewReader(set)) parsedSet, err := parser.parse() if err != nil {

@@ -135,7 +134,7 @@ FromEthAddr: tc.Users[inst.from].Addr,

FromBJJ: tc.Users[inst.from].BJJ.Public(), TokenID: inst.tokenID, LoadAmount: big.NewInt(int64(inst.loadAmount)), - Type: common.TxTypeCreateAccountDeposit, // as txTypeCreateAccountDepositCoordinator is not valid oustide Transakcio package + Type: common.TxTypeCreateAccountDeposit, // as txTypeCreateAccountDepositCoordinator is not valid oustide Til package } testTx := L1Tx{ lineNum: inst.lineNum,

@@ -267,11 +266,12 @@ if err = tc.calculateIdxForL1Txs(true, tc.currBatch.testL1CoordinatorTxs); err != nil {

return nil, err } - // once Idxs are calculated, update transactions to use the new Idxs + // once Idxs are calculated, update transactions to use the real Idxs for i := 0; i < len(tc.queues[tc.toForgeNum]); i++ { testTx := &tc.queues[tc.toForgeNum][i] - // set real Idx - testTx.L1Tx.FromIdx = tc.Users[testTx.fromIdxName].Accounts[testTx.L1Tx.TokenID].Idx + if testTx.L1Tx.Type != common.TxTypeCreateAccountDeposit && testTx.L1Tx.Type != common.TxTypeCreateAccountDepositTransfer { + testTx.L1Tx.FromIdx = tc.Users[testTx.fromIdxName].Accounts[testTx.L1Tx.TokenID].Idx + } testTx.L1Tx.FromEthAddr = tc.Users[testTx.fromIdxName].Addr testTx.L1Tx.FromBJJ = tc.Users[testTx.fromIdxName].BJJ.Public() if testTx.toIdxName == "" {

@@ -279,6 +279,18 @@ testTx.L1Tx.ToIdx = common.Idx(0)

} else { testTx.L1Tx.ToIdx = tc.Users[testTx.toIdxName].Accounts[testTx.L1Tx.TokenID].Idx } + if testTx.L1Tx.Type == common.TxTypeExit { + testTx.L1Tx.ToIdx = common.Idx(1) + } + bn := common.BatchNum(tc.currBatchNum) + testTx.L1Tx.BatchNum = &bn + nTx, err := common.NewL1Tx(&testTx.L1Tx) + if err != nil { + fmt.Println(testTx) + return nil, fmt.Errorf("Line %d: %s", testTx.lineNum, err.Error()) + } + testTx.L1Tx = *nTx + tc.currBlock.L1UserTxs = append(tc.currBlock.L1UserTxs, testTx.L1Tx) } if err = tc.setIdxs(); err != nil {

@@ -315,13 +327,13 @@ }

// calculateIdxsForL1Txs calculates new Idx for new created accounts. If // 'isCoordinatorTxs==true', adds the tx to tc.currBatch.L1CoordinatorTxs. -func (tc *TestContext) calculateIdxForL1Txs(isCoordinatorTxs bool, txs []L1Tx) error { +func (tc *Context) calculateIdxForL1Txs(isCoordinatorTxs bool, txs []L1Tx) error { // for each batch.L1CoordinatorTxs of the queues[ToForgeNum], calculate the Idx for i := 0; i < len(txs); i++ { tx := txs[i] if tx.L1Tx.Type == common.TxTypeCreateAccountDeposit || tx.L1Tx.Type == common.TxTypeCreateAccountDepositTransfer { if tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] != nil { // if account already exists, return error - return fmt.Errorf("Can not create same account twice (same User & same TokenID) (this is a design property of Transakcio)") + return fmt.Errorf("Can not create same account twice (same User & same TokenID) (this is a design property of Til)") } tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] = &Account{ Idx: common.Idx(tc.idx),

@@ -338,7 +350,7 @@ return nil

} // setIdxs sets the Idxs to the transactions of the tc.currBatch -func (tc *TestContext) setIdxs() error { +func (tc *Context) setIdxs() error { // once Idxs are calculated, update transactions to use the new Idxs for i := 0; i < len(tc.currBatch.testL2Txs); i++ { testTx := &tc.currBatch.testL2Txs[i]

@@ -361,7 +373,7 @@ testTx.L2Tx.ToIdx = tc.Users[testTx.toIdxName].Accounts[testTx.tokenID].Idx

} nTx, err := common.NewL2Tx(&testTx.L2Tx) if err != nil { - return err + return fmt.Errorf("Line %d: %s", testTx.lineNum, err.Error()) } testTx.L2Tx = *nTx

@@ -376,7 +388,7 @@ return nil

} // addToL1Queue adds the L1Tx into the queue that is open and has space -func (tc *TestContext) addToL1Queue(tx L1Tx) { +func (tc *Context) addToL1Queue(tx L1Tx) { if len(tc.queues[tc.openToForge]) >= tc.rollupConstMaxL1UserTx { // if current OpenToForge queue reached its Max, move into a // new queue

@@ -387,13 +399,13 @@ }

tc.queues[tc.openToForge] = append(tc.queues[tc.openToForge], tx) } -func (tc *TestContext) checkIfAccountExists(tf string, inst instruction) error { +func (tc *Context) checkIfAccountExists(tf string, inst instruction) error { if tc.Users[tf].Accounts[inst.tokenID] == nil { return fmt.Errorf("%s at User: %s, for TokenID: %d, while account not created yet", inst.typ, tf, inst.tokenID) } return nil } -func (tc *TestContext) checkIfTokenIsRegistered(inst instruction) error { +func (tc *Context) checkIfTokenIsRegistered(inst instruction) error { if inst.tokenID > tc.lastRegisteredTokenID { return fmt.Errorf("Can not process %s: TokenID %d not registered, last registered TokenID: %d", inst.typ, inst.tokenID, tc.lastRegisteredTokenID) }

@@ -401,8 +413,8 @@ return nil

} // GeneratePoolL2Txs returns an array of common.PoolL2Tx from a given set. It -// uses the accounts (keys & nonces) of the TestContext. -func (tc *TestContext) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) { +// uses the accounts (keys & nonces) of the Context. +func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) { parser := newParser(strings.NewReader(set)) parsedSet, err := parser.parse() if err != nil {

@@ -480,7 +492,7 @@

// generateKeys generates BabyJubJub & Address keys for the given list of // account names in a deterministic way. This means, that for the same given // 'accNames' in a certain order, the keys will be always the same. -func (tc *TestContext) generateKeys(accNames []string) { +func (tc *Context) generateKeys(accNames []string) { for i := 1; i < len(accNames)+1; i++ { if _, ok := tc.Users[accNames[i-1]]; ok { // account already created
M test/transakcio/txs_test.go → test/til/txs_test.go

@@ -1,4 +1,4 @@

-package transakcio +package til import ( "math/big"

@@ -66,7 +66,7 @@ // this transaction should not be generated, as it's after last

// batch and last block Transfer(1) User1-User0: 1 (1) ` - tc := NewTestContext(eth.RollupConstMaxL1UserTx) + tc := NewContext(eth.RollupConstMaxL1UserTx) blocks, err := tc.GenerateBlocks(set) require.Nil(t, err) assert.Equal(t, 2, len(blocks))

@@ -118,7 +118,7 @@ // #18: Transfer(1) A-B: 1 (1)

tc.checkL2TxParams(t, blocks[1].Batches[0].L2Txs[1], common.TxTypeTransfer, 1, "A", "B", big.NewInt(1), common.BatchNum(5), common.Nonce(5)) } -func (tc *TestContext) checkL1TxParams(t *testing.T, tx common.L1Tx, typ common.TxType, tokenID common.TokenID, from, to string, loadAmount, amount *big.Int) { +func (tc *Context) checkL1TxParams(t *testing.T, tx common.L1Tx, typ common.TxType, tokenID common.TokenID, from, to string, loadAmount, amount *big.Int) { assert.Equal(t, typ, tx.Type) if tx.FromIdx != common.Idx(0) { assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx)

@@ -135,7 +135,7 @@ if amount != nil {

assert.Equal(t, amount, tx.Amount) } } -func (tc *TestContext) checkL2TxParams(t *testing.T, tx common.L2Tx, typ common.TxType, tokenID common.TokenID, from, to string, amount *big.Int, batchNum common.BatchNum, nonce common.Nonce) { +func (tc *Context) checkL2TxParams(t *testing.T, tx common.L2Tx, typ common.TxType, tokenID common.TokenID, from, to string, amount *big.Int, batchNum common.BatchNum, nonce common.Nonce) { assert.Equal(t, typ, tx.Type) assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx) if tx.Type != common.TxTypeExit {

@@ -168,7 +168,7 @@ CreateAccountDeposit(2) D: 0

> batchL1 > batchL1 ` - tc := NewTestContext(eth.RollupConstMaxL1UserTx) + tc := NewContext(eth.RollupConstMaxL1UserTx) _, err := tc.GenerateBlocks(set) require.Nil(t, err) set = `

@@ -197,7 +197,7 @@ assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce)

assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce) assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce) - // load another set in the same TestContext + // load another set in the same Context set = ` Type: PoolL2 PoolTransfer(1) A-B: 6 (1)

@@ -217,7 +217,7 @@ set := `Type: Blockchain

CreateAccountDeposit(1) A: 5 > batchL1 ` - tc := NewTestContext(eth.RollupConstMaxL1UserTx) + tc := NewContext(eth.RollupConstMaxL1UserTx) _, err := tc.GenerateBlocks(set) assert.Equal(t, "Line 2: Can not process CreateAccountDeposit: TokenID 1 not registered, last registered TokenID: 0", err.Error())

@@ -226,7 +226,7 @@ set = `

Type: Blockchain RegisterToken(0) ` - tc = NewTestContext(eth.RollupConstMaxL1UserTx) + tc = NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(set) require.Equal(t, "Line 2: RegisterToken can not register TokenID 0", err.Error())

@@ -234,7 +234,7 @@ set = `

Type: Blockchain RegisterToken(2) ` - tc = NewTestContext(eth.RollupConstMaxL1UserTx) + tc = NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(set) require.Equal(t, "Line 2: RegisterToken TokenID should be sequential, expected TokenID: 1, defined TokenID: 2", err.Error())

@@ -245,7 +245,7 @@ RegisterToken(2)

RegisterToken(3) RegisterToken(5) ` - tc = NewTestContext(eth.RollupConstMaxL1UserTx) + tc = NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(set) require.Equal(t, "Line 5: RegisterToken TokenID should be sequential, expected TokenID: 4, defined TokenID: 5", err.Error())

@@ -259,7 +259,7 @@ CreateAccountDeposit(1) B

Transfer(1) A-B: 6 (1) > batch ` - tc = NewTestContext(eth.RollupConstMaxL1UserTx) + tc = NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(set) require.Equal(t, "Line 5: CreateAccountDeposit(1)BTransfer(1) A-B: 6 (1)\n, err: Expected ':', found 'Transfer'", err.Error()) set = `

@@ -273,7 +273,7 @@ > batch

Transfer(1) A-B: 6 (1) > batch ` - tc = NewTestContext(eth.RollupConstMaxL1UserTx) + tc = NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(set) require.Nil(t, err)

@@ -286,12 +286,12 @@ > batchL1

CreateAccountDepositCoordinator(1) B > batchL1 Transfer(1) A-B: 6 (1) - Transfer(1) A-B: 6 (1) // on purpose this is moving more money that what it has in the account, Transakcio should not fail + Transfer(1) A-B: 6 (1) // on purpose this is moving more money that what it has in the account, Til should not fail Transfer(1) B-A: 6 (1) Exit(1) A: 3 > batch ` - tc = NewTestContext(eth.RollupConstMaxL1UserTx) + tc = NewContext(eth.RollupConstMaxL1UserTx) _, err = tc.GenerateBlocks(set) require.Nil(t, err) assert.Equal(t, common.Nonce(3), tc.Users["A"].Accounts[common.TokenID(1)].Nonce)
D test/transakcio/utils.go

@@ -1,9 +0,0 @@

-package transakcio - -// TODO -// func extendTokenIDs(o, n []common.TokenID) []common.TokenID { -// return o -// } -// func extendAccounts(o, n map[string]*Account) map[string]*Account { -// return o -// }
M txselector/txselector_test.go → txselector/txselector_test.go

@@ -39,7 +39,7 @@ assert.Nil(t, hdb.AddTokens(tokens))

} func TestGetL2TxSelection(t *testing.T) { - txsel := initTest(t, transakcio.SetPool0, 5, 5, 10) + txsel := initTest(t, til.SetPool0, 5, 5, 10) test.CleanL2DB(txsel.l2db.DB()) // generate test transactions

@@ -57,7 +57,7 @@ _, _, _, err = txsel.GetL1L2TxSelection(0, l1Txs[0])

assert.Nil(t, err) // TODO once L2DB is updated to return error in case that AddTxTest - // fails, and the Transakcio is updated, update this test, checking that the + // fails, and the Til is updated, update this test, checking that the // selected PoolL2Tx are correctly sorted by Nonce