mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Merge pull request #247 from hermeznetwork/feature/til-sets
Add Til set w minimum flow, add balances tests at StateDB ProcessTxs, small fixes at StateDB
This commit is contained in:
@@ -28,6 +28,9 @@ var (
|
||||
// ErrToIdxNotFound is used when trying to get the ToIdx from ToEthAddr
|
||||
// or ToEthAddr&ToBJJ
|
||||
ErrToIdxNotFound = errors.New("ToIdx can not be found")
|
||||
// ErrGetIdxNoCase is used when trying to get the Idx from EthAddr &
|
||||
// BJJ with not compatible combination
|
||||
ErrGetIdxNoCase = errors.New("Can not get Idx due unexpected combination of ethereum Address & BabyJubJub PublicKey")
|
||||
|
||||
// KeyCurrentBatch is used as key in the db to store the current BatchNum
|
||||
KeyCurrentBatch = []byte("k:currentbatch")
|
||||
|
||||
@@ -264,7 +264,7 @@ func (s *StateDB) getTokenIDsBigInt(l1usertxs, l1coordinatortxs []common.L1Tx, l
|
||||
// AccountsDB (in the StateDB)
|
||||
acc, err := s.GetAccount(l2txs[i].FromIdx)
|
||||
if err != nil {
|
||||
log.Errorf("ToIdx %d not found: %s", l2txs[i].ToIdx, err.Error())
|
||||
log.Errorf("could not get account to determine TokenID of L2Tx: FromIdx %d not found: %s", l2txs[i].FromIdx, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
tokenIDs[acc.TokenID] = true
|
||||
@@ -397,7 +397,6 @@ func (s *StateDB) processL2Tx(coordIdxsMap map[common.TokenID]common.Idx, collec
|
||||
// case when tx.Type== common.TxTypeTransferToEthAddr or common.TxTypeTransferToBJJ
|
||||
tx.AuxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ, tx.TokenID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, nil, false, err
|
||||
}
|
||||
}
|
||||
@@ -607,6 +606,7 @@ func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx, coll
|
||||
fee := common.CalcFeeAmount(tx.Amount, *tx.Fee)
|
||||
feeAndAmount := new(big.Int).Add(tx.Amount, fee)
|
||||
accSender.Balance = new(big.Int).Sub(accSender.Balance, feeAndAmount)
|
||||
|
||||
// send the fee to the Idx of the Coordinator for the TokenID
|
||||
accCoord, err := s.GetAccount(coordIdxsMap[accSender.TokenID])
|
||||
if err != nil {
|
||||
@@ -623,6 +623,8 @@ func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx, coll
|
||||
collected.Add(collected, fee)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
|
||||
}
|
||||
|
||||
// add amount-feeAmount to the receiver
|
||||
@@ -676,7 +678,6 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
|
||||
PublicKey: tx.FromBJJ,
|
||||
EthAddr: tx.FromEthAddr,
|
||||
}
|
||||
accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
|
||||
accReceiver, err := s.GetAccount(tx.ToIdx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -762,6 +763,8 @@ func (s *StateDB) applyExit(coordIdxsMap map[common.TokenID]common.Idx, collecte
|
||||
collected.Add(collected, fee)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
acc.Balance = new(big.Int).Sub(acc.Balance, tx.Amount)
|
||||
}
|
||||
|
||||
p, err := s.UpdateAccount(tx.FromIdx, acc)
|
||||
|
||||
@@ -15,6 +15,139 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func checkBalance(t *testing.T, tc *til.Context, sdb *StateDB, username string, tokenid int, expected string) {
|
||||
idx := tc.Users[username].Accounts[common.TokenID(tokenid)].Idx
|
||||
acc, err := sdb.GetAccount(idx)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, expected, acc.Balance.String())
|
||||
}
|
||||
|
||||
func TestProcessTxsBalances(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "tmpdb")
|
||||
require.Nil(t, err)
|
||||
defer assert.Nil(t, os.RemoveAll(dir))
|
||||
|
||||
sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// generate test transactions from test.SetBlockchain0 code
|
||||
tc := til.NewContext(eth.RollupConstMaxL1UserTx)
|
||||
blocks, err := tc.GenerateBlocks(til.SetBlockchainMinimumFlow0)
|
||||
require.Nil(t, err)
|
||||
|
||||
// Coordinator Idx where to send the fees
|
||||
coordIdxs := []common.Idx{256, 257}
|
||||
|
||||
log.Debug("block:0 batch:0, only L1CoordinatorTxs")
|
||||
_, err = sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
log.Debug("block:0 batch:1")
|
||||
l1UserTxs := []common.L1Tx{}
|
||||
l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
|
||||
log.Debug("block:0 batch:2")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[2].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "A", 0, "500")
|
||||
|
||||
log.Debug("block:0 batch:3")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[3].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[3].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[3].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "A", 0, "500")
|
||||
checkBalance(t, tc, sdb, "A", 1, "500")
|
||||
|
||||
log.Debug("block:0 batch:4")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[4].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[4].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[4].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "A", 0, "500")
|
||||
checkBalance(t, tc, sdb, "A", 1, "500")
|
||||
|
||||
log.Debug("block:0 batch:5")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[5].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[5].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[5].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "A", 0, "600")
|
||||
checkBalance(t, tc, sdb, "A", 1, "500")
|
||||
checkBalance(t, tc, sdb, "B", 0, "400")
|
||||
|
||||
log.Debug("block:0 batch:6")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[6].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[6].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[6].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "Coord", 0, "10")
|
||||
checkBalance(t, tc, sdb, "Coord", 1, "20")
|
||||
checkBalance(t, tc, sdb, "A", 0, "600")
|
||||
checkBalance(t, tc, sdb, "A", 1, "280")
|
||||
checkBalance(t, tc, sdb, "B", 0, "290")
|
||||
checkBalance(t, tc, sdb, "B", 1, "200")
|
||||
checkBalance(t, tc, sdb, "C", 0, "100")
|
||||
checkBalance(t, tc, sdb, "D", 0, "800")
|
||||
|
||||
log.Debug("block:0 batch:7")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Batches[7].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[7].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Batches[7].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "Coord", 0, "35")
|
||||
checkBalance(t, tc, sdb, "Coord", 1, "30")
|
||||
checkBalance(t, tc, sdb, "A", 0, "430")
|
||||
checkBalance(t, tc, sdb, "A", 1, "280")
|
||||
checkBalance(t, tc, sdb, "B", 0, "390")
|
||||
checkBalance(t, tc, sdb, "B", 1, "90")
|
||||
checkBalance(t, tc, sdb, "C", 0, "45")
|
||||
checkBalance(t, tc, sdb, "C", 1, "100")
|
||||
checkBalance(t, tc, sdb, "D", 0, "800")
|
||||
|
||||
log.Debug("block:1 batch:0")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Batches[0].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[0].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "Coord", 0, "75")
|
||||
checkBalance(t, tc, sdb, "Coord", 1, "30")
|
||||
checkBalance(t, tc, sdb, "A", 0, "730")
|
||||
checkBalance(t, tc, sdb, "A", 1, "280")
|
||||
checkBalance(t, tc, sdb, "B", 0, "380")
|
||||
checkBalance(t, tc, sdb, "B", 1, "90")
|
||||
checkBalance(t, tc, sdb, "C", 0, "845")
|
||||
checkBalance(t, tc, sdb, "C", 1, "100")
|
||||
checkBalance(t, tc, sdb, "D", 0, "470")
|
||||
|
||||
log.Debug("block:1 batch:1")
|
||||
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Batches[1].Batch.ForgeL1TxsNum])
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[1].L2Txs)
|
||||
_, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
|
||||
// use Set of PoolL2 txs
|
||||
poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow0)
|
||||
assert.Nil(t, err)
|
||||
|
||||
_, err = sdb.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
|
||||
require.Nil(t, err)
|
||||
checkBalance(t, tc, sdb, "Coord", 0, "105")
|
||||
checkBalance(t, tc, sdb, "Coord", 1, "40")
|
||||
checkBalance(t, tc, sdb, "A", 0, "510")
|
||||
checkBalance(t, tc, sdb, "A", 1, "170")
|
||||
checkBalance(t, tc, sdb, "B", 0, "480")
|
||||
checkBalance(t, tc, sdb, "B", 1, "190")
|
||||
checkBalance(t, tc, sdb, "C", 0, "845")
|
||||
checkBalance(t, tc, sdb, "C", 1, "100")
|
||||
checkBalance(t, tc, sdb, "D", 0, "360")
|
||||
checkBalance(t, tc, sdb, "F", 0, "100")
|
||||
}
|
||||
|
||||
func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "tmpdb")
|
||||
require.Nil(t, err)
|
||||
@@ -121,7 +254,7 @@ func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "82", acc.Balance.String())
|
||||
assert.Equal(t, "77", acc.Balance.String())
|
||||
|
||||
idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
|
||||
acc, err = sdb.GetAccount(idxB0)
|
||||
@@ -195,7 +328,7 @@ func TestProcessTxsBatchBuilder(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "82", acc.Balance.String())
|
||||
assert.Equal(t, "77", acc.Balance.String())
|
||||
|
||||
idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
|
||||
acc, err = sdb.GetAccount(idxB0)
|
||||
|
||||
@@ -63,6 +63,7 @@ func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr ethCommon.Address, pk
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// store Addr-idx
|
||||
k = concatEthAddrTokenID(addr, tokenID)
|
||||
err = tx.Put(append(PrefixKeyAddr, k...), idxBytes[:])
|
||||
@@ -83,11 +84,11 @@ func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address, tokenID common.TokenID
|
||||
k := concatEthAddrTokenID(addr, tokenID)
|
||||
b, err := s.db.Get(append(PrefixKeyAddr, k...))
|
||||
if err != nil {
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
return common.Idx(0), fmt.Errorf("GetIdxByEthAddr: %s: ToEthAddr: %s, TokenID: %d", ErrToIdxNotFound, addr.Hex(), tokenID)
|
||||
}
|
||||
idx, err := common.IdxFromBytes(b)
|
||||
if err != nil {
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
return common.Idx(0), fmt.Errorf("GetIdxByEthAddr: %s: ToEthAddr: %s, TokenID: %d", err, addr.Hex(), tokenID)
|
||||
}
|
||||
return idx, nil
|
||||
}
|
||||
@@ -99,6 +100,7 @@ func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address, tokenID common.TokenID
|
||||
// the StateDB.
|
||||
func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicKey, tokenID common.TokenID) (common.Idx, error) {
|
||||
if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk == nil {
|
||||
// ToEthAddr
|
||||
// case ToEthAddr!=0 && ToBJJ=0
|
||||
return s.GetIdxByEthAddr(addr, tokenID)
|
||||
} else if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk != nil {
|
||||
@@ -106,16 +108,16 @@ func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicK
|
||||
k := concatEthAddrBJJTokenID(addr, pk, tokenID)
|
||||
b, err := s.db.Get(append(PrefixKeyAddrBJJ, k...))
|
||||
if err != nil {
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
return common.Idx(0), fmt.Errorf("GetIdxByEthAddrBJJ: %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", ErrToIdxNotFound, addr.Hex(), pk, tokenID)
|
||||
}
|
||||
idx, err := common.IdxFromBytes(b)
|
||||
if err != nil {
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
return common.Idx(0), fmt.Errorf("GetIdxByEthAddrBJJ: %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", err, addr.Hex(), pk, tokenID)
|
||||
}
|
||||
return idx, nil
|
||||
}
|
||||
// rest of cases (included case ToEthAddr==0) are not possible
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
return common.Idx(0), fmt.Errorf("GetIdxByEthAddrBJJ: Not found, %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", ErrGetIdxNoCase, addr.Hex(), pk, tokenID)
|
||||
}
|
||||
|
||||
func (s *StateDB) getTokenIDsFromIdxs(idxs []common.Idx) (map[common.TokenID]common.Idx, error) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package statedb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
@@ -82,7 +83,8 @@ func TestGetIdx(t *testing.T) {
|
||||
// expect error when trying to get Idx by addr2 & pk2
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(addr2, pk2, tokenID0)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, ErrToIdxNotFound, err)
|
||||
expectedErr := fmt.Errorf("GetIdxByEthAddrBJJ: %s: ToEthAddr: %s, ToBJJ: %s, TokenID: %d", ErrToIdxNotFound, addr2.Hex(), pk2, tokenID0)
|
||||
assert.Equal(t, expectedErr, err)
|
||||
assert.Equal(t, common.Idx(0), idxR)
|
||||
// expect error when trying to get Idx by addr with not used TokenID
|
||||
_, err = sdb.GetIdxByEthAddr(addr, tokenID1)
|
||||
|
||||
128
test/til/sets.go
128
test/til/sets.go
@@ -202,3 +202,131 @@ PoolTransfer(1) A-C: 3 (1)
|
||||
PoolTransferToEthAddr(1) A-C: 3 (1)
|
||||
PoolTransferToBJJ(1) A-C: 3 (1)
|
||||
`
|
||||
|
||||
// Minimum flow
|
||||
|
||||
// SetBlockchainMinimumFlow0 contains a set of transactions with a minimal flow
|
||||
var SetBlockchainMinimumFlow0 = `
|
||||
Type: Blockchain
|
||||
|
||||
AddToken(1)
|
||||
|
||||
|
||||
// Coordinator accounts, Idxs: 256, 257
|
||||
CreateAccountCoordinator(0) Coord
|
||||
CreateAccountCoordinator(1) Coord
|
||||
|
||||
// close Block:0, Batch:0
|
||||
> batch // forge L1Coord{2}
|
||||
|
||||
CreateAccountDeposit(0) A: 500
|
||||
CreateAccountDeposit(1) C: 0
|
||||
CreateAccountCoordinator(0) C
|
||||
|
||||
// close Block:0, Batch:1
|
||||
> batchL1 // freeze L1User{2}, forge L1Coord{1}
|
||||
// Expected balances:
|
||||
// Coord(0): 0, Coord(1): 0
|
||||
// C(0): 0
|
||||
|
||||
CreateAccountDeposit(1) A: 500
|
||||
|
||||
// close Block:0, Batch:2
|
||||
> batchL1 // freeze L1User{1}, forge L1User{2}
|
||||
// Expected balances:
|
||||
// Coord(0): 0, Coord(1): 0
|
||||
// A(0): 500
|
||||
// C(0): 0, C(1): 0
|
||||
|
||||
// close Block:0, Batch:3
|
||||
> batchL1 // freeze L1User{nil}, forge L1User{1}
|
||||
// Expected balances:
|
||||
// Coord(0): 0, Coord(1): 0
|
||||
// A(0): 500, A(1): 500
|
||||
// C(0): 0
|
||||
|
||||
|
||||
CreateAccountDepositTransfer(0) B-A: 500, 100
|
||||
|
||||
// close Block:0, Batch:4
|
||||
> batchL1 // freeze L1User{1}, forge L1User{nil}
|
||||
CreateAccountDeposit(0) D: 800
|
||||
|
||||
// close Block:0, Batch:5
|
||||
> batchL1 // freeze L1User{1}, forge L1User{1}
|
||||
// Expected balances:
|
||||
// Coord(0): 0, Coord(1): 0
|
||||
// A(0): 600, A(1): 500
|
||||
// B(0): 400
|
||||
// C(0): 0
|
||||
|
||||
CreateAccountCoordinator(1) B
|
||||
|
||||
Transfer(1) A-B: 200 (200)
|
||||
Transfer(0) B-C: 100 (200)
|
||||
|
||||
// close Block:0, Batch:6
|
||||
> batchL1 // forge L1User{1}, forge L1Coord{2}, forge L2{2}
|
||||
// Expected balances:
|
||||
// Coord(0): 10, Coord(1): 20
|
||||
// A(0): 600, A(1): 280
|
||||
// B(0): 290, B(1): 200
|
||||
// C(0): 100, C(1): 0
|
||||
// D(0): 800
|
||||
|
||||
Deposit(0) C: 500
|
||||
DepositTransfer(0) C-D: 400, 100
|
||||
|
||||
Transfer(0) A-B: 100 (200)
|
||||
Transfer(0) C-A: 50 (200)
|
||||
Transfer(1) B-C: 100 (200)
|
||||
Exit(0) A: 100 (200)
|
||||
|
||||
ForceTransfer(0) D-B: 200
|
||||
ForceExit(0) B: 100
|
||||
|
||||
// close Block:0, Batch:7
|
||||
> batchL1 // freeze L1User{4}, forge L1User{nil}, forge L2{4}
|
||||
> block
|
||||
// Expected balances:
|
||||
// Coord(0): 35, Coord(1): 30
|
||||
// A(0): 430, A(1): 280
|
||||
// B(0): 390, B(1): 90
|
||||
// C(0): 45, C(1): 100
|
||||
// D(0): 800
|
||||
|
||||
Transfer(0) D-A: 300 (200)
|
||||
Transfer(0) B-D: 100 (200)
|
||||
|
||||
// close Block:1, Batch:0
|
||||
> batchL1 // freeze L1User{nil}, forge L1User{4}, forge L2{1}
|
||||
// Expected balances:
|
||||
// Coord(0): 75, Coord(1): 30
|
||||
// A(0): 730, A(1): 280
|
||||
// B(0): 380, B(1): 90
|
||||
// C(0): 845, C(1): 100
|
||||
// D(0): 470
|
||||
|
||||
CreateAccountCoordinator(0) F
|
||||
|
||||
> batch // forge L1CoordinatorTx{1}
|
||||
> block
|
||||
`
|
||||
|
||||
// SetPoolL2MinimumFlow0 contains a set of transactions with a minimal flow
|
||||
var SetPoolL2MinimumFlow0 = `
|
||||
Type: PoolL2
|
||||
|
||||
PoolTransfer(0) A-B: 100 (200)
|
||||
PoolTransferToEthAddr(0) D-F: 100 (200)
|
||||
PoolExit(0) A: 100 (200)
|
||||
PoolTransferToEthAddr(1) A-B: 100 (200)
|
||||
|
||||
// Expected balances:
|
||||
// Coord(0): 105, Coord(1): 40
|
||||
// A(0): 510, A(1): 170
|
||||
// B(0): 480, B(1): 190
|
||||
// C(0): 845, C(1): 100
|
||||
// D(0): 360
|
||||
// F(0): 100
|
||||
`
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCompileSets(t *testing.T) {
|
||||
func TestCompileSetsBase(t *testing.T) {
|
||||
parser := newParser(strings.NewReader(SetBlockchain0))
|
||||
_, err := parser.parse()
|
||||
assert.Nil(t, err)
|
||||
@@ -22,3 +22,12 @@ func TestCompileSets(t *testing.T) {
|
||||
_, err = tc.GeneratePoolL2Txs(SetPool0)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestCompileSetsMinimumFlow(t *testing.T) {
|
||||
// minimum flow
|
||||
tc := NewContext(eth.RollupConstMaxL1UserTx)
|
||||
_, err := tc.GenerateBlocks(SetBlockchainMinimumFlow0)
|
||||
assert.Nil(t, err)
|
||||
_, err = tc.GeneratePoolL2Txs(SetPoolL2MinimumFlow0)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ type Context struct {
|
||||
currBlock common.BlockData
|
||||
currBatch common.BatchData
|
||||
currBatchNum int
|
||||
queues [][]L1Tx
|
||||
toForgeNum int
|
||||
Queues [][]L1Tx
|
||||
ToForgeNum int
|
||||
openToForge int
|
||||
currBatchTest struct {
|
||||
l1CoordinatorTxs []L1Tx
|
||||
@@ -75,8 +75,8 @@ func NewContext(rollupConstMaxL1UserTx int) *Context {
|
||||
currBatch: newBatchData(currBatchNum),
|
||||
currBatchNum: currBatchNum,
|
||||
// start with 2 queues, one for toForge, and the other for openToForge
|
||||
queues: make([][]L1Tx, 2),
|
||||
toForgeNum: 0,
|
||||
Queues: make([][]L1Tx, 2),
|
||||
ToForgeNum: 0,
|
||||
openToForge: 1,
|
||||
//nolint:gomnd
|
||||
blockNum: 2, // rollup genesis blockNum
|
||||
@@ -301,8 +301,8 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
||||
return nil, err
|
||||
}
|
||||
case typeNewBatchL1:
|
||||
// for each L1UserTx of the queues[ToForgeNum], calculate the Idx
|
||||
if err = tc.calculateIdxForL1Txs(false, tc.queues[tc.toForgeNum]); err != nil {
|
||||
// for each L1UserTx of the Queues[ToForgeNum], calculate the Idx
|
||||
if err = tc.calculateIdxForL1Txs(false, tc.Queues[tc.ToForgeNum]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = tc.calculateIdxForL1Txs(true, tc.currBatchTest.l1CoordinatorTxs); err != nil {
|
||||
@@ -313,12 +313,14 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
||||
log.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
toForgeL1TxsNum := int64(tc.openToForge)
|
||||
tc.currBatch.Batch.ForgeL1TxsNum = &toForgeL1TxsNum
|
||||
// advance batch
|
||||
tc.toForgeNum++
|
||||
if tc.toForgeNum == tc.openToForge {
|
||||
tc.ToForgeNum++
|
||||
if tc.ToForgeNum == tc.openToForge {
|
||||
tc.openToForge++
|
||||
newQueue := []L1Tx{}
|
||||
tc.queues = append(tc.queues, newQueue)
|
||||
tc.Queues = append(tc.Queues, newQueue)
|
||||
}
|
||||
case typeNewBlock:
|
||||
blocks = append(blocks, tc.currBlock)
|
||||
@@ -349,12 +351,12 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
||||
// calculateIdxsForL1Txs calculates new Idx for new created accounts. If
|
||||
// 'isCoordinatorTxs==true', adds the tx to tc.currBatch.L1CoordinatorTxs.
|
||||
func (tc *Context) calculateIdxForL1Txs(isCoordinatorTxs bool, txs []L1Tx) error {
|
||||
// for each batch.L1CoordinatorTxs of the queues[ToForgeNum], calculate the Idx
|
||||
// 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 Til)")
|
||||
return fmt.Errorf("Can not create same account twice (same User (%s) & same TokenID (%d)) (this is a design property of Til)", tx.fromIdxName, tx.L1Tx.TokenID)
|
||||
}
|
||||
tc.Users[tx.fromIdxName].Accounts[tx.L1Tx.TokenID] = &Account{
|
||||
Idx: common.Idx(tc.idx),
|
||||
@@ -418,19 +420,19 @@ func (tc *Context) setIdxs() error {
|
||||
|
||||
// addToL1Queue adds the L1Tx into the queue that is open and has space
|
||||
func (tc *Context) addToL1Queue(tx L1Tx) error {
|
||||
if len(tc.queues[tc.openToForge]) >= tc.rollupConstMaxL1UserTx {
|
||||
if len(tc.Queues[tc.openToForge]) >= tc.rollupConstMaxL1UserTx {
|
||||
// if current OpenToForge queue reached its Max, move into a
|
||||
// new queue
|
||||
tc.openToForge++
|
||||
newQueue := []L1Tx{}
|
||||
tc.queues = append(tc.queues, newQueue)
|
||||
tc.Queues = append(tc.Queues, newQueue)
|
||||
}
|
||||
// Fill L1UserTx specific parameters
|
||||
tx.L1Tx.UserOrigin = true
|
||||
toForgeL1TxsNum := int64(tc.openToForge)
|
||||
tx.L1Tx.ToForgeL1TxsNum = &toForgeL1TxsNum
|
||||
tx.L1Tx.EthBlockNum = tc.blockNum
|
||||
tx.L1Tx.Position = len(tc.queues[tc.openToForge])
|
||||
tx.L1Tx.Position = len(tc.Queues[tc.openToForge])
|
||||
|
||||
// When an L1UserTx is generated, all idxs must be available (except when idx == 0 or idx == 1)
|
||||
if tx.L1Tx.Type != common.TxTypeCreateAccountDeposit && tx.L1Tx.Type != common.TxTypeCreateAccountDepositTransfer {
|
||||
@@ -457,7 +459,7 @@ func (tc *Context) addToL1Queue(tx L1Tx) error {
|
||||
}
|
||||
tx.L1Tx = *nTx
|
||||
|
||||
tc.queues[tc.openToForge] = append(tc.queues[tc.openToForge], tx)
|
||||
tc.Queues[tc.openToForge] = append(tc.Queues[tc.openToForge], tx)
|
||||
tc.currBlock.L1UserTxs = append(tc.currBlock.L1UserTxs, tx.L1Tx)
|
||||
|
||||
return nil
|
||||
@@ -554,6 +556,7 @@ func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
|
||||
tx := common.PoolL2Tx{
|
||||
FromIdx: tc.Users[inst.from].Accounts[inst.tokenID].Idx,
|
||||
ToIdx: common.Idx(1), // as is an Exit
|
||||
Fee: common.FeeSelector(inst.fee),
|
||||
TokenID: inst.tokenID,
|
||||
Amount: big.NewInt(int64(inst.amount)),
|
||||
Nonce: tc.Users[inst.from].Accounts[inst.tokenID].Nonce,
|
||||
@@ -608,3 +611,12 @@ func (tc *Context) generateKeys(userNames []string) {
|
||||
tc.Users[userNames[i-1]] = &u
|
||||
}
|
||||
}
|
||||
|
||||
// L1TxsToCommonL1Txs converts an array of []til.L1Tx to []common.L1Tx
|
||||
func L1TxsToCommonL1Txs(l1 []L1Tx) []common.L1Tx {
|
||||
var r []common.L1Tx
|
||||
for i := 0; i < len(l1); i++ {
|
||||
r = append(r, l1[i].L1Tx)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user