package transakcio import ( "math/big" "testing" "github.com/hermeznetwork/hermez-node/common" "github.com/stretchr/testify/assert" ) func TestGenerateBlocks(t *testing.T) { set := ` Type: Blockchain CreateAccountDeposit(1) A: 10 CreateAccountDeposit(2) A: 20 CreateAccountDeposit(1) B: 5 CreateAccountDeposit(1) C: 5 CreateAccountDepositTransfer(1) D-A: 15, 10 (3) Transfer(1) A-B: 6 (1) Transfer(1) B-D: 3 (1) Transfer(1) A-D: 1 (1) // set new batch > batch DepositTransfer(1) A-B: 15, 10 (1) Transfer(1) C-A : 3 (1) Transfer(2) A-B: 15 (1) CreateAccountDeposit(1) User0: 20 CreateAccountDeposit(3) User1: 20 Transfer(1) User0-User1: 15 (1) Transfer(3) User1-User0: 15 (1) Transfer(1) A-C: 1 (1) > batch Transfer(1) User1-User0: 1 (1) > block // Exits Transfer(1) A-B: 1 (1) Exit(1) A: 5 ` tc := NewTestContext(t) blocks := tc.GenerateBlocks(set) assert.Equal(t, 2, len(blocks)) assert.Equal(t, 3, len(blocks[0].Batches)) assert.Equal(t, 1, len(blocks[1].Batches)) assert.Equal(t, 5, len(blocks[0].Batches[0].L1UserTxs)) assert.Equal(t, 0, len(blocks[1].Batches[0].L1UserTxs)) // Check expected values generated by each line // #0: Deposit(1) A: 10 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[0], common.TxTypeCreateAccountDeposit, 1, "A", "", big.NewInt(10), nil) // #1: Deposit(2) A: 20 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[1], common.TxTypeCreateAccountDeposit, 2, "A", "", big.NewInt(20), nil) // #2: Deposit(1) A: 20 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[2], common.TxTypeCreateAccountDeposit, 1, "B", "", big.NewInt(5), nil) // #3: CreateAccountDeposit(1) C: 5 tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[3], common.TxTypeCreateAccountDeposit, 1, "C", "", big.NewInt(5), nil) // #4: CreateAccountDepositTransfer(1) D-A: 15, 10 (3) tc.checkL1TxParams(t, blocks[0].Batches[0].L1UserTxs[4], common.TxTypeCreateAccountDepositTransfer, 1, "D", "A", big.NewInt(15), big.NewInt(10)) // #5: Transfer(1) A-B: 6 (1) tc.checkL2TxParams(t, blocks[0].Batches[0].L2Txs[0], common.TxTypeTransfer, 1, "A", "B", big.NewInt(6), common.BatchNum(0), common.Nonce(1)) // #6: Transfer(1) B-D: 3 (1) tc.checkL2TxParams(t, blocks[0].Batches[0].L2Txs[1], common.TxTypeTransfer, 1, "B", "D", big.NewInt(3), common.BatchNum(0), common.Nonce(1)) // #7: Transfer(1) A-D: 1 (1) tc.checkL2TxParams(t, blocks[0].Batches[0].L2Txs[2], common.TxTypeTransfer, 1, "A", "D", big.NewInt(1), common.BatchNum(0), common.Nonce(2)) // change of Batch // #8: DepositTransfer(1) A-B: 15, 10 (1) tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[0], common.TxTypeDepositTransfer, 1, "A", "B", big.NewInt(15), big.NewInt(10)) // #9: Deposit(1) User0: 20 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[0], common.TxTypeDepositTransfer, 1, "A", "B", big.NewInt(15), big.NewInt(10)) // #10: Transfer(1) C-A : 3 (1) tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[0], common.TxTypeTransfer, 1, "C", "A", big.NewInt(3), common.BatchNum(1), common.Nonce(1)) // #11: Transfer(2) A-B: 15 (1) tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[1], common.TxTypeTransfer, 2, "A", "B", big.NewInt(15), common.BatchNum(1), common.Nonce(1)) // #12: Deposit(1) User0: 20 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[1], common.TxTypeCreateAccountDeposit, 1, "User0", "", big.NewInt(20), nil) // #13: Deposit(3) User1: 20 tc.checkL1TxParams(t, blocks[0].Batches[1].L1UserTxs[2], common.TxTypeCreateAccountDeposit, 3, "User1", "", big.NewInt(20), nil) // #14: Transfer(1) User0-User1: 15 (1) tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[2], common.TxTypeTransfer, 1, "User0", "User1", big.NewInt(15), common.BatchNum(1), common.Nonce(1)) // #15: Transfer(3) User1-User0: 15 (1) tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[3], common.TxTypeTransfer, 3, "User1", "User0", big.NewInt(15), common.BatchNum(1), common.Nonce(1)) // #16: Transfer(1) A-C: 1 (1) tc.checkL2TxParams(t, blocks[0].Batches[1].L2Txs[4], common.TxTypeTransfer, 1, "A", "C", big.NewInt(1), common.BatchNum(1), common.Nonce(3)) // change of Batch // #17: Transfer(1) User1-User0: 1 (1) tc.checkL2TxParams(t, blocks[0].Batches[2].L2Txs[0], common.TxTypeTransfer, 1, "User1", "User0", big.NewInt(1), common.BatchNum(2), common.Nonce(1)) // change of Block (implies also a change of batch) // #18: Transfer(1) A-B: 1 (1) tc.checkL2TxParams(t, blocks[1].Batches[0].L2Txs[0], common.TxTypeTransfer, 1, "A", "B", big.NewInt(1), common.BatchNum(3), common.Nonce(4)) } func (tc *TestContext) 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) } assert.Equal(t, tc.Users[from].Addr.Hex(), tx.FromEthAddr.Hex()) assert.Equal(t, tc.Users[from].BJJ.Public(), tx.FromBJJ) if tx.ToIdx != common.Idx(0) { assert.Equal(t, tc.Users[to].Accounts[tokenID].Idx, tx.ToIdx) } if loadAmount != nil { assert.Equal(t, loadAmount, tx.LoadAmount) } 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) { assert.Equal(t, typ, tx.Type) assert.Equal(t, tc.Users[from].Accounts[tokenID].Idx, tx.FromIdx) if tx.Type != common.TxTypeExit { assert.Equal(t, tc.Users[to].Accounts[tokenID].Idx, tx.ToIdx) } if amount != nil { assert.Equal(t, amount, tx.Amount) } assert.Equal(t, batchNum, tx.BatchNum) assert.Equal(t, nonce, tx.Nonce) } func TestGeneratePoolL2Txs(t *testing.T) { set := ` Type: Blockchain CreateAccountDeposit(1) A: 10 CreateAccountDeposit(2) A: 20 CreateAccountDeposit(1) B: 5 CreateAccountDeposit(1) C: 5 CreateAccountDeposit(1) User0: 5 CreateAccountDeposit(1) User1: 0 CreateAccountDeposit(3) User0: 0 CreateAccountDeposit(3) User1: 5 CreateAccountDeposit(2) B: 5 CreateAccountDeposit(2) D: 0 ` tc := NewTestContext(t) _ = tc.GenerateBlocks(set) set = ` Type: PoolL2 PoolTransfer(1) A-B: 6 (1) PoolTransfer(1) B-C: 3 (1) PoolTransfer(1) C-A: 3 (1) PoolTransfer(1) A-B: 1 (1) PoolTransfer(2) A-B: 15 (1) PoolTransfer(1) User0-User1: 15 (1) PoolTransfer(3) User1-User0: 15 (1) PoolTransfer(2) B-D: 3 (1) PoolExit(1) A: 3 ` poolL2Txs := tc.GeneratePoolL2Txs(set) assert.Equal(t, 9, len(poolL2Txs)) assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type) assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type) assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex()) assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[0].ToBJJ.String()) assert.Equal(t, tc.Users["User1"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex()) assert.Equal(t, tc.Users["User1"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String()) 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 set = ` Type: PoolL2 PoolTransfer(1) A-B: 6 (1) PoolTransfer(1) B-C: 3 (1) PoolTransfer(1) A-C: 3 (1) ` poolL2Txs = tc.GeneratePoolL2Txs(set) assert.Equal(t, common.Nonce(4), poolL2Txs[0].Nonce) assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce) assert.Equal(t, common.Nonce(5), poolL2Txs[2].Nonce) }