mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-06 19:06:42 +01:00
Add account_update SQL table with balances and nonces
This commit is contained in:
@@ -27,6 +27,9 @@ type TxProcessor struct {
|
||||
// AccumulatedFees contains the accumulated fees for each token (Coord
|
||||
// Idx) in the processed batch
|
||||
AccumulatedFees map[common.Idx]*big.Int
|
||||
// updatedAccounts stores the last version of the account when it has
|
||||
// been created/updated by any of the processed transactions.
|
||||
updatedAccounts map[common.Idx]*common.Account
|
||||
config Config
|
||||
}
|
||||
|
||||
@@ -55,6 +58,9 @@ type ProcessTxOutput struct {
|
||||
CreatedAccounts []common.Account
|
||||
CoordinatorIdxsMap map[common.TokenID]common.Idx
|
||||
CollectedFees map[common.TokenID]*big.Int
|
||||
// UpdatedAccounts returns the current state of each account
|
||||
// created/updated by any of the processed transactions.
|
||||
UpdatedAccounts map[common.Idx]*common.Account
|
||||
}
|
||||
|
||||
func newErrorNotEnoughBalance(tx common.Tx) error {
|
||||
@@ -127,6 +133,10 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
||||
return nil, tracerr.Wrap(fmt.Errorf("L1UserTx + L1CoordinatorTx (%d) can not be bigger than MaxL1Tx (%d)", len(l1usertxs)+len(l1coordinatortxs), tp.config.MaxTx))
|
||||
}
|
||||
|
||||
if tp.s.Type() == statedb.TypeSynchronizer {
|
||||
tp.updatedAccounts = make(map[common.Idx]*common.Account)
|
||||
}
|
||||
|
||||
exits := make([]processedExit, nTx)
|
||||
|
||||
if tp.s.Type() == statedb.TypeBatchBuilder {
|
||||
@@ -382,7 +392,7 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
||||
tp.zki.EthAddr3[iFee] = common.EthAddrToBigInt(accCoord.EthAddr)
|
||||
}
|
||||
accCoord.Balance = new(big.Int).Add(accCoord.Balance, accumulatedFee)
|
||||
pFee, err := tp.s.UpdateAccount(idx, accCoord)
|
||||
pFee, err := tp.updateAccount(idx, accCoord)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil, tracerr.Wrap(err)
|
||||
@@ -439,7 +449,7 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
||||
}
|
||||
}
|
||||
|
||||
// retuTypeexitInfos, createdAccounts and collectedFees, so Synchronizer will
|
||||
// retun exitInfos, createdAccounts and collectedFees, so Synchronizer will
|
||||
// be able to store it into HistoryDB for the concrete BatchNum
|
||||
return &ProcessTxOutput{
|
||||
ZKInputs: nil,
|
||||
@@ -447,6 +457,7 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
||||
CreatedAccounts: createdAccounts,
|
||||
CoordinatorIdxsMap: coordIdxsMap,
|
||||
CollectedFees: collectedFees,
|
||||
UpdatedAccounts: tp.updatedAccounts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -741,7 +752,7 @@ func (tp *TxProcessor) applyCreateAccount(tx *common.L1Tx) error {
|
||||
EthAddr: tx.FromEthAddr,
|
||||
}
|
||||
|
||||
p, err := tp.s.CreateAccount(common.Idx(tp.s.CurrentIdx()+1), account)
|
||||
p, err := tp.createAccount(common.Idx(tp.s.CurrentIdx()+1), account)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@@ -776,6 +787,28 @@ func (tp *TxProcessor) applyCreateAccount(tx *common.L1Tx) error {
|
||||
return tp.s.SetCurrentIdx(tp.s.CurrentIdx() + 1)
|
||||
}
|
||||
|
||||
// createAccount is a wrapper over the StateDB.CreateAccount method that also
|
||||
// stores the created account in the updatedAccounts map in case the StateDB is
|
||||
// of TypeSynchronizer
|
||||
func (tp *TxProcessor) createAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
if tp.s.Type() == statedb.TypeSynchronizer {
|
||||
account.Idx = idx
|
||||
tp.updatedAccounts[idx] = account
|
||||
}
|
||||
return tp.s.CreateAccount(idx, account)
|
||||
}
|
||||
|
||||
// updateAccount is a wrapper over the StateDB.UpdateAccount method that also
|
||||
// stores the updated account in the updatedAccounts map in case the StateDB is
|
||||
// of TypeSynchronizer
|
||||
func (tp *TxProcessor) updateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
if tp.s.Type() == statedb.TypeSynchronizer {
|
||||
account.Idx = idx
|
||||
tp.updatedAccounts[idx] = account
|
||||
}
|
||||
return tp.s.UpdateAccount(idx, account)
|
||||
}
|
||||
|
||||
// applyDeposit updates the balance in the account of the depositer, if
|
||||
// andTransfer parameter is set to true, the method will also apply the
|
||||
// Transfer of the L1Tx/DepositTransfer
|
||||
@@ -806,7 +839,7 @@ func (tp *TxProcessor) applyDeposit(tx *common.L1Tx, transfer bool) error {
|
||||
}
|
||||
|
||||
// update sender account in localStateDB
|
||||
p, err := tp.s.UpdateAccount(tx.FromIdx, accSender)
|
||||
p, err := tp.updateAccount(tx.FromIdx, accSender)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@@ -843,7 +876,7 @@ func (tp *TxProcessor) applyDeposit(tx *common.L1Tx, transfer bool) error {
|
||||
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
|
||||
|
||||
// update receiver account in localStateDB
|
||||
p, err := tp.s.UpdateAccount(tx.ToIdx, accReceiver)
|
||||
p, err := tp.updateAccount(tx.ToIdx, accReceiver)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@@ -926,7 +959,7 @@ func (tp *TxProcessor) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx,
|
||||
}
|
||||
|
||||
// update sender account in localStateDB
|
||||
pSender, err := tp.s.UpdateAccount(tx.FromIdx, accSender)
|
||||
pSender, err := tp.updateAccount(tx.FromIdx, accSender)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return tracerr.Wrap(err)
|
||||
@@ -965,7 +998,7 @@ func (tp *TxProcessor) applyTransfer(coordIdxsMap map[common.TokenID]common.Idx,
|
||||
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.Amount)
|
||||
|
||||
// update receiver account in localStateDB
|
||||
pReceiver, err := tp.s.UpdateAccount(auxToIdx, accReceiver)
|
||||
pReceiver, err := tp.updateAccount(auxToIdx, accReceiver)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@@ -1008,7 +1041,7 @@ func (tp *TxProcessor) applyCreateAccountDepositTransfer(tx *common.L1Tx) error
|
||||
}
|
||||
|
||||
// create Account of the Sender
|
||||
p, err := tp.s.CreateAccount(common.Idx(tp.s.CurrentIdx()+1), accSender)
|
||||
p, err := tp.createAccount(common.Idx(tp.s.CurrentIdx()+1), accSender)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@@ -1056,7 +1089,7 @@ func (tp *TxProcessor) applyCreateAccountDepositTransfer(tx *common.L1Tx) error
|
||||
accReceiver.Balance = new(big.Int).Add(accReceiver.Balance, tx.EffectiveAmount)
|
||||
|
||||
// update receiver account in localStateDB
|
||||
p, err = tp.s.UpdateAccount(tx.ToIdx, accReceiver)
|
||||
p, err = tp.updateAccount(tx.ToIdx, accReceiver)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@@ -1130,7 +1163,7 @@ func (tp *TxProcessor) applyExit(coordIdxsMap map[common.TokenID]common.Idx,
|
||||
}
|
||||
}
|
||||
|
||||
p, err := tp.s.UpdateAccount(tx.FromIdx, acc)
|
||||
p, err := tp.updateAccount(tx.FromIdx, acc)
|
||||
if err != nil {
|
||||
return nil, false, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
@@ -1006,3 +1007,103 @@ func TestExitOf0Amount(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "0", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
|
||||
}
|
||||
|
||||
func TestUpdatedAccounts(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "tmpdb")
|
||||
require.NoError(t, err)
|
||||
defer assert.NoError(t, os.RemoveAll(dir))
|
||||
|
||||
sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128,
|
||||
Type: statedb.TypeSynchronizer, NLevels: 32})
|
||||
assert.NoError(t, err)
|
||||
|
||||
set := `
|
||||
Type: Blockchain
|
||||
AddToken(1)
|
||||
CreateAccountCoordinator(0) Coord // 256
|
||||
CreateAccountCoordinator(1) Coord // 257
|
||||
> batch // 1
|
||||
CreateAccountDeposit(0) A: 50 // 258
|
||||
CreateAccountDeposit(0) B: 60 // 259
|
||||
CreateAccountDeposit(1) A: 70 // 260
|
||||
CreateAccountDeposit(1) B: 80 // 261
|
||||
> batchL1 // 2
|
||||
> batchL1 // 3
|
||||
Transfer(0) A-B: 5 (126)
|
||||
> batch // 4
|
||||
Exit(1) B: 5 (126)
|
||||
> batch // 5
|
||||
> block
|
||||
`
|
||||
|
||||
chainID := uint16(0)
|
||||
tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
|
||||
blocks, err := tc.GenerateBlocks(set)
|
||||
require.NoError(t, err)
|
||||
tilCfgExtra := til.ConfigExtra{
|
||||
BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
|
||||
CoordUser: "Coord",
|
||||
}
|
||||
err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
|
||||
require.NoError(t, err)
|
||||
tc.FillBlocksL1UserTxsBatchNum(blocks)
|
||||
err = tc.FillBlocksForgedL1UserTxs(blocks)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, 5, len(blocks[0].Rollup.Batches))
|
||||
|
||||
config := Config{
|
||||
NLevels: 32,
|
||||
MaxFeeTx: 64,
|
||||
MaxTx: 512,
|
||||
MaxL1Tx: 16,
|
||||
ChainID: chainID,
|
||||
}
|
||||
tp := NewTxProcessor(sdb, config)
|
||||
|
||||
sortedKeys := func(m map[common.Idx]*common.Account) []int {
|
||||
keys := make([]int, 0)
|
||||
for k := range m {
|
||||
keys = append(keys, int(k))
|
||||
}
|
||||
sort.Ints(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
for _, batch := range blocks[0].Rollup.Batches {
|
||||
l2Txs := common.L2TxsToPoolL2Txs(batch.L2Txs)
|
||||
ptOut, err := tp.ProcessTxs(batch.Batch.FeeIdxsCoordinator, batch.L1UserTxs,
|
||||
batch.L1CoordinatorTxs, l2Txs)
|
||||
require.NoError(t, err)
|
||||
switch batch.Batch.BatchNum {
|
||||
case 1:
|
||||
assert.Equal(t, 2, len(ptOut.UpdatedAccounts))
|
||||
assert.Equal(t, []int{256, 257}, sortedKeys(ptOut.UpdatedAccounts))
|
||||
case 2:
|
||||
assert.Equal(t, 0, len(ptOut.UpdatedAccounts))
|
||||
assert.Equal(t, []int{}, sortedKeys(ptOut.UpdatedAccounts))
|
||||
case 3:
|
||||
assert.Equal(t, 4, len(ptOut.UpdatedAccounts))
|
||||
assert.Equal(t, []int{258, 259, 260, 261}, sortedKeys(ptOut.UpdatedAccounts))
|
||||
case 4:
|
||||
assert.Equal(t, 2+1, len(ptOut.UpdatedAccounts))
|
||||
assert.Equal(t, []int{256, 258, 259}, sortedKeys(ptOut.UpdatedAccounts))
|
||||
case 5:
|
||||
assert.Equal(t, 1+1, len(ptOut.UpdatedAccounts))
|
||||
assert.Equal(t, []int{257, 261}, sortedKeys(ptOut.UpdatedAccounts))
|
||||
}
|
||||
for idx, updAcc := range ptOut.UpdatedAccounts {
|
||||
acc, err := sdb.GetAccount(idx)
|
||||
require.NoError(t, err)
|
||||
// If acc.Balance is 0, set it to 0 with big.NewInt so
|
||||
// that the comparison succeeds. Without this, the
|
||||
// comparison will not succeed because acc.Balance is
|
||||
// set from a slice, and thus the internal big.Int
|
||||
// buffer is not nil (big.Int.abs)
|
||||
if acc.Balance.BitLen() == 0 {
|
||||
acc.Balance = big.NewInt(0)
|
||||
}
|
||||
assert.Equal(t, acc, updAcc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user