This repository has been archived by the owner on Jan 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Test all the purger functions - Fix nonces set by til (previously til started with nonce 1 for pool l2txs, but the correct implementation is to start with nonce 0) - Rename L2DB.CheckNonces to L2DB.invalidateOldNoncesQuery - Rename L2DB.checkNoncesQuery to L2DB.InvalidateOldNonces Related #392 (Fix checkNoncesQuery) Resolve #396
- Loading branch information
Showing
8 changed files
with
325 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,287 @@ | ||
package coordinator | ||
|
||
// TODO: Test purger functions | ||
import ( | ||
"io/ioutil" | ||
"os" | ||
"testing" | ||
"time" | ||
|
||
"github.com/hermeznetwork/hermez-node/common" | ||
dbUtils "github.com/hermeznetwork/hermez-node/db" | ||
"github.com/hermeznetwork/hermez-node/db/l2db" | ||
"github.com/hermeznetwork/hermez-node/db/statedb" | ||
"github.com/hermeznetwork/hermez-node/test" | ||
"github.com/hermeznetwork/hermez-node/test/til" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func newL2DB(t *testing.T) *l2db.L2DB { | ||
pass := os.Getenv("POSTGRES_PASS") | ||
db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez") | ||
require.NoError(t, err) | ||
test.WipeDB(db) | ||
return l2db.NewL2DB(db, 10, 100, 24*time.Hour) | ||
} | ||
|
||
func newStateDB(t *testing.T) *statedb.LocalStateDB { | ||
syncDBPath, err := ioutil.TempDir("", "tmpSyncDB") | ||
require.NoError(t, err) | ||
deleteme = append(deleteme, syncDBPath) | ||
syncStateDB, err := statedb.NewStateDB(syncDBPath, statedb.TypeSynchronizer, 48) | ||
assert.NoError(t, err) | ||
stateDBPath, err := ioutil.TempDir("", "tmpStateDB") | ||
require.NoError(t, err) | ||
deleteme = append(deleteme, stateDBPath) | ||
stateDB, err := statedb.NewLocalStateDB(stateDBPath, syncStateDB, statedb.TypeTxSelector, 0) | ||
require.NoError(t, err) | ||
return stateDB | ||
} | ||
|
||
func TestCanPurgeCanInvalidate(t *testing.T) { | ||
cfg := PurgerCfg{ | ||
PurgeBatchDelay: 2, | ||
PurgeBlockDelay: 6, | ||
InvalidateBatchDelay: 4, | ||
InvalidateBlockDelay: 8, | ||
} | ||
p := Purger{ | ||
cfg: cfg, | ||
} | ||
startBlockNum := int64(1000) | ||
startBatchNum := int64(10) | ||
blockNum := startBlockNum | ||
batchNum := startBatchNum | ||
|
||
assert.True(t, p.CanPurge(blockNum, batchNum)) | ||
p.lastPurgeBlock = startBlockNum | ||
p.lastPurgeBatch = startBatchNum | ||
assert.False(t, p.CanPurge(blockNum, batchNum)) | ||
|
||
blockNum = startBlockNum + cfg.PurgeBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.PurgeBatchDelay - 1 | ||
assert.False(t, p.CanPurge(blockNum, batchNum)) | ||
blockNum = startBlockNum + cfg.PurgeBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.PurgeBatchDelay | ||
assert.True(t, p.CanPurge(blockNum, batchNum)) | ||
blockNum = startBlockNum + cfg.PurgeBlockDelay | ||
batchNum = startBatchNum + cfg.PurgeBatchDelay - 1 | ||
assert.True(t, p.CanPurge(blockNum, batchNum)) | ||
|
||
assert.True(t, p.CanInvalidate(blockNum, batchNum)) | ||
p.lastInvalidateBlock = startBlockNum | ||
p.lastInvalidateBatch = startBatchNum | ||
assert.False(t, p.CanInvalidate(blockNum, batchNum)) | ||
|
||
blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.InvalidateBatchDelay - 1 | ||
assert.False(t, p.CanInvalidate(blockNum, batchNum)) | ||
blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.InvalidateBatchDelay | ||
assert.True(t, p.CanInvalidate(blockNum, batchNum)) | ||
blockNum = startBlockNum + cfg.InvalidateBlockDelay | ||
batchNum = startBatchNum + cfg.InvalidateBatchDelay - 1 | ||
assert.True(t, p.CanInvalidate(blockNum, batchNum)) | ||
} | ||
|
||
func TestPurgeMaybeInvalidateMaybe(t *testing.T) { | ||
cfg := PurgerCfg{ | ||
PurgeBatchDelay: 2, | ||
PurgeBlockDelay: 6, | ||
InvalidateBatchDelay: 4, | ||
InvalidateBlockDelay: 8, | ||
} | ||
p := Purger{ | ||
cfg: cfg, | ||
} | ||
l2DB := newL2DB(t) | ||
stateDB := newStateDB(t) | ||
|
||
startBlockNum := int64(1000) | ||
startBatchNum := int64(10) | ||
|
||
p.lastPurgeBlock = startBlockNum | ||
p.lastPurgeBatch = startBatchNum | ||
|
||
blockNum := startBlockNum + cfg.PurgeBlockDelay - 1 | ||
batchNum := startBatchNum + cfg.PurgeBatchDelay - 1 | ||
ok, err := p.PurgeMaybe(l2DB, blockNum, batchNum) | ||
require.NoError(t, err) | ||
assert.False(t, ok) | ||
// At this point the purger will purge. The second time it doesn't | ||
// because it the first time it has updates the last time it did. | ||
blockNum = startBlockNum + cfg.PurgeBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.PurgeBatchDelay | ||
ok, err = p.PurgeMaybe(l2DB, blockNum, batchNum) | ||
require.NoError(t, err) | ||
assert.True(t, ok) | ||
ok, err = p.PurgeMaybe(l2DB, blockNum, batchNum) | ||
require.NoError(t, err) | ||
assert.False(t, ok) | ||
|
||
p.lastInvalidateBlock = startBlockNum | ||
p.lastInvalidateBatch = startBatchNum | ||
|
||
blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.InvalidateBatchDelay - 1 | ||
ok, err = p.InvalidateMaybe(l2DB, stateDB, blockNum, batchNum) | ||
require.NoError(t, err) | ||
assert.False(t, ok) | ||
// At this point the purger will invaidate. The second time it doesn't | ||
// because it the first time it has updates the last time it did. | ||
blockNum = startBlockNum + cfg.InvalidateBlockDelay - 1 | ||
batchNum = startBatchNum + cfg.InvalidateBatchDelay | ||
ok, err = p.InvalidateMaybe(l2DB, stateDB, blockNum, batchNum) | ||
require.NoError(t, err) | ||
assert.True(t, ok) | ||
ok, err = p.InvalidateMaybe(l2DB, stateDB, blockNum, batchNum) | ||
require.NoError(t, err) | ||
assert.False(t, ok) | ||
} | ||
|
||
func TestIdxsNonce(t *testing.T) { | ||
inputIdxsNonce := []common.IdxNonce{ | ||
{Idx: 256, Nonce: 1}, | ||
{Idx: 256, Nonce: 2}, | ||
{Idx: 257, Nonce: 3}, | ||
{Idx: 258, Nonce: 5}, | ||
{Idx: 258, Nonce: 2}, | ||
} | ||
expectedIdxsNonce := map[common.Idx]common.Nonce{ | ||
common.Idx(256): common.Nonce(2), | ||
common.Idx(257): common.Nonce(3), | ||
common.Idx(258): common.Nonce(5), | ||
} | ||
|
||
l2txs := make([]common.L2Tx, len(inputIdxsNonce)) | ||
for i, idxNonce := range inputIdxsNonce { | ||
l2txs[i].FromIdx = idxNonce.Idx | ||
l2txs[i].Nonce = idxNonce.Nonce | ||
} | ||
idxsNonce := idxsNonceFromL2Txs(l2txs) | ||
assert.Equal(t, len(expectedIdxsNonce), len(idxsNonce)) | ||
for _, idxNonce := range idxsNonce { | ||
nonce := expectedIdxsNonce[idxNonce.Idx] | ||
assert.Equal(t, nonce, idxNonce.Nonce) | ||
} | ||
|
||
pooll2txs := make([]common.PoolL2Tx, len(inputIdxsNonce)) | ||
for i, idxNonce := range inputIdxsNonce { | ||
pooll2txs[i].FromIdx = idxNonce.Idx | ||
pooll2txs[i].Nonce = idxNonce.Nonce | ||
} | ||
idxsNonce = idxsNonceFromPoolL2Txs(pooll2txs) | ||
assert.Equal(t, len(expectedIdxsNonce), len(idxsNonce)) | ||
for _, idxNonce := range idxsNonce { | ||
nonce := expectedIdxsNonce[idxNonce.Idx] | ||
assert.Equal(t, nonce, idxNonce.Nonce) | ||
} | ||
} | ||
|
||
func TestPoolMarkInvalidOldNonces(t *testing.T) { | ||
l2DB := newL2DB(t) | ||
stateDB := newStateDB(t) | ||
|
||
set0 := ` | ||
Type: Blockchain | ||
CreateAccountDeposit(0) A: 1000 // Idx=256 | ||
CreateAccountDeposit(0) B: 1000 // Idx=257 | ||
CreateAccountDeposit(0) C: 1000 // Idx=258 | ||
CreateAccountDeposit(0) D: 1000 // Idx=259 | ||
> batchL1 | ||
> batchL1 | ||
> block | ||
` | ||
tc := til.NewContext(common.RollupConstMaxL1UserTx) | ||
blocks, err := tc.GenerateBlocks(set0) | ||
require.NoError(t, err) | ||
tilCfgExtra := til.ConfigExtra{ | ||
CoordUser: "A", | ||
} | ||
// Call FillBlocksExtra to fill `Batch.CreatedAccounts` | ||
err = tc.FillBlocksExtra(blocks, &tilCfgExtra) | ||
require.NoError(t, err) | ||
require.Equal(t, 4, len(blocks[0].Rollup.Batches[1].CreatedAccounts)) // sanity check | ||
|
||
for _, acc := range blocks[0].Rollup.Batches[1].CreatedAccounts { | ||
_, err := stateDB.CreateAccount(acc.Idx, &acc) //nolint:gosec | ||
require.NoError(t, err) | ||
} | ||
|
||
setPool0 := ` | ||
Type: PoolL2 | ||
PoolTransfer(0) A-B: 10 (1) | ||
PoolTransfer(0) A-C: 10 (1) | ||
PoolTransfer(0) A-D: 10 (1) | ||
PoolTransfer(0) B-A: 10 (1) | ||
PoolTransfer(0) B-C: 10 (1) | ||
PoolTransfer(0) C-A: 10 (1) | ||
` | ||
// We expect the following nonces | ||
nonces0 := map[string]int64{"A": 3, "B": 2, "C": 1, "D": 0} | ||
l2txs0, err := tc.GeneratePoolL2Txs(setPool0) | ||
assert.Nil(t, err) | ||
assert.Equal(t, 6, len(l2txs0)) | ||
for _, tx := range l2txs0 { | ||
require.NoError(t, l2DB.AddTxTest(&tx)) //nolint:gosec | ||
} | ||
|
||
// Update the accounts in the StateDB, making the txs in the setPool0 | ||
// invalid | ||
for name, user := range tc.Users { | ||
for _, _acc := range user.Accounts { | ||
require.Equal(t, common.Nonce(nonces0[name]), _acc.Nonce) // sanity check | ||
acc, err := stateDB.GetAccount(_acc.Idx) | ||
require.NoError(t, err) | ||
require.Equal(t, common.Nonce(0), acc.Nonce) // sanity check | ||
acc.Nonce = _acc.Nonce | ||
_, err = stateDB.UpdateAccount(acc.Idx, acc) | ||
require.NoError(t, err) | ||
} | ||
} | ||
|
||
setPool1 := ` | ||
Type: PoolL2 | ||
PoolTransfer(0) A-B: 10 (1) | ||
PoolTransfer(0) A-C: 10 (1) | ||
PoolTransfer(0) A-D: 10 (1) | ||
PoolTransfer(0) B-A: 10 (1) | ||
PoolTransfer(0) B-C: 10 (1) | ||
PoolTransfer(0) C-A: 10 (1) | ||
` | ||
// We expect the following nonces | ||
nonces1 := map[string]int64{"A": 6, "B": 4, "C": 2, "D": 0} | ||
l2txs1, err := tc.GeneratePoolL2Txs(setPool1) | ||
require.NoError(t, err) | ||
assert.Equal(t, 6, len(l2txs1)) | ||
for _, tx := range l2txs1 { | ||
require.NoError(t, l2DB.AddTxTest(&tx)) //nolint:gosec | ||
} | ||
|
||
for name, user := range tc.Users { | ||
for _, _acc := range user.Accounts { | ||
require.Equal(t, common.Nonce(nonces1[name]), _acc.Nonce) // sanity check | ||
acc, err := stateDB.GetAccount(_acc.Idx) | ||
require.NoError(t, err) | ||
require.Equal(t, common.Nonce(nonces0[name]), acc.Nonce) // sanity check | ||
} | ||
} | ||
|
||
// Now we should have 12 txs in the pool, all marked as pending. Since | ||
// we updated the stateDB with the nonces after setPool0, the first 6 | ||
// txs will be marked as invalid | ||
|
||
pendingTxs, err := l2DB.GetPendingTxs() | ||
require.NoError(t, err) | ||
assert.Equal(t, 12, len(pendingTxs)) | ||
|
||
batchNum := common.BatchNum(1) | ||
err = poolMarkInvalidOldNonces(l2DB, stateDB, batchNum) | ||
require.NoError(t, err) | ||
|
||
pendingTxs, err = l2DB.GetPendingTxs() | ||
require.NoError(t, err) | ||
assert.Equal(t, 6, len(pendingTxs)) | ||
} |
Oops, something went wrong.