Update Common & StateDB & ZKInputs to last protocol version

- Add InvalidData flag to L1Tx
- Add BytesDataAvailability to L1Tx
- Update ZKInputs & HashGlobalInputs to last spec of the protocol
(massive migrations)
- TxProcessor check correctness of L1Txs

Compatible with hermeznetwork/commonjs v0.0.4
(c345239bba)
This commit is contained in:
arnaucube
2020-11-25 20:07:37 +01:00
parent 0c83417881
commit dde9250429
17 changed files with 442 additions and 90 deletions

View File

@@ -783,24 +783,26 @@ func (hdb *HistoryDB) addL1Txs(d meddler.DB, l1txs []common.L1Tx) error {
loadAmountFloat, _ := laf.Float64()
txs = append(txs, txWrite{
// Generic
IsL1: true,
TxID: l1txs[i].TxID,
Type: l1txs[i].Type,
Position: l1txs[i].Position,
FromIdx: &l1txs[i].FromIdx,
ToIdx: l1txs[i].ToIdx,
Amount: l1txs[i].Amount,
AmountFloat: amountFloat,
TokenID: l1txs[i].TokenID,
BatchNum: l1txs[i].BatchNum,
EthBlockNum: l1txs[i].EthBlockNum,
IsL1: true,
TxID: l1txs[i].TxID,
Type: l1txs[i].Type,
Position: l1txs[i].Position,
FromIdx: &l1txs[i].FromIdx,
ToIdx: l1txs[i].ToIdx,
Amount: l1txs[i].Amount,
EffectiveAmount: l1txs[i].EffectiveAmount,
AmountFloat: amountFloat,
TokenID: l1txs[i].TokenID,
BatchNum: l1txs[i].BatchNum,
EthBlockNum: l1txs[i].EthBlockNum,
// L1
ToForgeL1TxsNum: l1txs[i].ToForgeL1TxsNum,
UserOrigin: &l1txs[i].UserOrigin,
FromEthAddr: &l1txs[i].FromEthAddr,
FromBJJ: l1txs[i].FromBJJ,
LoadAmount: l1txs[i].LoadAmount,
LoadAmountFloat: &loadAmountFloat,
ToForgeL1TxsNum: l1txs[i].ToForgeL1TxsNum,
UserOrigin: &l1txs[i].UserOrigin,
FromEthAddr: &l1txs[i].FromEthAddr,
FromBJJ: l1txs[i].FromBJJ,
LoadAmount: l1txs[i].LoadAmount,
EffectiveLoadAmount: l1txs[i].EffectiveLoadAmount,
LoadAmountFloat: &loadAmountFloat,
})
}
return hdb.addTxs(d, txs)
@@ -846,6 +848,7 @@ func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
from_idx,
to_idx,
amount,
effective_amount,
amount_f,
token_id,
batch_num,
@@ -855,6 +858,7 @@ func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
from_eth_addr,
from_bjj,
load_amount,
effective_load_amount,
load_amount_f,
fee,
nonce
@@ -1162,8 +1166,9 @@ func (hdb *HistoryDB) GetAllL1UserTxs() ([]common.L1Tx, error) {
err := meddler.QueryAll(
hdb.db, &txs,
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id, tx.amount,
tx.load_amount, tx.eth_block_num, tx.type, tx.batch_num
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
tx.amount, tx.effective_amount, tx.load_amount, tx.effective_load_amount,
tx.eth_block_num, tx.type, tx.batch_num
FROM tx WHERE is_l1 = TRUE AND user_origin = TRUE;`,
)
return db.SlicePtrsToSlice(txs).([]common.L1Tx), err
@@ -1175,8 +1180,9 @@ func (hdb *HistoryDB) GetAllL1CoordinatorTxs() ([]common.L1Tx, error) {
err := meddler.QueryAll(
hdb.db, &txs,
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id, tx.amount,
tx.load_amount, tx.eth_block_num, tx.type, tx.batch_num
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
tx.amount, tx.effective_amount, tx.load_amount, tx.effective_load_amount,
tx.eth_block_num, tx.type, tx.batch_num
FROM tx WHERE is_l1 = TRUE AND user_origin = FALSE;`,
)
return db.SlicePtrsToSlice(txs).([]common.L1Tx), err
@@ -1201,8 +1207,9 @@ func (hdb *HistoryDB) GetL1UserTxs(toForgeL1TxsNum int64) ([]common.L1Tx, error)
err := meddler.QueryAll(
hdb.db, &txs,
`SELECT tx.id, tx.to_forge_l1_txs_num, tx.position, tx.user_origin,
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id, tx.amount,
tx.load_amount, tx.eth_block_num, tx.type, tx.batch_num
tx.from_idx, tx.from_eth_addr, tx.from_bjj, tx.to_idx, tx.token_id,
tx.amount, tx.effective_amount, tx.load_amount, tx.effective_load_amount,
tx.eth_block_num, tx.type, tx.batch_num
FROM tx WHERE to_forge_l1_txs_num = $1 AND is_l1 = TRUE AND user_origin = TRUE;`,
toForgeL1TxsNum,
)

View File

@@ -112,24 +112,26 @@ func (tx TxAPI) MarshalJSON() ([]byte, error) {
// in order to perform inserts into tx table
type txWrite struct {
// Generic
IsL1 bool `meddler:"is_l1"`
TxID common.TxID `meddler:"id"`
Type common.TxType `meddler:"type"`
Position int `meddler:"position"`
FromIdx *common.Idx `meddler:"from_idx"`
ToIdx common.Idx `meddler:"to_idx"`
Amount *big.Int `meddler:"amount,bigint"`
AmountFloat float64 `meddler:"amount_f"`
TokenID common.TokenID `meddler:"token_id"`
BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
IsL1 bool `meddler:"is_l1"`
TxID common.TxID `meddler:"id"`
Type common.TxType `meddler:"type"`
Position int `meddler:"position"`
FromIdx *common.Idx `meddler:"from_idx"`
ToIdx common.Idx `meddler:"to_idx"`
Amount *big.Int `meddler:"amount,bigint"`
EffectiveAmount *big.Int `meddler:"effective_amount,bigintnull"`
AmountFloat float64 `meddler:"amount_f"`
TokenID common.TokenID `meddler:"token_id"`
BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
// L1
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
FromEthAddr *ethCommon.Address `meddler:"from_eth_addr"`
FromBJJ *babyjub.PublicKey `meddler:"from_bjj"`
LoadAmount *big.Int `meddler:"load_amount,bigintnull"`
LoadAmountFloat *float64 `meddler:"load_amount_f"`
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
FromEthAddr *ethCommon.Address `meddler:"from_eth_addr"`
FromBJJ *babyjub.PublicKey `meddler:"from_bjj"`
LoadAmount *big.Int `meddler:"load_amount,bigintnull"`
EffectiveLoadAmount *big.Int `meddler:"effective_load_amount,bigintnull"`
LoadAmountFloat *float64 `meddler:"load_amount_f"`
// L2
Fee *common.FeeSelector `meddler:"fee"`
Nonce *common.Nonce `meddler:"nonce"`

View File

@@ -149,6 +149,7 @@ CREATE TABLE tx (
to_eth_addr BYTEA,
to_bjj BYTEA,
amount BYTEA NOT NULL,
effective_amount BYTEA,
amount_f NUMERIC NOT NULL,
token_id INT NOT NULL REFERENCES token (token_id),
amount_usd NUMERIC, -- Value of the amount in USD at the moment the tx was inserted in the DB
@@ -158,6 +159,7 @@ CREATE TABLE tx (
to_forge_l1_txs_num BIGINT,
user_origin BOOLEAN,
load_amount BYTEA,
effective_load_amount BYTEA,
load_amount_f NUMERIC,
load_amount_usd NUMERIC,
-- L2

View File

@@ -1,6 +1,7 @@
package statedb
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
@@ -93,7 +94,7 @@ func (s *StateDB) ProcessTxs(ptc ProcessTxsConfig, coordIdxs []common.Idx, l1use
exits := make([]processedExit, nTx)
if s.typ == TypeBatchBuilder {
s.zki = common.NewZKInputs(uint32(nTx), ptc.MaxL1Tx, ptc.MaxTx, ptc.MaxFeeTx, ptc.NLevels)
s.zki = common.NewZKInputs(uint32(nTx), ptc.MaxL1Tx, ptc.MaxTx, ptc.MaxFeeTx, ptc.NLevels, s.currentBatch.BigInt())
s.zki.OldLastIdx = s.idx.BigInt()
s.zki.OldStateRoot = s.mt.Root().BigInt()
}
@@ -138,6 +139,12 @@ func (s *StateDB) ProcessTxs(ptc ProcessTxsConfig, coordIdxs []common.Idx, l1use
}
s.zki.Metadata.L1TxsData = append(s.zki.Metadata.L1TxsData, l1TxData)
l1TxDataAvailability, err := l1usertxs[i].BytesDataAvailability(s.zki.Metadata.NLevels)
if err != nil {
return nil, err
}
s.zki.Metadata.L1TxsDataAvailability = append(s.zki.Metadata.L1TxsDataAvailability, l1TxDataAvailability)
if s.i < nTx-1 {
s.zki.ISOutIdx[s.i] = s.idx.BigInt()
s.zki.ISStateRoot[s.i] = s.mt.Root().BigInt()
@@ -222,7 +229,7 @@ func (s *StateDB) ProcessTxs(ptc ProcessTxsConfig, coordIdxs []common.Idx, l1use
return nil, err
}
if s.zki != nil {
l2TxData, err := l2txs[i].L2Tx().Bytes(s.zki.Metadata.NLevels)
l2TxData, err := l2txs[i].L2Tx().BytesDataAvailability(s.zki.Metadata.NLevels)
if err != nil {
return nil, err
}
@@ -443,6 +450,8 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
switch tx.Type {
case common.TxTypeForceTransfer:
s.computeEffectiveAmounts(tx)
// go to the MT account of sender and receiver, and update balance
// & nonce
@@ -454,6 +463,8 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
return nil, nil, false, nil, err
}
case common.TxTypeCreateAccountDeposit:
s.computeEffectiveAmounts(tx)
// add new account to the MT, update balance of the MT account
err := s.applyCreateAccount(tx)
if err != nil {
@@ -464,6 +475,8 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
// which in the case type==TypeSynchronizer will be added to an
// array of created accounts that will be returned
case common.TxTypeDeposit:
s.computeEffectiveAmounts(tx)
// update balance of the MT account
err := s.applyDeposit(tx, false)
if err != nil {
@@ -471,6 +484,8 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
return nil, nil, false, nil, err
}
case common.TxTypeDepositTransfer:
s.computeEffectiveAmounts(tx)
// update balance in MT account, update balance & nonce of sender
// & receiver
err := s.applyDeposit(tx, true)
@@ -479,6 +494,8 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
return nil, nil, false, nil, err
}
case common.TxTypeCreateAccountDepositTransfer:
s.computeEffectiveAmounts(tx)
// add new account to the merkletree, update balance in MT account,
// update balance & nonce of sender & receiver
err := s.applyCreateAccountDepositTransfer(tx)
@@ -487,6 +504,8 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
return nil, nil, false, nil, err
}
case common.TxTypeForceExit:
s.computeEffectiveAmounts(tx)
// execute exit flow
// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees
exitAccount, newExit, err := s.applyExit(nil, nil, exitTree, tx.Tx())
@@ -520,6 +539,11 @@ func (s *StateDB) processL2Tx(coordIdxsMap map[common.TokenID]common.Idx, collec
var err error
// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
if s.typ == TypeSynchronizer {
// this should never be reached
log.Error("WARNING: In StateDB with Synchronizer mode L2.ToIdx can't be 0")
return nil, nil, false, fmt.Errorf("In StateDB with Synchronizer mode L2.ToIdx can't be 0")
}
// case when tx.Type== common.TxTypeTransferToEthAddr or common.TxTypeTransferToBJJ
tx.AuxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ, tx.TokenID)
if err != nil {
@@ -612,7 +636,7 @@ func (s *StateDB) applyCreateAccount(tx *common.L1Tx) error {
account := &common.Account{
TokenID: tx.TokenID,
Nonce: 0,
Balance: tx.LoadAmount,
Balance: tx.EffectiveLoadAmount,
PublicKey: tx.FromBJJ,
EthAddr: tx.FromEthAddr,
}
@@ -628,7 +652,7 @@ func (s *StateDB) applyCreateAccount(tx *common.L1Tx) error {
s.zki.Sign1[s.i] = big.NewInt(1)
}
s.zki.Ay1[s.i] = tx.FromBJJ.Y
s.zki.Balance1[s.i] = tx.LoadAmount
s.zki.Balance1[s.i] = tx.EffectiveLoadAmount
s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(tx.FromEthAddr)
s.zki.Siblings1[s.i] = siblingsToZKInputFormat(p.Siblings)
if p.IsOld0 {
@@ -656,12 +680,12 @@ func (s *StateDB) applyCreateAccount(tx *common.L1Tx) error {
// andTransfer parameter is set to true, the method will also apply the
// Transfer of the L1Tx/DepositTransfer
func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
// deposit the tx.LoadAmount into the sender account
// deposit the tx.EffectiveLoadAmount into the sender account
accSender, err := s.GetAccount(tx.FromIdx)
if err != nil {
return err
}
accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
accSender.Balance = new(big.Int).Add(accSender.Balance, tx.EffectiveLoadAmount)
// in case that the tx is a L1Tx>DepositTransfer
var accReceiver *common.Account
@@ -671,9 +695,9 @@ func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
return err
}
// subtract amount to the sender
accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.EffectiveAmount)
// add amount to the receiver
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
}
// update sender account in localStateDB
p, err := s.UpdateAccount(tx.FromIdx, accSender)
@@ -723,7 +747,8 @@ func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
// tx.ToIdx==0, then toIdx!=0, and will be used the toIdx parameter as Idx of
// the receiver. This parameter is used when the tx.ToIdx is not specified and
// the real ToIdx is found trhrough the ToEthAddr or ToBJJ.
func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx, collectedFees map[common.TokenID]*big.Int,
func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx,
collectedFees map[common.TokenID]*big.Int,
tx common.Tx, auxToIdx common.Idx) error {
if auxToIdx == common.Idx(0) {
auxToIdx = tx.ToIdx
@@ -824,7 +849,7 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
accSender := &common.Account{
TokenID: tx.TokenID,
Nonce: 0,
Balance: tx.LoadAmount,
Balance: tx.EffectiveLoadAmount,
PublicKey: tx.FromBJJ,
EthAddr: tx.FromEthAddr,
}
@@ -833,9 +858,9 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
return err
}
// subtract amount to the sender
accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.Amount)
accSender.Balance = new(big.Int).Sub(accSender.Balance, tx.EffectiveAmount)
// add amount to the receiver
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
// create Account of the Sender
p, err := s.CreateAccount(common.Idx(s.idx+1), accSender)
@@ -849,7 +874,7 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
s.zki.Sign1[s.i] = big.NewInt(1)
}
s.zki.Ay1[s.i] = tx.FromBJJ.Y
s.zki.Balance1[s.i] = tx.LoadAmount
s.zki.Balance1[s.i] = tx.EffectiveLoadAmount
s.zki.EthAddr1[s.i] = common.EthAddrToBigInt(tx.FromEthAddr)
s.zki.Siblings1[s.i] = siblingsToZKInputFormat(p.Siblings)
if p.IsOld0 {
@@ -890,8 +915,9 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
// It returns the ExitAccount and a boolean determining if the Exit created a
// new Leaf in the ExitTree.
func (s *StateDB) applyExit(coordIdxsMap map[common.TokenID]common.Idx, collectedFees map[common.TokenID]*big.Int,
exitTree *merkletree.MerkleTree, tx common.Tx) (*common.Account, bool, error) {
func (s *StateDB) applyExit(coordIdxsMap map[common.TokenID]common.Idx,
collectedFees map[common.TokenID]*big.Int, exitTree *merkletree.MerkleTree,
tx common.Tx) (*common.Account, bool, error) {
// 0. subtract tx.Amount from current Account in StateMT
// add the tx.Amount into the Account (tx.FromIdx) in the ExitMT
acc, err := s.GetAccount(tx.FromIdx)
@@ -971,6 +997,89 @@ func (s *StateDB) applyExit(coordIdxsMap map[common.TokenID]common.Idx, collecte
return exitAccount, false, err
}
// computeEffectiveAmounts checks that the L1Tx data is correct
func (s *StateDB) computeEffectiveAmounts(tx *common.L1Tx) {
if !tx.UserOrigin {
// case where the L1Tx is generated by the Coordinator
tx.EffectiveAmount = big.NewInt(0)
tx.EffectiveLoadAmount = big.NewInt(0)
return
}
tx.EffectiveAmount = tx.Amount
tx.EffectiveLoadAmount = tx.LoadAmount
if tx.Type == common.TxTypeCreateAccountDeposit {
return
}
if tx.ToIdx >= common.UserThreshold && tx.FromIdx == common.Idx(0) {
// CreateAccountDepositTransfer case
cmp := tx.LoadAmount.Cmp(tx.Amount)
if cmp == -1 { // LoadAmount<Amount
tx.EffectiveAmount = big.NewInt(0)
return
}
return
}
accSender, err := s.GetAccount(tx.FromIdx)
if err != nil {
log.Debugf("EffectiveAmount & EffectiveLoadAmount = 0: can not get account for tx.FromIdx: %d", tx.FromIdx)
tx.EffectiveLoadAmount = big.NewInt(0)
tx.EffectiveAmount = big.NewInt(0)
return
}
// check that tx.TokenID corresponds to the Sender account TokenID
if tx.TokenID != accSender.TokenID {
log.Debugf("EffectiveAmount & EffectiveLoadAmount = 0: tx.TokenID (%d) !=sender account TokenID (%d)", tx.TokenID, accSender.TokenID)
tx.EffectiveLoadAmount = big.NewInt(0)
tx.EffectiveAmount = big.NewInt(0)
return
}
// check that Sender has enough balance
bal := accSender.Balance
if tx.LoadAmount != nil {
bal = new(big.Int).Add(bal, tx.EffectiveLoadAmount)
}
cmp := bal.Cmp(tx.Amount)
if cmp == -1 {
log.Debugf("EffectiveAmount = 0: Not enough funds (%s<%s)", bal.String(), tx.Amount.String())
tx.EffectiveAmount = big.NewInt(0)
return
}
// check that the tx.FromEthAddr is the same than the EthAddress of the
// Sender
if !bytes.Equal(tx.FromEthAddr.Bytes(), accSender.EthAddr.Bytes()) {
log.Debugf("EffectiveAmount & EffectiveLoadAmount = 0: tx.FromEthAddr (%s) must be the same EthAddr of the sender account by the Idx (%s)", tx.FromEthAddr.Hex(), accSender.EthAddr.Hex())
tx.EffectiveLoadAmount = big.NewInt(0)
tx.EffectiveAmount = big.NewInt(0)
return
}
if tx.ToIdx == common.Idx(1) || tx.ToIdx == common.Idx(0) {
// if transfer is Exit type, there are no more checks
return
}
// check that TokenID is the same for Sender & Receiver account
accReceiver, err := s.GetAccount(tx.ToIdx)
if err != nil {
log.Debugf("EffectiveAmount & EffectiveLoadAmount = 0: can not get account for tx.ToIdx: %d", tx.ToIdx)
tx.EffectiveLoadAmount = big.NewInt(0)
tx.EffectiveAmount = big.NewInt(0)
return
}
if accSender.TokenID != accReceiver.TokenID {
log.Debugf("EffectiveAmount & EffectiveLoadAmount = 0: sender account TokenID (%d) != receiver account TokenID (%d)", tx.TokenID, accSender.TokenID)
tx.EffectiveLoadAmount = big.NewInt(0)
tx.EffectiveAmount = big.NewInt(0)
return
}
}
// getIdx returns the stored Idx from the localStateDB, which is the last Idx
// used for an Account in the localStateDB.
func (s *StateDB) getIdx() (common.Idx, error) {

View File

@@ -24,6 +24,116 @@ func checkBalance(t *testing.T, tc *til.Context, sdb *StateDB, username string,
assert.Equal(t, expected, acc.Balance.String())
}
func TestCheckL1TxInvalidData(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)
set := `
Type: Blockchain
AddToken(1)
CreateAccountDeposit(0) A: 10
CreateAccountDeposit(0) B: 10
CreateAccountDeposit(1) C: 10
> batchL1
> batchL1
> block
`
tc := til.NewContext(common.RollupConstMaxL1UserTx)
blocks, err := tc.GenerateBlocks(set)
require.Nil(t, err)
ptc := ProcessTxsConfig{
NLevels: 32,
MaxFeeTx: 64,
MaxTx: 512,
MaxL1Tx: 16,
}
_, err = sdb.ProcessTxs(ptc, nil, blocks[0].Rollup.L1UserTxs, nil, nil)
require.Nil(t, err)
tx := common.L1Tx{
FromIdx: 256,
ToIdx: 257,
Amount: big.NewInt(10),
LoadAmount: big.NewInt(0),
FromEthAddr: tc.Users["A"].Addr,
UserOrigin: true,
}
sdb.computeEffectiveAmounts(&tx)
assert.Equal(t, big.NewInt(0), tx.EffectiveLoadAmount)
assert.Equal(t, big.NewInt(10), tx.EffectiveAmount)
// expect error due not enough funds
tx = common.L1Tx{
FromIdx: 256,
ToIdx: 257,
Amount: big.NewInt(11),
LoadAmount: big.NewInt(0),
FromEthAddr: tc.Users["A"].Addr,
UserOrigin: true,
}
sdb.computeEffectiveAmounts(&tx)
assert.Equal(t, big.NewInt(0), tx.EffectiveLoadAmount)
assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
// expect no-error due not enough funds in a
// CreateAccountDepositTransfer transction
tx = common.L1Tx{
FromIdx: 0,
ToIdx: 257,
Amount: big.NewInt(10),
LoadAmount: big.NewInt(10),
UserOrigin: true,
}
sdb.computeEffectiveAmounts(&tx)
assert.Equal(t, big.NewInt(10), tx.EffectiveLoadAmount)
assert.Equal(t, big.NewInt(10), tx.EffectiveAmount)
// expect error due not enough funds in a CreateAccountDepositTransfer
// transction
tx = common.L1Tx{
FromIdx: 0,
ToIdx: 257,
Amount: big.NewInt(11),
LoadAmount: big.NewInt(10),
UserOrigin: true,
}
sdb.computeEffectiveAmounts(&tx)
assert.Equal(t, big.NewInt(10), tx.EffectiveLoadAmount)
assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
// expect error due not same TokenID
tx = common.L1Tx{
FromIdx: 256,
ToIdx: 258,
Amount: big.NewInt(5),
LoadAmount: big.NewInt(0),
FromEthAddr: tc.Users["A"].Addr,
UserOrigin: true,
}
sdb.computeEffectiveAmounts(&tx)
assert.Equal(t, big.NewInt(0), tx.EffectiveLoadAmount)
assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
// expect error due not same EthAddr
tx = common.L1Tx{
FromIdx: 256,
ToIdx: 257,
Amount: big.NewInt(8),
LoadAmount: big.NewInt(0),
FromEthAddr: tc.Users["B"].Addr,
UserOrigin: true,
}
sdb.computeEffectiveAmounts(&tx)
assert.Equal(t, big.NewInt(0), tx.EffectiveLoadAmount)
assert.Equal(t, big.NewInt(0), tx.EffectiveAmount)
}
func TestProcessTxsBalances(t *testing.T) {
dir, err := ioutil.TempDir("", "tmpdb")
require.Nil(t, err)
@@ -139,7 +249,7 @@ func TestProcessTxsBalances(t *testing.T) {
require.Nil(t, err)
// use Set of PoolL2 txs
poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow0)
poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow1)
assert.Nil(t, err)
_, err = sdb.ProcessTxs(ptc, coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
@@ -452,6 +562,7 @@ func TestProcessTxsRootTestVectors(t *testing.T) {
FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
ToIdx: 0,
Type: common.TxTypeCreateAccountDeposit,
UserOrigin: true,
},
}
l2Txs := []common.PoolL2Tx{
@@ -499,6 +610,7 @@ func TestCircomTest(t *testing.T) {
FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
ToIdx: 0,
Type: common.TxTypeCreateAccountDeposit,
UserOrigin: true,
},
}
l2Txs := []common.PoolL2Tx{
@@ -564,8 +676,7 @@ func TestZKInputsHashTestVector0(t *testing.T) {
assert.Nil(t, err)
l1Txs := []common.L1Tx{
{
FromIdx: 0,
// LoadAmount: big.NewInt(10400),
FromIdx: 0,
LoadAmount: big.NewInt(16000000),
Amount: big.NewInt(0),
TokenID: 1,
@@ -573,6 +684,7 @@ func TestZKInputsHashTestVector0(t *testing.T) {
FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
ToIdx: 0,
Type: common.TxTypeCreateAccountDeposit,
UserOrigin: true,
},
}
l2Txs := []common.PoolL2Tx{
@@ -593,6 +705,10 @@ func TestZKInputsHashTestVector0(t *testing.T) {
MaxTx: 32,
MaxL1Tx: 16,
}
// skip first batch to do the test with BatchNum=1
_, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil)
require.Nil(t, err)
ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs)
require.Nil(t, err)
@@ -610,7 +726,7 @@ func TestZKInputsHashTestVector0(t *testing.T) {
toHash, err := ptOut.ZKInputs.ToHashGlobalData()
assert.Nil(t, err)
// value from js test vector
expectedToHash := "0000000000ff000000000100000000000000000000000000000000000000000000000000000000000000000015ba488d749f6b891d29d0bf3a72481ec812e4d4ecef2bf7a3fc64f3c010444200000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010003e87e00000100000000000000000000000000000000000000000000000000000000000000"
expectedToHash := "0000000000ff000000000100000000000000000000000000000000000000000000000000000000000000000015ba488d749f6b891d29d0bf3a72481ec812e4d4ecef2bf7a3fc64f3c010444200000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010003e87e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000001"
// checks are splitted to find the difference easier
assert.Equal(t, expectedToHash[:1000], hex.EncodeToString(toHash)[:1000])
assert.Equal(t, expectedToHash[1000:2000], hex.EncodeToString(toHash)[1000:2000])
@@ -619,7 +735,7 @@ func TestZKInputsHashTestVector0(t *testing.T) {
h, err := ptOut.ZKInputs.HashGlobalData()
require.Nil(t, err)
// value from js test vector
assert.Equal(t, "80757288244566854497474223360206077562032050734432637237701187686677568506", h.String())
assert.Equal(t, "4356692423721763303547321618014315464040324829724049399065961225345730555597", h.String())
}
func TestZKInputsHashTestVector1(t *testing.T) {
@@ -646,6 +762,7 @@ func TestZKInputsHashTestVector1(t *testing.T) {
FromEthAddr: ethCommon.HexToAddress("0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
ToIdx: 0,
Type: common.TxTypeCreateAccountDeposit,
UserOrigin: true,
},
{
FromIdx: 0,
@@ -656,6 +773,7 @@ func TestZKInputsHashTestVector1(t *testing.T) {
FromEthAddr: ethCommon.HexToAddress("0x2b5ad5c4795c026514f8317c7a215e218dccd6cf"),
ToIdx: 0,
Type: common.TxTypeCreateAccountDeposit,
UserOrigin: true,
},
}
l2Txs := []common.PoolL2Tx{
@@ -676,6 +794,10 @@ func TestZKInputsHashTestVector1(t *testing.T) {
MaxTx: 32,
MaxL1Tx: 16,
}
// skip first batch to do the test with BatchNum=1
_, err = sdb.ProcessTxs(ptc, nil, nil, nil, nil)
require.Nil(t, err)
ptOut, err := sdb.ProcessTxs(ptc, nil, l1Txs, nil, l2Txs)
require.Nil(t, err)
@@ -697,7 +819,7 @@ func TestZKInputsHashTestVector1(t *testing.T) {
toHash, err := ptOut.ZKInputs.ToHashGlobalData()
assert.Nil(t, err)
// value from js test vector
expectedToHash := "0000000000ff0000000001010000000000000000000000000000000000000000000000000000000000000000304a3f3aef4f416cca887aab7265227449077627138345c2eb25bf8ff946b09500000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d00000000000028a00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010000010003e88900000101000000000000000000000000000000000000000000000000000000000000"
expectedToHash := "0000000000ff0000000001010000000000000000000000000000000000000000000000000000000000000000304a3f3aef4f416cca887aab7265227449077627138345c2eb25bf8ff946b09500000000000000000000000000000000000000000000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d700000000000028a00000000000010000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf093985b1993d9f743f9d7d943ed56f38601cb8b196db025f79650c4007c3054d00000000000028a000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010000010003e889000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000000000001"
// checks are splitted to find the difference easier
assert.Equal(t, expectedToHash[:1000], hex.EncodeToString(toHash)[:1000])
assert.Equal(t, expectedToHash[1000:2000], hex.EncodeToString(toHash)[1000:2000])
@@ -706,5 +828,5 @@ func TestZKInputsHashTestVector1(t *testing.T) {
h, err := ptOut.ZKInputs.HashGlobalData()
require.Nil(t, err)
// value from js test vector
assert.Equal(t, "10900521462378877053056992084240080637954406133884857263674494661625916419481", h.String())
assert.Equal(t, "20293112365009290386650039345314592436395562810005523677125576447132206192598", h.String())
}