diff --git a/state/state.go b/state/state.go index 2eebcfdd5..e002bb304 100644 --- a/state/state.go +++ b/state/state.go @@ -434,8 +434,8 @@ func (st *state) CommitBlock(blk *block.Block, cert *certificate.BlockCertificat st.store.SaveBlock(blk, cert) // Remove transactions from pool and update consumption - if err = st.txPool.HandleCommittedBlock(blk); err != nil { - return err + if errHandleCommittedBlk := st.txPool.HandleCommittedBlock(blk); errHandleCommittedBlk != nil { + return errHandleCommittedBlk } if err := st.store.WriteBatch(); err != nil { diff --git a/txpool/interface.go b/txpool/interface.go index 7c969c5bf..34ee3b4ac 100644 --- a/txpool/interface.go +++ b/txpool/interface.go @@ -23,5 +23,5 @@ type TxPool interface { SetNewSandboxAndRecheck(sb sandbox.Sandbox) AppendTxAndBroadcast(trx *tx.Tx) error AppendTx(trx *tx.Tx) error - HandleCommittedBlock(block *block.Block) error + HandleCommittedBlock(blk *block.Block) error } diff --git a/txpool/mock.go b/txpool/mock.go index 212963cfc..e305a6aca 100644 --- a/txpool/mock.go +++ b/txpool/mock.go @@ -79,7 +79,7 @@ func (m *MockTxPool) RemoveTx(id hash.Hash) { } } -func (m *MockTxPool) HandleCommittedBlock(_ *block.Block) error { +func (*MockTxPool) HandleCommittedBlock(_ *block.Block) error { return nil } diff --git a/txpool/txpool.go b/txpool/txpool.go index 839349e58..827fe0c52 100644 --- a/txpool/txpool.go +++ b/txpool/txpool.go @@ -5,10 +5,9 @@ import ( "sync" "github.com/pactus-project/pactus/crypto" - "github.com/pactus-project/pactus/store" - "github.com/pactus-project/pactus/execution" "github.com/pactus-project/pactus/sandbox" + "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/sync/bundle/message" "github.com/pactus-project/pactus/types/amount" "github.com/pactus-project/pactus/types/block" @@ -157,16 +156,17 @@ func (p *txPool) handleIncreaseConsumption(trx *tx.Tx) { if trx.IsTransferTx() || trx.IsBondTx() || trx.IsWithdrawTx() { signer := trx.Payload().Signer() - // retrieve existing consumption or start with 0 - p.consumptionMap[signer] = p.consumptionMap[signer] + uint32(trx.SerializeSize()) + p.consumptionMap[signer] += uint32(trx.SerializeSize()) } } func (p *txPool) handleDecreaseConsumption(height uint32) error { + // If height is less than or equal to ConsumptionBlocks, nothing to do if height <= p.config.ConsumptionBlocks { return nil } + // Calculate the height of the old block based on ConsumptionBlocks oldConsumptionHeight := height - p.config.ConsumptionBlocks committedBlock, err := p.strReader.Block(oldConsumptionHeight) if err != nil { @@ -182,7 +182,16 @@ func (p *txPool) handleDecreaseConsumption(height uint32) error { if trx.IsTransferTx() || trx.IsBondTx() || trx.IsWithdrawTx() { signer := trx.Payload().Signer() if v, ok := p.consumptionMap[signer]; ok { - p.consumptionMap[signer] = v - uint32(trx.SerializeSize()) + // Decrease the consumption by the size of the transaction + v -= uint32(trx.SerializeSize()) + + // If the new value is zero, remove the signer from the consumptionMap + if v == 0 { + delete(p.consumptionMap, signer) + } else { + // Otherwise, update the map with the new value + p.consumptionMap[signer] = v + } } } } diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 05b9673c3..e45b4768f 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -5,10 +5,10 @@ import ( "testing" "time" - "github.com/pactus-project/pactus/store" - + "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/execution" "github.com/pactus-project/pactus/sandbox" + "github.com/pactus-project/pactus/store" "github.com/pactus-project/pactus/sync/bundle/message" "github.com/pactus-project/pactus/types/account" "github.com/pactus-project/pactus/types/tx" @@ -110,26 +110,52 @@ func TestAppendAndRemove(t *testing.T) { func TestCalculatingConsumption(t *testing.T) { td := setup(t) - _, prv := td.TestSuite.RandEd25519KeyPair() - signer := prv + // Generate keys for different transaction signers + _, prv1 := td.RandEd25519KeyPair() + _, prv2 := td.RandEd25519KeyPair() + _, prv3 := td.RandBLSKeyPair() + _, prv4 := td.RandBLSKeyPair() + + // Generate different types of transactions + trx11 := td.GenerateTestTransferTx(testsuite.TransactionWithEd25519Signer(prv1)) + trx12 := td.GenerateTestBondTx(testsuite.TransactionWithEd25519Signer(prv1)) + trx13 := td.GenerateTestWithdrawTx(testsuite.TransactionWithBLSSigner(prv3)) + trx14 := td.GenerateTestUnbondTx(testsuite.TransactionWithBLSSigner(prv4)) + trx21 := td.GenerateTestTransferTx(testsuite.TransactionWithEd25519Signer(prv2)) + trx31 := td.GenerateTestBondTx(testsuite.TransactionWithBLSSigner(prv4)) + trx41 := td.GenerateTestWithdrawTx(testsuite.TransactionWithBLSSigner(prv3)) + trx42 := td.GenerateTestTransferTx(testsuite.TransactionWithEd25519Signer(prv2)) + + // Expected consumption map after transactions + expected := map[crypto.Address]uint32{ + prv2.PublicKeyNative().AccountAddress(): uint32(trx21.SerializeSize()) + uint32(trx42.SerializeSize()), + prv4.PublicKeyNative().AccountAddress(): uint32(trx31.SerializeSize()), + prv3.PublicKeyNative().ValidatorAddress(): uint32(trx41.SerializeSize()), + } - for i := uint32(1); i < 10; i++ { - txr := td.GenerateTestTransferTx(func(tm *testsuite.TransactionMaker) { - tm.Signer = signer - }) + tests := []struct { + height uint32 + txs []*tx.Tx + }{ + {1, []*tx.Tx{trx11, trx12, trx13, trx14}}, + {2, []*tx.Tx{trx21}}, + {3, []*tx.Tx{trx31}}, + {4, []*tx.Tx{trx41, trx42}}, + } - blk, cert := td.TestSuite.GenerateTestBlock(i, func(bm *testsuite.BlockMaker) { - bm.Txs = []*tx.Tx{txr} + for _, tt := range tests { + // Generate a block with the transactions for the given height + blk, cert := td.TestSuite.GenerateTestBlock(tt.height, func(bm *testsuite.BlockMaker) { + bm.Txs = tt.txs }) - td.str.SaveBlock(blk, cert) + // Handle the block in the transaction pool err := td.pool.HandleCommittedBlock(blk) require.NoError(t, err) - - //t.Log(td.pool.consumptionMap[txr.Payload().Signer()]) } + require.Equal(t, expected, td.pool.consumptionMap) } func TestAppendInvalidTransaction(t *testing.T) {