mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-06 19:06:42 +01:00
Merge pull request #553 from hermeznetwork/fix/exit-amount-0
Txs w/ exit Amount=0,to not create new Exit leafs
This commit is contained in:
@@ -198,7 +198,7 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
||||
}
|
||||
}
|
||||
if tp.s.Type() == statedb.TypeSynchronizer || tp.s.Type() == statedb.TypeBatchBuilder {
|
||||
if exitIdx != nil && exitTree != nil {
|
||||
if exitIdx != nil && exitTree != nil && exitAccount != nil {
|
||||
exits[tp.i] = processedExit{
|
||||
exit: true,
|
||||
newExit: newExit,
|
||||
@@ -407,38 +407,38 @@ func (tp *TxProcessor) ProcessTxs(coordIdxs []common.Idx, l1usertxs, l1coordinat
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// once all txs processed (exitTree root frozen), for each Exit,
|
||||
// generate common.ExitInfo data
|
||||
var exitInfos []common.ExitInfo
|
||||
exitInfosByIdx := make(map[common.Idx]*common.ExitInfo)
|
||||
for i := 0; i < nTx; i++ {
|
||||
if !exits[i].exit {
|
||||
continue
|
||||
}
|
||||
exitIdx := exits[i].idx
|
||||
exitAccount := exits[i].acc
|
||||
|
||||
// 0. generate MerkleProof
|
||||
p, err := exitTree.GenerateSCVerifierProof(exitIdx.BigInt(), nil)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// 1. generate common.ExitInfo
|
||||
ei := common.ExitInfo{
|
||||
AccountIdx: exitIdx,
|
||||
MerkleProof: p,
|
||||
Balance: exitAccount.Balance,
|
||||
}
|
||||
if prevExit, ok := exitInfosByIdx[exitIdx]; !ok {
|
||||
exitInfos = append(exitInfos, ei)
|
||||
exitInfosByIdx[exitIdx] = &exitInfos[len(exitInfos)-1]
|
||||
} else {
|
||||
*prevExit = ei
|
||||
}
|
||||
}
|
||||
|
||||
if tp.s.Type() == statedb.TypeSynchronizer {
|
||||
// once all txs processed (exitTree root frozen), for each Exit,
|
||||
// generate common.ExitInfo data
|
||||
var exitInfos []common.ExitInfo
|
||||
exitInfosByIdx := make(map[common.Idx]*common.ExitInfo)
|
||||
for i := 0; i < nTx; i++ {
|
||||
if !exits[i].exit {
|
||||
continue
|
||||
}
|
||||
exitIdx := exits[i].idx
|
||||
exitAccount := exits[i].acc
|
||||
|
||||
// 0. generate MerkleProof
|
||||
p, err := exitTree.GenerateSCVerifierProof(exitIdx.BigInt(), nil)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// 1. generate common.ExitInfo
|
||||
ei := common.ExitInfo{
|
||||
AccountIdx: exitIdx,
|
||||
MerkleProof: p,
|
||||
Balance: exitAccount.Balance,
|
||||
}
|
||||
if prevExit, ok := exitInfosByIdx[exitIdx]; !ok {
|
||||
exitInfos = append(exitInfos, ei)
|
||||
exitInfosByIdx[exitIdx] = &exitInfos[len(exitInfos)-1]
|
||||
} else {
|
||||
*prevExit = ei
|
||||
}
|
||||
}
|
||||
|
||||
// retuTypeexitInfos, createdAccounts and collectedFees, so Synchronizer will
|
||||
// be able to store it into HistoryDB for the concrete BatchNum
|
||||
return &ProcessTxOutput{
|
||||
@@ -1141,6 +1141,11 @@ func (tp *TxProcessor) applyExit(coordIdxsMap map[common.TokenID]common.Idx,
|
||||
if exitTree == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
if tx.Amount.Cmp(big.NewInt(0)) == 0 { // Amount == 0
|
||||
// if the Exit Amount==0, the Exit is not added to the ExitTree
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
exitAccount, err := statedb.GetAccountInTreeDB(exitTree.DB(), tx.FromIdx)
|
||||
if tracerr.Unwrap(err) == db.ErrNotFound {
|
||||
// 1a. if idx does not exist in exitTree:
|
||||
|
||||
@@ -911,3 +911,98 @@ func TestTwoExits(t *testing.T) {
|
||||
|
||||
assert.Equal(t, ptOuts[3].ExitInfos[0].MerkleProof, ptOuts2[3].ExitInfos[0].MerkleProof)
|
||||
}
|
||||
|
||||
func TestExitOf0Amount(t *testing.T) {
|
||||
// Test to check that when doing an Exit with amount 0 the Exit Root
|
||||
// does not change (as there is no new Exit Leaf created)
|
||||
|
||||
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.TypeBatchBuilder, NLevels: 32})
|
||||
assert.NoError(t, err)
|
||||
|
||||
chainID := uint16(1)
|
||||
|
||||
tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
|
||||
|
||||
set := `
|
||||
Type: Blockchain
|
||||
|
||||
CreateAccountDeposit(0) A: 100
|
||||
CreateAccountDeposit(0) B: 100
|
||||
|
||||
> batchL1 // batch1: freeze L1User{2}
|
||||
> batchL1 // batch2: forge L1User{2}
|
||||
|
||||
ForceExit(0) A: 10
|
||||
ForceExit(0) B: 0
|
||||
|
||||
> batchL1 // batch3: freeze L1User{2}
|
||||
> batchL1 // batch4: forge L1User{2}
|
||||
|
||||
ForceExit(0) A: 10
|
||||
|
||||
> batchL1 // batch5: freeze L1User{1}
|
||||
> batchL1 // batch6: forge L1User{1}
|
||||
|
||||
ForceExit(0) A: 0
|
||||
> batchL1 // batch7: freeze L1User{1}
|
||||
> batchL1 // batch8: forge L1User{1}
|
||||
> block
|
||||
`
|
||||
blocks, err := tc.GenerateBlocks(set)
|
||||
require.NoError(t, err)
|
||||
err = tc.FillBlocksExtra(blocks, &til.ConfigExtra{})
|
||||
require.NoError(t, err)
|
||||
err = tc.FillBlocksForgedL1UserTxs(blocks)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Sanity check
|
||||
require.Equal(t, 2, len(blocks[0].Rollup.Batches[1].L1UserTxs))
|
||||
require.Equal(t, 2, len(blocks[0].Rollup.Batches[3].L1UserTxs))
|
||||
require.Equal(t, big.NewInt(10), blocks[0].Rollup.Batches[3].L1UserTxs[0].Amount)
|
||||
require.Equal(t, big.NewInt(0), blocks[0].Rollup.Batches[3].L1UserTxs[1].Amount)
|
||||
|
||||
config := Config{
|
||||
NLevels: 32,
|
||||
MaxFeeTx: 64,
|
||||
MaxTx: 512,
|
||||
MaxL1Tx: 16,
|
||||
ChainID: chainID,
|
||||
}
|
||||
tp := NewTxProcessor(sdb, config)
|
||||
|
||||
// For this test are only processed the batches with transactions:
|
||||
// - Batch2, equivalent to Batches[1]
|
||||
// - Batch4, equivalent to Batches[3]
|
||||
// - Batch6, equivalent to Batches[5]
|
||||
// - Batch8, equivalent to Batches[7]
|
||||
|
||||
// process Batch2:
|
||||
_, err = tp.ProcessTxs(nil, blocks[0].Rollup.Batches[1].L1UserTxs, nil, nil)
|
||||
require.NoError(t, err)
|
||||
// process Batch4:
|
||||
ptOut, err := tp.ProcessTxs(nil, blocks[0].Rollup.Batches[3].L1UserTxs, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "14329759303391468223438874789317921522067594445474390443816827472846339238908", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
|
||||
exitRootBatch4 := ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String()
|
||||
|
||||
// process Batch6:
|
||||
ptOut, err = tp.ProcessTxs(nil, blocks[0].Rollup.Batches[5].L1UserTxs, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "14329759303391468223438874789317921522067594445474390443816827472846339238908", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
|
||||
// Expect that the ExitRoot for the Batch6 will be equal than for the
|
||||
// Batch4, as the Batch4 & Batch6 have the same tx with Exit Amount=10,
|
||||
// and Batch4 has a 2nd tx with Exit Amount=0.
|
||||
assert.Equal(t, exitRootBatch4, ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
|
||||
|
||||
// For the Batch8, as there is only 1 exit with Amount=0, the ExitRoot
|
||||
// should be 0.
|
||||
// process Batch8:
|
||||
ptOut, err = tp.ProcessTxs(nil, blocks[0].Rollup.Batches[7].L1UserTxs, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "0", ptOut.ZKInputs.Metadata.NewExitRootRaw.BigInt().String())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user