mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-06 19:06:42 +01:00
Add ProcessTxs send fees to Coordinator accounts
This commit is contained in:
@@ -51,8 +51,8 @@ func (bb *BatchBuilder) Reset(batchNum common.BatchNum, fromSynchronizer bool) e
|
||||
}
|
||||
|
||||
// BuildBatch takes the transactions and returns the common.ZKInputs of the next batch
|
||||
func (bb *BatchBuilder) BuildBatch(configBatch *ConfigBatch, l1usertxs, l1coordinatortxs []common.L1Tx, pooll2txs []common.PoolL2Tx, tokenIDs []common.TokenID) (*common.ZKInputs, error) {
|
||||
zkInputs, _, err := bb.localStateDB.ProcessTxs(l1usertxs, l1coordinatortxs, pooll2txs)
|
||||
func (bb *BatchBuilder) BuildBatch(coordIdxs []common.Idx, configBatch *ConfigBatch, l1usertxs, l1coordinatortxs []common.L1Tx, pooll2txs []common.PoolL2Tx, tokenIDs []common.TokenID) (*common.ZKInputs, error) {
|
||||
zkInputs, _, err := bb.localStateDB.ProcessTxs(coordIdxs, l1usertxs, l1coordinatortxs, pooll2txs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func NewL1Tx(l1Tx *L1Tx) (*L1Tx, error) {
|
||||
if l1Tx.ToIdx == Idx(0) {
|
||||
txType = TxTypeDeposit
|
||||
} else if l1Tx.ToIdx == Idx(1) {
|
||||
txType = TxTypeExit
|
||||
txType = TxTypeForceExit
|
||||
} else if l1Tx.ToIdx >= IdxUserThreshold {
|
||||
if l1Tx.LoadAmount.Int64() == int64(0) {
|
||||
txType = TxTypeForceTransfer
|
||||
|
||||
@@ -250,6 +250,7 @@ func (tx PoolL2Tx) Tx() Tx {
|
||||
FromIdx: tx.FromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
Amount: tx.Amount,
|
||||
TokenID: tx.TokenID,
|
||||
Nonce: &tx.Nonce,
|
||||
Fee: &tx.Fee,
|
||||
Type: tx.Type,
|
||||
|
||||
28
common/tx.go
28
common/tx.go
@@ -1,6 +1,7 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql/driver"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
@@ -145,6 +146,33 @@ type Tx struct {
|
||||
Nonce *Nonce `meddler:"nonce"`
|
||||
}
|
||||
|
||||
func (tx *Tx) String() string {
|
||||
buf := bytes.NewBufferString("")
|
||||
fmt.Fprintf(buf, "Type: %s, ", tx.Type)
|
||||
fmt.Fprintf(buf, "FromIdx: %s, ", tx.FromIdx)
|
||||
if tx.Type == TxTypeTransfer ||
|
||||
tx.Type == TxTypeDepositTransfer ||
|
||||
tx.Type == TxTypeCreateAccountDepositTransfer {
|
||||
fmt.Fprintf(buf, "ToIdx: %s, ", tx.ToIdx)
|
||||
}
|
||||
if tx.Type == TxTypeDeposit ||
|
||||
tx.Type == TxTypeDepositTransfer ||
|
||||
tx.Type == TxTypeCreateAccountDepositTransfer {
|
||||
fmt.Fprintf(buf, "LoadAmount: %d, ", tx.LoadAmount)
|
||||
}
|
||||
if tx.Type != TxTypeDeposit {
|
||||
fmt.Fprintf(buf, "Amount: %s, ", tx.Amount)
|
||||
}
|
||||
if tx.Type == TxTypeTransfer ||
|
||||
tx.Type == TxTypeDepositTransfer ||
|
||||
tx.Type == TxTypeCreateAccountDepositTransfer {
|
||||
fmt.Fprintf(buf, "Fee: %d, ", tx.Fee)
|
||||
}
|
||||
fmt.Fprintf(buf, "TokenID: %d\n", tx.TokenID)
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// L1Tx returns a *L1Tx from the Tx
|
||||
func (tx *Tx) L1Tx() (*L1Tx, error) {
|
||||
return &L1Tx{
|
||||
|
||||
@@ -214,13 +214,13 @@ func (c *Coordinator) forge(serverProof ServerProofInterface) (*BatchInfo, error
|
||||
// 2a: L1+L2 txs
|
||||
// l1UserTxs, toForgeL1TxsNumber := c.hdb.GetNextL1UserTxs() // TODO once HistoryDB is ready, uncomment
|
||||
var l1UserTxs []common.L1Tx = nil // tmp, depends on HistoryDB
|
||||
l1UserTxsExtra, l1OperatorTxs, poolL2Txs, err = c.txsel.GetL1L2TxSelection(c.batchNum, l1UserTxs) // TODO once feesInfo is added to method return, add the var
|
||||
l1UserTxsExtra, l1OperatorTxs, poolL2Txs, err = c.txsel.GetL1L2TxSelection([]common.Idx{}, c.batchNum, l1UserTxs) // TODO once feesInfo is added to method return, add the var
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// 2b: only L2 txs
|
||||
poolL2Txs, err = c.txsel.GetL2TxSelection(c.batchNum) // TODO once feesInfo is added to method return, add the var
|
||||
poolL2Txs, err = c.txsel.GetL2TxSelection([]common.Idx{}, c.batchNum) // TODO once feesInfo is added to method return, add the var
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -244,7 +244,7 @@ func (c *Coordinator) forge(serverProof ServerProofInterface) (*BatchInfo, error
|
||||
configBatch := &batchbuilder.ConfigBatch{
|
||||
ForgerAddress: c.config.ForgerAddress,
|
||||
}
|
||||
zkInputs, err := c.batchBuilder.BuildBatch(configBatch, l1UserTxsExtra, l1OperatorTxs, poolL2Txs, nil) // TODO []common.TokenID --> feesInfo
|
||||
zkInputs, err := c.batchBuilder.BuildBatch([]common.Idx{}, configBatch, l1UserTxsExtra, l1OperatorTxs, poolL2Txs, nil) // TODO []common.TokenID --> feesInfo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ type processedExit struct {
|
||||
// type==TypeSynchronizer, assumes that the call is done from the Synchronizer,
|
||||
// returns common.ExitTreeLeaf that is later used by the Synchronizer to update
|
||||
// the HistoryDB, and adds Nonce & TokenID to the L2Txs.
|
||||
func (s *StateDB) ProcessTxs(l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []common.PoolL2Tx) (*common.ZKInputs, []common.ExitInfo, error) {
|
||||
func (s *StateDB) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []common.PoolL2Tx) (*common.ZKInputs, []common.ExitInfo, error) {
|
||||
var err error
|
||||
var exitTree *merkletree.MerkleTree
|
||||
|
||||
@@ -54,6 +54,12 @@ func (s *StateDB) ProcessTxs(l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []
|
||||
}
|
||||
exits := make([]processedExit, nTx)
|
||||
|
||||
// get TokenIDs of coordIdxs
|
||||
coordIdxsMap, err := s.getTokenIDsFromIdxs(coordIdxs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if s.typ == TypeBatchBuilder {
|
||||
s.zki = common.NewZKInputs(nTx, 24, 32) // TODO this values will be parameters of the function, taken from config file/coordinator call
|
||||
s.zki.OldLastIdx = (s.idx - 1).BigInt()
|
||||
@@ -121,7 +127,7 @@ func (s *StateDB) ProcessTxs(l1usertxs, l1coordinatortxs []common.L1Tx, l2txs []
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(l2txs); i++ {
|
||||
exitIdx, exitAccount, newExit, err := s.processL2Tx(exitTree, &l2txs[i])
|
||||
exitIdx, exitAccount, newExit, err := s.processL2Tx(coordIdxsMap, exitTree, &l2txs[i])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -258,10 +264,13 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
|
||||
}
|
||||
|
||||
switch tx.Type {
|
||||
case common.TxTypeForceTransfer, common.TxTypeTransfer:
|
||||
case common.TxTypeForceTransfer:
|
||||
// go to the MT account of sender and receiver, and update balance
|
||||
// & nonce
|
||||
err := s.applyTransfer(tx.Tx(), 0) // 0 for the parameter toIdx, as at L1Tx ToIdx can only be 0 in the Deposit type case.
|
||||
|
||||
// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees
|
||||
// 0 for the parameter toIdx, as at L1Tx ToIdx can only be 0 in the Deposit type case.
|
||||
err := s.applyTransfer(nil, tx.Tx(), 0)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, nil, false, err
|
||||
@@ -309,9 +318,10 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
|
||||
s.zki.AuxFromIdx[s.i] = s.idx.BigInt() // last s.idx is the one used for creating the new account
|
||||
s.zki.NewAccount[s.i] = big.NewInt(1)
|
||||
}
|
||||
case common.TxTypeExit:
|
||||
case common.TxTypeForceExit:
|
||||
// execute exit flow
|
||||
exitAccount, newExit, err := s.applyExit(exitTree, tx.Tx())
|
||||
// coordIdxsMap is 'nil', as at L1Txs there is no L2 fees
|
||||
exitAccount, newExit, err := s.applyExit(nil, exitTree, tx.Tx())
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, nil, false, err
|
||||
@@ -327,7 +337,7 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
|
||||
// StateDB depending on the transaction Type. It returns the 3 parameters
|
||||
// related to the Exit (in case of): Idx, ExitAccount, boolean determining if
|
||||
// the Exit created a new Leaf in the ExitTree.
|
||||
func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2Tx) (*common.Idx, *common.Account, bool, error) {
|
||||
func (s *StateDB) processL2Tx(coordIdxsMap map[common.TokenID]common.Idx, exitTree *merkletree.MerkleTree, tx *common.PoolL2Tx) (*common.Idx, *common.Account, bool, error) {
|
||||
var err error
|
||||
// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
|
||||
if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
|
||||
@@ -394,14 +404,14 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
||||
case common.TxTypeTransfer, common.TxTypeTransferToEthAddr, common.TxTypeTransferToBJJ:
|
||||
// go to the MT account of sender and receiver, and update
|
||||
// balance & nonce
|
||||
err = s.applyTransfer(tx.Tx(), tx.AuxToIdx)
|
||||
err = s.applyTransfer(coordIdxsMap, tx.Tx(), tx.AuxToIdx)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, nil, false, err
|
||||
}
|
||||
case common.TxTypeExit:
|
||||
// execute exit flow
|
||||
exitAccount, newExit, err := s.applyExit(exitTree, tx.Tx())
|
||||
exitAccount, newExit, err := s.applyExit(coordIdxsMap, exitTree, tx.Tx())
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, nil, false, err
|
||||
@@ -519,7 +529,7 @@ 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(tx common.Tx, auxToIdx common.Idx) error {
|
||||
func (s *StateDB) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx, tx common.Tx, auxToIdx common.Idx) error {
|
||||
if auxToIdx == common.Idx(0) {
|
||||
auxToIdx = tx.ToIdx
|
||||
}
|
||||
@@ -543,8 +553,18 @@ func (s *StateDB) applyTransfer(tx common.Tx, auxToIdx common.Idx) error {
|
||||
fee := common.CalcFeeAmount(tx.Amount, *tx.Fee)
|
||||
feeAndAmount := new(big.Int).Add(tx.Amount, fee)
|
||||
accSender.Balance = new(big.Int).Sub(accSender.Balance, feeAndAmount)
|
||||
// TODO send the fee to the Fee Idx of the Coordinator for the
|
||||
// TokenID
|
||||
// send the fee to the Idx of the Coordinator for the TokenID
|
||||
accCoord, err := s.GetAccount(coordIdxsMap[tx.TokenID])
|
||||
if err != nil {
|
||||
log.Errorf("applyTransfer error: Tx=%s, error: %s", tx.String(), err)
|
||||
return err
|
||||
}
|
||||
accCoord.Balance = new(big.Int).Add(accCoord.Balance, fee)
|
||||
_, err = s.UpdateAccount(coordIdxsMap[tx.TokenID], accCoord)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// add amount-feeAmount to the receiver
|
||||
@@ -653,7 +673,7 @@ 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(exitTree *merkletree.MerkleTree, tx common.Tx) (*common.Account, bool, error) {
|
||||
func (s *StateDB) applyExit(coordIdxsMap map[common.TokenID]common.Idx, 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)
|
||||
@@ -666,8 +686,19 @@ func (s *StateDB) applyExit(exitTree *merkletree.MerkleTree, tx common.Tx) (*com
|
||||
fee := common.CalcFeeAmount(tx.Amount, *tx.Fee)
|
||||
feeAndAmount := new(big.Int).Add(tx.Amount, fee)
|
||||
acc.Balance = new(big.Int).Sub(acc.Balance, feeAndAmount)
|
||||
// TODO send the fee to the Fee Idx of the Coordinator for the
|
||||
// TokenID
|
||||
|
||||
// send the fee to the Idx of the Coordinator for the TokenID
|
||||
accCoord, err := s.GetAccount(coordIdxsMap[tx.TokenID])
|
||||
if err != nil {
|
||||
log.Errorf("applyExit error: Tx=%s, error: %s", tx.String(), err)
|
||||
return nil, false, err
|
||||
}
|
||||
accCoord.Balance = new(big.Int).Add(accCoord.Balance, fee)
|
||||
_, err = s.UpdateAccount(coordIdxsMap[tx.TokenID], accCoord)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
p, err := s.UpdateAccount(tx.FromIdx, acc)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/eth"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/hermeznetwork/hermez-node/test/til"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -28,53 +29,74 @@ func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 29, len(blocks[0].L1UserTxs))
|
||||
assert.Equal(t, 0, len(blocks[0].Batches[0].L1CoordinatorTxs))
|
||||
assert.Equal(t, 21, len(blocks[0].Batches[1].L2Txs))
|
||||
assert.Equal(t, 31, len(blocks[0].L1UserTxs))
|
||||
assert.Equal(t, 4, len(blocks[0].Batches[0].L1CoordinatorTxs))
|
||||
assert.Equal(t, 0, len(blocks[0].Batches[1].L1CoordinatorTxs))
|
||||
assert.Equal(t, 22, len(blocks[0].Batches[2].L2Txs))
|
||||
assert.Equal(t, 1, len(blocks[1].Batches[0].L1CoordinatorTxs))
|
||||
assert.Equal(t, 59, len(blocks[1].Batches[0].L2Txs))
|
||||
assert.Equal(t, 1, len(blocks[1].Batches[1].L1CoordinatorTxs))
|
||||
assert.Equal(t, 8, len(blocks[1].Batches[1].L2Txs))
|
||||
|
||||
// use first batch
|
||||
l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[0].L2Txs)
|
||||
_, exitInfos, err := sdb.ProcessTxs(blocks[0].L1UserTxs, blocks[0].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
// Coordinator Idx where to send the fees
|
||||
coordIdxs := []common.Idx{256, 257, 258, 259}
|
||||
|
||||
// Idx of user 'A'
|
||||
idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
|
||||
|
||||
log.Debug("1st batch, 1st block, only L1CoordinatorTxs")
|
||||
_, _, err = sdb.ProcessTxs(nil, nil, blocks[0].Batches[0].L1CoordinatorTxs, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
log.Debug("2nd batch, 1st block")
|
||||
l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
|
||||
_, exitInfos, err := sdb.ProcessTxs(coordIdxs, blocks[0].L1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(exitInfos))
|
||||
acc, err := sdb.GetAccount(common.Idx(256))
|
||||
acc, err := sdb.GetAccount(idxA1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "50", acc.Balance.String())
|
||||
|
||||
// second batch of first block
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(nil, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
log.Debug("3rd batch, 1st block")
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(coordIdxs, nil, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
// TODO once TTGL is updated, add a check that a input poolL2Tx with
|
||||
// Nonce & TokenID =0, after ProcessTxs call has the expected value
|
||||
|
||||
assert.Equal(t, 0, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "28", acc.Balance.String())
|
||||
|
||||
// use second batch
|
||||
log.Debug("1st batch, 2nd block")
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[0].L2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(nil, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(coordIdxs, nil, blocks[1].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 4, len(exitInfos)) // the 'ForceExit(1)' is not computed yet, as the batch is without L1UserTxs
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "53", acc.Balance.String())
|
||||
|
||||
// use third batch
|
||||
log.Debug("2nd batch, 2nd block")
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Batches[1].L2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(blocks[1].L1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(coordIdxs, blocks[1].L1UserTxs, blocks[1].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(exitInfos)) // 2, as previous batch was without L1UserTxs, and has pending the 'ForceExit(1) A: 5'
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "78", acc.Balance.String())
|
||||
|
||||
idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
|
||||
acc, err = sdb.GetAccount(idxB0)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "51", acc.Balance.String())
|
||||
|
||||
// get balance of Coordinator account for TokenID==0
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "2", acc.Balance.String())
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -102,30 +124,33 @@ func TestProcessTxsBatchBuilder(t *testing.T) {
|
||||
assert.Equal(t, 0, len(blocks[0].Batches[2].L1CoordinatorTxs))
|
||||
assert.Equal(t, 8, len(blocks[0].Batches[2].L2Txs))
|
||||
|
||||
// Idx of user 'A'
|
||||
idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
|
||||
|
||||
// use first batch
|
||||
l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[0].L2Txs)
|
||||
_, exitInfos, err := sdb.ProcessTxs(blocks[0].Batches[0].L1UserTxs, blocks[0].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
_, exitInfos, err := sdb.ProcessTxs(coordIdxs, blocks[0].Batches[0].L1UserTxs, blocks[0].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(exitInfos))
|
||||
acc, err := sdb.GetAccount(common.Idx(256))
|
||||
acc, err := sdb.GetAccount(idxA1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "28", acc.Balance.String())
|
||||
|
||||
// use second batch
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[1].L2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(blocks[0].Batches[1].L1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(coordIdxs, blocks[0].Batches[1].L1UserTxs, blocks[0].Batches[1].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 5, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "48", acc.Balance.String())
|
||||
|
||||
// use third batch
|
||||
l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Batches[2].L2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(blocks[0].Batches[2].L1UserTxs, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
|
||||
_, exitInfos, err = sdb.ProcessTxs(coordIdxs, blocks[0].Batches[2].L1UserTxs, blocks[0].Batches[2].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 1, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(idxA1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "23", acc.Balance.String())
|
||||
}
|
||||
@@ -146,7 +171,7 @@ func TestZKInputsGeneration(t *testing.T) {
|
||||
assert.Equal(t, 21, len(blocks[0].Batches[0].L2Txs))
|
||||
|
||||
l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Batches[0].L2Txs)
|
||||
zki, _, err := sdb.ProcessTxs(blocks[0].Batches[0].L1UserTxs, blocks[0].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
zki, _, err := sdb.ProcessTxs(coordIdxs, blocks[0].Batches[0].L1UserTxs, blocks[0].Batches[0].L1CoordinatorTxs, l2Txs)
|
||||
require.Nil(t, err)
|
||||
|
||||
s, err := json.Marshal(zki)
|
||||
|
||||
@@ -2,6 +2,7 @@ package statedb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
@@ -108,6 +109,18 @@ func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicK
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
}
|
||||
|
||||
func (s *StateDB) getTokenIDsFromIdxs(idxs []common.Idx) (map[common.TokenID]common.Idx, error) {
|
||||
m := make(map[common.TokenID]common.Idx)
|
||||
for i := 0; i < len(idxs); i++ {
|
||||
a, err := s.GetAccount(idxs[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getTokenIDsFromIdxs error on GetAccount with Idx==%d: %s", idxs[i], err.Error())
|
||||
}
|
||||
m[a.TokenID] = idxs[i]
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func siblingsToZKInputFormat(s []*merkletree.Hash) []*big.Int {
|
||||
b := make([]*big.Int, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
|
||||
@@ -405,7 +405,7 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*rollupData, error) {
|
||||
// TODO: Get CollectedFees from ProcessTxs()
|
||||
// TODO: Pass forgeBatchArgs.FeeIdxCoordinator to ProcessTxs()
|
||||
// ProcessTxs updates poolL2Txs adding: Nonce, TokenID
|
||||
_, exitInfo, err := s.stateDB.ProcessTxs(l1UserTxs, batchData.L1CoordinatorTxs, poolL2Txs)
|
||||
_, exitInfo, err := s.stateDB.ProcessTxs([]common.Idx{}, l1UserTxs, batchData.L1CoordinatorTxs, poolL2Txs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestSync(t *testing.T) {
|
||||
CreateAccountDeposit(1) C: 5 // Idx=256+4
|
||||
CreateAccountDeposit(1) D: 5 // Idx=256+5
|
||||
|
||||
CreateAccountDepositCoordinator(2) B // Idx=256+0
|
||||
CreateAccountCoordinator(2) B // Idx=256+0
|
||||
|
||||
> batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs
|
||||
> batchL1 // forge defined L1UserTxs, freeze L1UserTxs{nil}
|
||||
|
||||
@@ -32,7 +32,7 @@ CreateAccountDepositTransfer(1) B-A: 40, 10
|
||||
|
||||
// transaction generated by the Coordinator, create account for user User0 for
|
||||
// the TokenID=2, with a deposit of 0
|
||||
CreateAccountDepositCoordinator(2) User0
|
||||
CreateAccountCoordinator(2) User0
|
||||
|
||||
|
||||
// deposit of TokenID=1, at the account A, of 6 units
|
||||
|
||||
@@ -350,7 +350,7 @@ func (p *parser) parseLine(setType setType) (*instruction, error) {
|
||||
case "CreateAccountDepositTransfer":
|
||||
c.typ = common.TxTypeCreateAccountDepositTransfer
|
||||
transferring = true
|
||||
case "CreateAccountDepositCoordinator":
|
||||
case "CreateAccountCoordinator":
|
||||
c.typ = txTypeCreateAccountDepositCoordinator
|
||||
// transferring is false, as the Coordinator tx transfer will be 0
|
||||
case "DepositTransfer":
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestParseBlockchainTxs(t *testing.T) {
|
||||
Deposit(1) B: 5
|
||||
CreateAccountDeposit(1) C: 5
|
||||
CreateAccountDepositTransfer(1) D-A: 15, 10
|
||||
CreateAccountDepositCoordinator(1) E
|
||||
CreateAccountCoordinator(1) E
|
||||
|
||||
// L2 transactions
|
||||
Transfer(1) A-B: 6 (1)
|
||||
|
||||
@@ -10,6 +10,14 @@ AddToken(1)
|
||||
AddToken(2)
|
||||
AddToken(3)
|
||||
|
||||
// Coordinator accounts, Idxs: 256, 257, 258, 259
|
||||
CreateAccountCoordinator(0) Coord
|
||||
CreateAccountCoordinator(1) Coord
|
||||
CreateAccountCoordinator(2) Coord
|
||||
CreateAccountCoordinator(3) Coord
|
||||
|
||||
> batch
|
||||
|
||||
// deposits TokenID: 1
|
||||
CreateAccountDeposit(1) A: 50
|
||||
CreateAccountDeposit(1) B: 5
|
||||
@@ -42,6 +50,9 @@ CreateAccountDeposit(2) B: 5
|
||||
CreateAccountDeposit(2) A: 20
|
||||
// deposits TokenID: 3
|
||||
CreateAccountDeposit(3) B: 100
|
||||
// deposits TokenID: 0
|
||||
CreateAccountDeposit(0) B: 10000
|
||||
CreateAccountDeposit(0) C: 1
|
||||
|
||||
> batchL1
|
||||
|
||||
@@ -67,11 +78,12 @@ Transfer(1) G-K: 3 (1)
|
||||
Transfer(1) H-K: 3 (2)
|
||||
Transfer(1) H-K: 3 (1)
|
||||
Transfer(1) H-K: 3 (1)
|
||||
Transfer(0) B-C: 50 (192)
|
||||
|
||||
> batchL1
|
||||
> block
|
||||
// A (3) still does not exist, coordinator should create new L1Tx to create the account
|
||||
CreateAccountDepositCoordinator(3) A
|
||||
CreateAccountCoordinator(3) A
|
||||
|
||||
Transfer(3) B-A: 5 (1)
|
||||
Transfer(2) A-B: 5 (1)
|
||||
@@ -156,7 +168,7 @@ Transfer(1) I-H: 5 (1)
|
||||
Exit(1) A: 5 (1)
|
||||
|
||||
// create CoordinatorTx CreateAccount for D, TokenId 2, used at SetPool0 for 'PoolTransfer(2) B-D: 3 (1)'
|
||||
CreateAccountDepositCoordinator(2) D
|
||||
CreateAccountCoordinator(2) D
|
||||
|
||||
> batchL1
|
||||
> batchL1
|
||||
|
||||
@@ -219,6 +219,26 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
||||
L2Tx: tx,
|
||||
}
|
||||
tc.currBatchTest.l2Txs = append(tc.currBatchTest.l2Txs, testTx)
|
||||
case common.TxTypeForceTransfer: // tx source: L1UserTx
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
log.Error(err)
|
||||
return nil, fmt.Errorf("Line %d: %s", inst.lineNum, err.Error())
|
||||
}
|
||||
tx := common.L1Tx{
|
||||
TokenID: inst.tokenID,
|
||||
Amount: big.NewInt(int64(inst.amount)),
|
||||
LoadAmount: big.NewInt(0),
|
||||
Type: common.TxTypeForceTransfer,
|
||||
}
|
||||
testTx := L1Tx{
|
||||
lineNum: inst.lineNum,
|
||||
fromIdxName: inst.from,
|
||||
toIdxName: inst.to,
|
||||
L1Tx: tx,
|
||||
}
|
||||
if err := tc.addToL1Queue(testTx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case common.TxTypeExit: // tx source: L2Tx
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
log.Error(err)
|
||||
@@ -248,7 +268,7 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
||||
TokenID: inst.tokenID,
|
||||
Amount: big.NewInt(int64(inst.amount)),
|
||||
LoadAmount: big.NewInt(0),
|
||||
Type: common.TxTypeExit,
|
||||
Type: common.TxTypeForceExit,
|
||||
}
|
||||
testTx := L1Tx{
|
||||
lineNum: inst.lineNum,
|
||||
@@ -415,7 +435,7 @@ func (tc *Context) addToL1Queue(tx L1Tx) error {
|
||||
}
|
||||
tx.L1Tx.ToIdx = account.Idx
|
||||
}
|
||||
if tx.L1Tx.Type == common.TxTypeExit {
|
||||
if tx.L1Tx.Type == common.TxTypeForceExit {
|
||||
tx.L1Tx.ToIdx = common.Idx(1)
|
||||
}
|
||||
nTx, err := common.NewL1Tx(&tx.L1Tx)
|
||||
|
||||
@@ -54,8 +54,8 @@ func TestGenerateBlocks(t *testing.T) {
|
||||
|
||||
// set new batch
|
||||
> batch // batchNum = 3
|
||||
CreateAccountDepositCoordinator(1) E
|
||||
CreateAccountDepositCoordinator(2) B
|
||||
CreateAccountCoordinator(1) E
|
||||
CreateAccountCoordinator(2) B
|
||||
|
||||
DepositTransfer(1) A-B: 15, 10
|
||||
Transfer(1) C-A : 3 (1)
|
||||
@@ -64,8 +64,8 @@ func TestGenerateBlocks(t *testing.T) {
|
||||
|
||||
CreateAccountDeposit(1) User0: 20
|
||||
CreateAccountDeposit(3) User1: 20
|
||||
CreateAccountDepositCoordinator(1) User1
|
||||
CreateAccountDepositCoordinator(3) User0
|
||||
CreateAccountCoordinator(1) User1
|
||||
CreateAccountCoordinator(3) User0
|
||||
> batchL1 // batchNum = 4
|
||||
Transfer(1) User0-User1: 15 (1)
|
||||
Transfer(3) User1-User0: 15 (1)
|
||||
@@ -329,7 +329,7 @@ func TestGenerateErrors(t *testing.T) {
|
||||
AddToken(1)
|
||||
CreateAccountDeposit(1) A: 10
|
||||
> batchL1
|
||||
CreateAccountDepositCoordinator(1) B
|
||||
CreateAccountCoordinator(1) B
|
||||
> batchL1
|
||||
> batch
|
||||
Transfer(1) A-B: 6 (1)
|
||||
@@ -345,7 +345,7 @@ func TestGenerateErrors(t *testing.T) {
|
||||
AddToken(1)
|
||||
CreateAccountDeposit(1) A: 10
|
||||
> batchL1
|
||||
CreateAccountDepositCoordinator(1) B
|
||||
CreateAccountCoordinator(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, Til should not fail
|
||||
|
||||
@@ -68,7 +68,7 @@ func (txsel *TxSelector) Reset(batchNum common.BatchNum) error {
|
||||
}
|
||||
|
||||
// GetL2TxSelection returns a selection of the L2Txs for the next batch, from the L2DB pool
|
||||
func (txsel *TxSelector) GetL2TxSelection(batchNum common.BatchNum) ([]common.PoolL2Tx, error) {
|
||||
func (txsel *TxSelector) GetL2TxSelection(coordIdxs []common.Idx, batchNum common.BatchNum) ([]common.PoolL2Tx, error) {
|
||||
// get pending l2-tx from tx-pool
|
||||
l2TxsRaw, err := txsel.l2db.GetPendingTxs() // once l2db ready, maybe use parameter 'batchNum'
|
||||
if err != nil {
|
||||
@@ -89,7 +89,7 @@ func (txsel *TxSelector) GetL2TxSelection(batchNum common.BatchNum) ([]common.Po
|
||||
txs := txsel.getL2Profitable(validTxs, txsel.MaxTxs)
|
||||
|
||||
// process the txs in the local AccountsDB
|
||||
_, _, err = txsel.localAccountsDB.ProcessTxs(nil, nil, txs)
|
||||
_, _, err = txsel.localAccountsDB.ProcessTxs(coordIdxs, nil, nil, txs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func (txsel *TxSelector) GetL2TxSelection(batchNum common.BatchNum) ([]common.Po
|
||||
}
|
||||
|
||||
// GetL1L2TxSelection returns the selection of L1 + L2 txs
|
||||
func (txsel *TxSelector) GetL1L2TxSelection(batchNum common.BatchNum, l1Txs []common.L1Tx) ([]common.L1Tx, []common.L1Tx, []common.PoolL2Tx, error) {
|
||||
func (txsel *TxSelector) GetL1L2TxSelection(coordIdxs []common.Idx, batchNum common.BatchNum, l1Txs []common.L1Tx) ([]common.L1Tx, []common.L1Tx, []common.PoolL2Tx, error) {
|
||||
// apply l1-user-tx to localAccountDB
|
||||
// create new leaves
|
||||
// update balances
|
||||
@@ -238,7 +238,7 @@ func (txsel *TxSelector) GetL1L2TxSelection(batchNum common.BatchNum, l1Txs []co
|
||||
l2Txs := txsel.getL2Profitable(validTxs, maxL2Txs)
|
||||
|
||||
// process the txs in the local AccountsDB
|
||||
_, _, err = txsel.localAccountsDB.ProcessTxs(l1Txs, l1CoordinatorTxs, l2Txs)
|
||||
_, _, err = txsel.localAccountsDB.ProcessTxs(coordIdxs, l1Txs, l1CoordinatorTxs, l2Txs)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user