-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(txpool): calculate consumption when committing a new block #1554
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,9 @@ | |
"fmt" | ||
"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/sync/bundle/message" | ||
|
@@ -19,14 +22,16 @@ | |
type txPool struct { | ||
lk sync.RWMutex | ||
|
||
config *Config | ||
sandbox sandbox.Sandbox | ||
pools map[payload.Type]pool | ||
broadcastCh chan message.Message | ||
logger *logger.SubLogger | ||
config *Config | ||
sandbox sandbox.Sandbox | ||
pools map[payload.Type]pool | ||
consumptionMap map[crypto.Address]uint32 | ||
broadcastCh chan message.Message | ||
strReader store.Reader | ||
logger *logger.SubLogger | ||
} | ||
|
||
func NewTxPool(conf *Config, broadcastCh chan message.Message) TxPool { | ||
func NewTxPool(conf *Config, broadcastCh chan message.Message, storeReader store.Reader) TxPool { | ||
pools := make(map[payload.Type]pool) | ||
pools[payload.TypeTransfer] = newPool(conf.transferPoolSize(), conf.minFee()) | ||
pools[payload.TypeBond] = newPool(conf.bondPoolSize(), conf.minFee()) | ||
|
@@ -35,9 +40,11 @@ | |
pools[payload.TypeSortition] = newPool(conf.sortitionPoolSize(), 0) | ||
|
||
pool := &txPool{ | ||
config: conf, | ||
pools: pools, | ||
broadcastCh: broadcastCh, | ||
config: conf, | ||
pools: pools, | ||
consumptionMap: make(map[crypto.Address]uint32), | ||
strReader: storeReader, | ||
broadcastCh: broadcastCh, | ||
} | ||
|
||
pool.logger = logger.NewSubLogger("_pool", pool) | ||
|
@@ -133,10 +140,57 @@ | |
return nil | ||
} | ||
|
||
func (p *txPool) RemoveTx(id tx.ID) { | ||
func (p *txPool) HandleCommittedBlock(blk *block.Block) error { | ||
p.lk.Lock() | ||
defer p.lk.Unlock() | ||
|
||
for _, trx := range blk.Transactions() { | ||
p.removeTx(trx.ID()) | ||
|
||
p.handleIncreaseConsumption(trx) | ||
} | ||
|
||
return p.handleDecreaseConsumption(blk.Height()) | ||
} | ||
|
||
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()) | ||
Check failure on line 161 in txpool/txpool.go GitHub Actions / linting
|
||
} | ||
} | ||
|
||
func (p *txPool) handleDecreaseConsumption(height uint32) error { | ||
if height <= p.config.ConsumptionBlocks { | ||
return nil | ||
} | ||
|
||
oldConsumptionHeight := height - p.config.ConsumptionBlocks | ||
committedBlock, err := p.strReader.Block(oldConsumptionHeight) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
blk, err := committedBlock.ToBlock() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, trx := range blk.Transactions() { | ||
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()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @b00f I don't know on test |
||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *txPool) removeTx(id tx.ID) { | ||
for _, pool := range p.pools { | ||
if pool.list.Remove(id) { | ||
break | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,8 @@ | |
"testing" | ||
"time" | ||
|
||
"github.com/pactus-project/pactus/store" | ||
|
||
"github.com/pactus-project/pactus/execution" | ||
"github.com/pactus-project/pactus/sandbox" | ||
"github.com/pactus-project/pactus/sync/bundle/message" | ||
|
@@ -22,12 +24,14 @@ | |
|
||
pool *txPool | ||
sandbox *sandbox.MockSandbox | ||
str *store.MockStore | ||
ch chan message.Message | ||
} | ||
|
||
func testConfig() *Config { | ||
return &Config{ | ||
MaxSize: 10, | ||
MaxSize: 10, | ||
ConsumptionBlocks: 3, | ||
Fee: &FeeConfig{ | ||
FixedFee: 0.000001, | ||
DailyLimit: 280, | ||
|
@@ -44,7 +48,8 @@ | |
ch := make(chan message.Message, 10) | ||
sb := sandbox.MockingSandbox(ts) | ||
config := testConfig() | ||
p := NewTxPool(config, ch) | ||
mockStore := store.MockingStore(ts) | ||
p := NewTxPool(config, ch, mockStore) | ||
p.SetNewSandboxAndRecheck(sb) | ||
pool := p.(*txPool) | ||
assert.NotNil(t, pool) | ||
|
@@ -53,6 +58,7 @@ | |
TestSuite: ts, | ||
pool: pool, | ||
sandbox: sb, | ||
str: mockStore, | ||
ch: ch, | ||
} | ||
} | ||
|
@@ -96,11 +102,36 @@ | |
// Appending the same transaction again, should not return any error | ||
assert.NoError(t, td.pool.AppendTx(testTrx)) | ||
|
||
td.pool.RemoveTx(testTrx.ID()) | ||
td.pool.removeTx(testTrx.ID()) | ||
assert.False(t, td.pool.HasTx(testTrx.ID()), "Transaction should be removed") | ||
assert.Nil(t, td.pool.PendingTx(testTrx.ID())) | ||
} | ||
|
||
func TestCalculatingConsumption(t *testing.T) { | ||
Check failure on line 110 in txpool/txpool_test.go GitHub Actions / linting
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @b00f What case need for check consumption map? I need to more details for test cases. |
||
td := setup(t) | ||
|
||
_, prv := td.TestSuite.RandEd25519KeyPair() | ||
signer := prv | ||
|
||
for i := uint32(1); i < 10; i++ { | ||
txr := td.GenerateTestTransferTx(func(tm *testsuite.TransactionMaker) { | ||
tm.Signer = signer | ||
}) | ||
|
||
blk, cert := td.TestSuite.GenerateTestBlock(i, func(bm *testsuite.BlockMaker) { | ||
bm.Txs = []*tx.Tx{txr} | ||
}) | ||
|
||
td.str.SaveBlock(blk, cert) | ||
|
||
err := td.pool.HandleCommittedBlock(blk) | ||
require.NoError(t, err) | ||
|
||
//t.Log(td.pool.consumptionMap[txr.Payload().Signer()]) | ||
Check failure on line 130 in txpool/txpool_test.go GitHub Actions / linting
|
||
} | ||
|
||
} | ||
Check failure on line 133 in txpool/txpool_test.go GitHub Actions / linting
|
||
|
||
func TestAppendInvalidTransaction(t *testing.T) { | ||
td := setup(t) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@b00f Please double check for remove this line.