From 1b1ef4c7efa5f5116a851c23a6c34b68fab1393b Mon Sep 17 00:00:00 2001 From: Herr Seppia Date: Mon, 20 Jun 2022 14:53:45 +0200 Subject: [PATCH] Improve mempool extraction Resolves #1421 --- CHANGELOG.md | 2 ++ .../data/ipc/transactions/payload_decoded.go | 14 ++++++++++ pkg/core/mempool/mempool.go | 27 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc6582729..671a86194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mempool discards any transaction with repeated nullifier [#1388] ### Changed +- Extraction from mempool consider Gas expenditure estimation [#1421] - Add GasLimit to the Block's header [#1416] - Reduce wire messages needed for propagating an Agreement vote - Improve fallback procedure to revert multiple ephemeral blocks [#1343] @@ -30,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Default configuration values loading [#1419] +[#1421]: (https://github.com/dusk-network/dusk-blockchain/issues/1421) [#1419]: (https://github.com/dusk-network/dusk-blockchain/issues/1419) [#1418]: (https://github.com/dusk-network/dusk-blockchain/issues/1418) [#1416]: (https://github.com/dusk-network/dusk-blockchain/issues/1416) diff --git a/pkg/core/data/ipc/transactions/payload_decoded.go b/pkg/core/data/ipc/transactions/payload_decoded.go index 715002db7..c66f52883 100644 --- a/pkg/core/data/ipc/transactions/payload_decoded.go +++ b/pkg/core/data/ipc/transactions/payload_decoded.go @@ -193,3 +193,17 @@ func UnmarshalTransactionPayloadDecoded(r *bytes.Buffer, f *TransactionPayloadDe return nil } + +// EstimatedGasSpent return the estimated amount of Gas that a transaction will +// spend. For now it uses `t.Call` to determine if it's a normal transfer or it +// is an intercontract call. +// TODO: further improvement should take care of the contractAddress to compare +// it against historical data. +func (p *TransactionPayloadDecoded) EstimatedGasSpent() uint64 { + if p.Call == nil { + // This is a normal transfer transaction + return 250_000_000 + } + // This is an inter-contract call + return 1_200_000_000 +} diff --git a/pkg/core/mempool/mempool.go b/pkg/core/mempool/mempool.go index 81ef77a55..a16cf37a3 100644 --- a/pkg/core/mempool/mempool.go +++ b/pkg/core/mempool/mempool.go @@ -436,6 +436,7 @@ func (m Mempool) processGetMempoolTxsRequest(r rpcbus.Request) (interface{}, err // processGetMempoolTxsBySizeRequest returns a subset of verified mempool txs which // 1. contains only highest fee txs // 2. has total txs size not bigger than maxTxsSize (request param) +// 3. has total txs EstimatedGasSpent not bigger than BlockGasLimit+10% // Called by BlockGenerator on generating a new candidate block. func (m Mempool) processGetMempoolTxsBySizeRequest(r rpcbus.Request) (interface{}, error) { // Read maxTxsSize param @@ -447,16 +448,42 @@ func (m Mempool) processGetMempoolTxsBySizeRequest(r rpcbus.Request) (interface{ } txs := make([]transactions.ContractCall, 0) + gasLimit := config.Get().State.BlockGasLimit + // The slippageGasLimit is the threshold that consider the "estimated gas + // spent" acceptable even if it exceeds the strict GasLimit. This is + // required to avoid to iterate the whole meempol until it fit perfectly + // the block GasLimit + slippageGasLimit := gasLimit + gasLimit/10 var totalSize uint32 + var totalGas uint64 err := m.verified.RangeSort(func(k txHash, t TxDesc) (bool, error) { var done bool + + decoded, err := t.tx.Decode() + if err != nil { + // Cannot decode, skip the tx. + // This should never happen, keeping `err` to log it properly` + return false, err + } + + totalGas += decoded.EstimatedGasSpent() + if totalGas > slippageGasLimit { + // Total gas exceeded the slippage threshold, skip the tx + return false, nil + } + + // If the totalGas exceeded the gasLimit (but still below the + // slippage threshold) stop to iterate the mempool + done = totalGas >= gasLimit + totalSize += uint32(t.size) if totalSize <= maxTxsSize { txs = append(txs, t.tx) } else { + // it the totalSize exceeds the limit, stop to iterate the mempool done = true }