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:
Eduard S
2020-11-02 12:55:43 +01:00
committed by GitHub
8 changed files with 319 additions and 27 deletions

View File

@@ -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")

View File

@@ -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)

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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)