Compare commits

...

62 Commits

Author SHA1 Message Date
emailtovamos
60bdc2539e pool: fail fast, disable by default, no interface 2024-10-16 13:56:48 +01:00
emailtovamos
0dd0bd7b38 pool: remove extra new lines 2024-10-15 18:25:12 +01:00
emailtovamos
f41bb13160 pool: refactoring, addressing comments 2024-10-15 12:50:58 +01:00
emailtovamos
0e67514ee7 pool: remove debug logs 2024-10-14 14:55:44 +01:00
emailtovamos
8170d99b2f Merge branch 'develop' into txpool-new 2024-10-14 14:41:42 +01:00
emailtovamos
7a929d6324 pool: refactor to overflow pool 2024-10-14 11:05:49 +01:00
Ethan
00a36bb0cc feat: modify LOCK_PERIOD_FOR_TOKEN_RECOVER to 300 seconds on BSC Testnet in pascal hardfork (#2737)
* feat: modify LOCK_PERIOD_FOR_TOKEN_RECOVER to 300 seconds on BSC Testnet

* feat: update commit id in pascal hardfork
2024-10-12 09:14:28 +08:00
galaio
3a6dbe4d85 ethclient: move TransactionOpts to avoid import internal package; (#2736) 2024-10-11 16:44:50 +08:00
Ethan
72ec06eae7 feat: update system contract bytecodes of pascal hardfork (#2734) 2024-10-10 13:01:30 +08:00
emailtovamos
5d44ba9c6a pool: remove sequence, more sturdy, maxsize 2024-10-01 11:48:56 +01:00
emailtovamos
9c72c02502 pool: preallocate pool3 2024-09-26 16:03:23 +01:00
emailtovamos
a8959fe60e pool: minor refactors 2024-09-26 15:18:06 +01:00
emailtovamos
31c9465eac pool: remove old buffer for pool3 2024-09-26 14:58:31 +01:00
emailtovamos
4e69ac4a0f pool: remove event and debug logs 2024-09-26 14:55:59 +01:00
emailtovamos
d5b10e09a7 pool: remove fastcache which is no longer required 2024-09-26 14:24:37 +01:00
emailtovamos
1ad40cda3f pool: add back removed logic 2024-09-26 14:24:13 +01:00
emailtovamos
355dee9000 pool: edit tests and remove remaining pool2 logic 2024-09-26 14:21:36 +01:00
emailtovamos
6a6e09c849 pool: remove pool2 related code 2024-09-26 14:13:13 +01:00
emailtovamos
846e55b9a4 pool: remove pool2 from legacypool 2024-09-25 16:05:01 +01:00
emailtovamos
09575625db pool: heap map as pool3 2024-09-25 14:06:24 +01:00
emailtovamos
3e3c56b235 pool: address minor issues 2024-09-19 04:32:47 +01:00
emailtovamos
629af6dab4 pool: else ifs instead of ifs 2024-09-18 13:04:29 +01:00
emailtovamos
774e314096 pool: truly discard underpriced, Transfer after lock is over 2024-09-18 13:01:22 +01:00
emailtovamos
b818cb78db pool: transfer on block import and simplify it 2024-09-12 16:29:57 +01:00
emailtovamos
cf10c5cfe6 eth: send to some peers of pool2, not just static 2024-09-11 15:57:29 +01:00
emailtovamos
248bb6b0d6 pool: fastcache, interface, metrics modify 2024-09-11 15:57:06 +01:00
emailtovamos
0a5dbef9f4 pool: queued goes to 0 locally after this change 2024-09-06 17:19:56 +01:00
emailtovamos
0e61543954 test: requestPromoteExecutables after every enqueue for testing 2024-09-06 12:20:36 +01:00
emailtovamos
706a24eb2c pool: lint fix 2024-09-04 04:46:45 +01:00
emailtovamos
5f398db90a pool: pool2 can have 0 size 2024-09-03 16:57:21 +01:00
emailtovamos
8e6833cec4 pool: bug fix and test fix 2024-09-03 16:39:35 +01:00
emailtovamos
53042e15d7 buffer: make private 2024-09-03 15:08:30 +01:00
emailtovamos
aeec0c7129 pool: remove unused criticalpathpool 2024-09-03 13:03:10 +01:00
emailtovamos
76d157d08b pool: set transfer time in config 2024-09-03 12:42:11 +01:00
emailtovamos
0f8a1b5c5a pool: test for transfer 2024-09-03 12:41:54 +01:00
emailtovamos
16a2a53635 Merge remote-tracking branch 'origin/develop' into txpool-new 2024-09-02 15:03:44 +01:00
emailtovamos
e7d0a16bc4 pool: fix test as now by default pool2 and pool3 aren't empty 2024-08-30 13:36:09 +01:00
emailtovamos
70ece9355a pool: flags for pool2 and 3 capacity 2024-08-29 16:10:59 +01:00
emailtovamos
069eaf22f7 pool: proper use of AsyncSendPooledTransactionHashes 2024-08-29 15:57:30 +01:00
emailtovamos
e45e7eb9c6 pool: include static in flatten 2024-08-29 08:03:45 +01:00
emailtovamos
bdb4cc2acd pool: lint 2024-08-29 06:49:28 +01:00
emailtovamos
ebd8f590a3 pool: fix all old tests 2024-08-28 15:52:41 +01:00
emailtovamos
6673f3e75a pool: fix TestUnderpricingDynamicFee based on new pool 2024-08-28 15:49:07 +01:00
emailtovamos
40dcfcd776 pool: cleanup debug logs 2024-08-28 14:29:15 +01:00
emailtovamos
0692a99ea9 pool: fix the TestTransactionFutureAttack test 2024-08-28 14:26:16 +01:00
emailtovamos
253d9a566b pool: some cleanups 2024-08-27 07:58:38 +01:00
emailtovamos
a1a25e91a4 pool: TestDualHeapEviction fully pass 2024-08-27 07:38:02 +01:00
emailtovamos
9d7298f0c1 pool: TestDualHeapEviction passing partly 2024-08-27 07:33:23 +01:00
emailtovamos
6daecfb105 pool: bugfix:always drop drop and pool2 size 2024-08-27 07:24:00 +01:00
emailtovamos
ed2d1d7f8f pool: enqueue in pool2 & drop properly 2024-08-25 19:24:20 +01:00
emailtovamos
94a60a9006 pool: add underpriced to pool2 or 3 2024-08-23 09:11:59 +01:00
emailtovamos
d03f7e5e94 pool: initialise pool3 slots 2024-08-21 15:51:21 +01:00
emailtovamos
6b4e16ba7b pool: make slots config 2024-08-21 15:50:59 +01:00
emailtovamos
5bb78b34be pool: minor refactor 2024-08-20 07:46:22 +01:00
emailtovamos
5faf41359a pool: add discarded ones to pool3 by default. 2024-08-02 13:05:05 +01:00
emailtovamos
d0d6a272f0 pool: buffer test and size logic 2024-08-02 13:03:35 +01:00
emailtovamos
4369e3d997 pool: refactor and bugfix 2024-08-01 15:01:28 +01:00
emailtovamos
4538e92dbb pool: remove unused function 2024-08-01 14:54:07 +01:00
emailtovamos
8655d30cb9 pool: remove comments, use queue not pool23 2024-08-01 14:51:18 +01:00
emailtovamos
f80ac01c95 pool: add static info and simplify transfer 2024-08-01 14:36:47 +01:00
emailtovamos
e30248be3a pool: optimise sending in reorg 2024-07-29 11:51:02 +01:00
emailtovamos
dfb046e852 txpool: incomplete pool2 and pool3 2024-07-16 05:49:06 +01:00
32 changed files with 773 additions and 177 deletions

View File

@@ -24,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi"
)
var (
@@ -101,7 +100,7 @@ type ContractTransactor interface {
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
// SendTransactionConditional injects the conditional transaction into the pending pool for execution after verification.
SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error
SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts types.TransactionOpts) error
}
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.

View File

@@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rlp"
"github.com/stretchr/testify/assert"
)
@@ -76,7 +75,7 @@ func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transac
return nil
}
func (mt *mockTransactor) SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error {
func (mt *mockTransactor) SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts types.TransactionOpts) error {
return nil
}

View File

@@ -92,6 +92,7 @@ var (
utils.TxPoolGlobalSlotsFlag,
utils.TxPoolAccountQueueFlag,
utils.TxPoolGlobalQueueFlag,
utils.TxPoolOverflowPoolSlotsFlag,
utils.TxPoolLifetimeFlag,
utils.TxPoolReannounceTimeFlag,
utils.BlobPoolDataDirFlag,

View File

@@ -458,6 +458,12 @@ var (
Value: ethconfig.Defaults.TxPool.GlobalQueue,
Category: flags.TxPoolCategory,
}
TxPoolOverflowPoolSlotsFlag = &cli.Uint64Flag{
Name: "txpool.overflowpoolslots",
Usage: "Maximum number of transaction slots in overflow pool",
Value: ethconfig.Defaults.TxPool.OverflowPoolSlots,
Category: flags.TxPoolCategory,
}
TxPoolLifetimeFlag = &cli.DurationFlag{
Name: "txpool.lifetime",
Usage: "Maximum amount of time non-executable transaction are queued",
@@ -1789,6 +1795,9 @@ func setTxPool(ctx *cli.Context, cfg *legacypool.Config) {
if ctx.IsSet(TxPoolGlobalQueueFlag.Name) {
cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name)
}
if ctx.IsSet(TxPoolOverflowPoolSlotsFlag.Name) {
cfg.OverflowPoolSlots = ctx.Uint64(TxPoolOverflowPoolSlotsFlag.Name)
}
if ctx.IsSet(TxPoolLifetimeFlag.Name) {
cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name)
}
@@ -2310,16 +2319,17 @@ func EnableNodeInfo(poolConfig *legacypool.Config, nodeInfo *p2p.NodeInfo) Setup
return func() {
// register node info into metrics
metrics.NewRegisteredLabel("node-info", nil).Mark(map[string]interface{}{
"Enode": nodeInfo.Enode,
"ENR": nodeInfo.ENR,
"ID": nodeInfo.ID,
"PriceLimit": poolConfig.PriceLimit,
"PriceBump": poolConfig.PriceBump,
"AccountSlots": poolConfig.AccountSlots,
"GlobalSlots": poolConfig.GlobalSlots,
"AccountQueue": poolConfig.AccountQueue,
"GlobalQueue": poolConfig.GlobalQueue,
"Lifetime": poolConfig.Lifetime,
"Enode": nodeInfo.Enode,
"ENR": nodeInfo.ENR,
"ID": nodeInfo.ID,
"PriceLimit": poolConfig.PriceLimit,
"PriceBump": poolConfig.PriceBump,
"AccountSlots": poolConfig.AccountSlots,
"GlobalSlots": poolConfig.GlobalSlots,
"AccountQueue": poolConfig.AccountQueue,
"GlobalQueue": poolConfig.GlobalQueue,
"OverflowPoolSlots": poolConfig.OverflowPoolSlots,
"Lifetime": poolConfig.Lifetime,
})
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -781,87 +781,87 @@ func init() {
Configs: []*UpgradeConfig{
{
ContractAddr: common.HexToAddress(ValidatorContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetValidatorContract,
},
{
ContractAddr: common.HexToAddress(SlashContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetSlashContract,
},
{
ContractAddr: common.HexToAddress(SystemRewardContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetSystemRewardContract,
},
{
ContractAddr: common.HexToAddress(LightClientContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetLightClientContract,
},
{
ContractAddr: common.HexToAddress(TokenHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetTokenHubContract,
},
{
ContractAddr: common.HexToAddress(RelayerIncentivizeContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetRelayerIncentivizeContract,
},
{
ContractAddr: common.HexToAddress(RelayerHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetRelayerHubContract,
},
{
ContractAddr: common.HexToAddress(GovHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetGovHubContract,
},
{
ContractAddr: common.HexToAddress(TokenManagerContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetTokenManagerContract,
},
{
ContractAddr: common.HexToAddress(CrossChainContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetCrossChainContract,
},
{
ContractAddr: common.HexToAddress(StakingContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetStakingContract,
},
{
ContractAddr: common.HexToAddress(StakeHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetStakeHubContract,
},
{
ContractAddr: common.HexToAddress(StakeCreditContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetStakeCreditContract,
},
{
ContractAddr: common.HexToAddress(GovernorContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetGovernorContract,
},
{
ContractAddr: common.HexToAddress(GovTokenContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetGovTokenContract,
},
{
ContractAddr: common.HexToAddress(TimelockContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetTimelockContract,
},
{
ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.MainnetTokenRecoverPortalContract,
},
},
@@ -872,87 +872,87 @@ func init() {
Configs: []*UpgradeConfig{
{
ContractAddr: common.HexToAddress(ValidatorContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelValidatorContract,
},
{
ContractAddr: common.HexToAddress(SlashContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelSlashContract,
},
{
ContractAddr: common.HexToAddress(SystemRewardContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelSystemRewardContract,
},
{
ContractAddr: common.HexToAddress(LightClientContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelLightClientContract,
},
{
ContractAddr: common.HexToAddress(TokenHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelTokenHubContract,
},
{
ContractAddr: common.HexToAddress(RelayerIncentivizeContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelRelayerIncentivizeContract,
},
{
ContractAddr: common.HexToAddress(RelayerHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelRelayerHubContract,
},
{
ContractAddr: common.HexToAddress(GovHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelGovHubContract,
},
{
ContractAddr: common.HexToAddress(TokenManagerContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelTokenManagerContract,
},
{
ContractAddr: common.HexToAddress(CrossChainContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelCrossChainContract,
},
{
ContractAddr: common.HexToAddress(StakingContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelStakingContract,
},
{
ContractAddr: common.HexToAddress(StakeHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelStakeHubContract,
},
{
ContractAddr: common.HexToAddress(StakeCreditContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelStakeCreditContract,
},
{
ContractAddr: common.HexToAddress(GovernorContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelGovernorContract,
},
{
ContractAddr: common.HexToAddress(GovTokenContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelGovTokenContract,
},
{
ContractAddr: common.HexToAddress(TimelockContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelTimelockContract,
},
{
ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.ChapelTokenRecoverPortalContract,
},
},
@@ -963,87 +963,87 @@ func init() {
Configs: []*UpgradeConfig{
{
ContractAddr: common.HexToAddress(ValidatorContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoValidatorContract,
},
{
ContractAddr: common.HexToAddress(SlashContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoSlashContract,
},
{
ContractAddr: common.HexToAddress(SystemRewardContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoSystemRewardContract,
},
{
ContractAddr: common.HexToAddress(LightClientContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoLightClientContract,
},
{
ContractAddr: common.HexToAddress(TokenHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoTokenHubContract,
},
{
ContractAddr: common.HexToAddress(RelayerIncentivizeContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoRelayerIncentivizeContract,
},
{
ContractAddr: common.HexToAddress(RelayerHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoRelayerHubContract,
},
{
ContractAddr: common.HexToAddress(GovHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoGovHubContract,
},
{
ContractAddr: common.HexToAddress(TokenManagerContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoTokenManagerContract,
},
{
ContractAddr: common.HexToAddress(CrossChainContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoCrossChainContract,
},
{
ContractAddr: common.HexToAddress(StakingContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoStakingContract,
},
{
ContractAddr: common.HexToAddress(StakeHubContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoStakeHubContract,
},
{
ContractAddr: common.HexToAddress(StakeCreditContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoStakeCreditContract,
},
{
ContractAddr: common.HexToAddress(GovernorContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoGovernorContract,
},
{
ContractAddr: common.HexToAddress(GovTokenContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoGovTokenContract,
},
{
ContractAddr: common.HexToAddress(TimelockContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoTimelockContract,
},
{
ContractAddr: common.HexToAddress(TokenRecoverPortalContract),
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/4c03f8222f8ac13e3b6bd424e1235698282bb28d",
CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/020c0459e37d1f9d635c1cff86dd1099ab1383fa",
Code: pascal.RialtoTokenRecoverPortalContract,
},
},

View File

@@ -19,6 +19,7 @@ package legacypool
import (
"errors"
"fmt"
"math"
"math/big"
"sort"
@@ -99,10 +100,11 @@ var (
// that this number is pretty low, since txpool reorgs happen very frequently.
dropBetweenReorgHistogram = metrics.NewRegisteredHistogram("txpool/dropbetweenreorg", nil, metrics.NewExpDecaySample(1028, 0.015))
pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil)
queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil)
localGauge = metrics.NewRegisteredGauge("txpool/local", nil)
slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil)
pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil)
queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil)
localGauge = metrics.NewRegisteredGauge("txpool/local", nil)
slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil)
OverflowPoolGauge = metrics.NewRegisteredGauge("txpool/overflowpool", nil)
reheapTimer = metrics.NewRegisteredTimer("txpool/reheap", nil)
)
@@ -133,10 +135,11 @@ type Config struct {
PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool
PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce)
AccountSlots uint64 // Number of executable transaction slots guaranteed per account
GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts
AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account
GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts
AccountSlots uint64 // Number of executable transaction slots guaranteed per account
GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts
AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account
GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts
OverflowPoolSlots uint64 // Maximum number of transaction slots in overflow pool
Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
ReannounceTime time.Duration // Duration for announcing local pending transactions again
@@ -150,10 +153,11 @@ var DefaultConfig = Config{
PriceLimit: 1,
PriceBump: 10,
AccountSlots: 16,
GlobalSlots: 4096 + 1024, // urgent + floating queue capacity with 4:1 ratio
AccountQueue: 64,
GlobalQueue: 1024,
AccountSlots: 16,
GlobalSlots: 4096 + 1024, // urgent + floating queue capacity with 4:1 ratio
AccountQueue: 64,
GlobalQueue: 1024,
OverflowPoolSlots: 0,
Lifetime: 3 * time.Hour,
ReannounceTime: 10 * 365 * 24 * time.Hour,
@@ -235,6 +239,8 @@ type LegacyPool struct {
all *lookup // All transactions to allow lookups
priced *pricedList // All transactions sorted by price
localBufferPool *TxOverflowPool // Local buffer transactions
reqResetCh chan *txpoolResetRequest
reqPromoteCh chan *accountSet
queueTxEventCh chan *types.Transaction
@@ -272,6 +278,7 @@ func New(config Config, chain BlockChain) *LegacyPool {
reorgDoneCh: make(chan chan struct{}),
reorgShutdownCh: make(chan struct{}),
initDoneCh: make(chan struct{}),
localBufferPool: NewTxOverflowPoolHeap(config.OverflowPoolSlots),
}
pool.locals = newAccountSet(pool.signer)
for _, addr := range config.Locals {
@@ -408,7 +415,6 @@ func (pool *LegacyPool) loop() {
if !pool.locals.contains(addr) {
continue
}
for _, tx := range list.Flatten() {
// Default ReannounceTime is 10 years, won't announce by default.
if time.Since(tx.Time()) < pool.config.ReannounceTime {
@@ -517,6 +523,17 @@ func (pool *LegacyPool) Stats() (int, int) {
return pool.stats()
}
func (pool *LegacyPool) statsOverflowPool() int {
pool.mu.RLock()
defer pool.mu.RUnlock()
if pool.localBufferPool == nil {
return 0
}
return pool.localBufferPool.Size()
}
// stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
func (pool *LegacyPool) stats() (int, int) {
@@ -831,6 +848,8 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e
}
}
pool.addToOverflowPool(drop, isLocal)
// Kick out the underpriced remote transactions.
for _, tx := range drop {
log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap())
@@ -887,6 +906,29 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e
return replaced, nil
}
func (pool *LegacyPool) addToOverflowPool(drop types.Transactions, isLocal bool) {
// calculate total number of slots in drop. Accordingly add them to OverflowPool (if there is space)
availableSlotsOverflowPool := pool.availableSlotsOverflowPool()
if availableSlotsOverflowPool > 0 {
// transfer availableSlotsOverflowPool number of transactions slots from drop to OverflowPool
currentSlotsUsed := 0
for i, tx := range drop {
txSlots := numSlots(tx)
if currentSlotsUsed+txSlots <= availableSlotsOverflowPool {
from, _ := types.Sender(pool.signer, tx)
pool.localBufferPool.Add(tx)
log.Debug("adding to OverflowPool", "transaction", tx.Hash().String(), "from", from.String())
currentSlotsUsed += txSlots
} else {
log.Debug("not all got added to OverflowPool", "totalAdded", i+1)
return
}
}
} else {
log.Debug("adding to OverflowPool unsuccessful", "availableSlotsOverflowPool", availableSlotsOverflowPool)
}
}
// isGapped reports whether the given transaction is immediately executable.
func (pool *LegacyPool) isGapped(from common.Address, tx *types.Transaction) bool {
// Short circuit if transaction falls within the scope of the pending list
@@ -1333,7 +1375,6 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest,
reorgDurationTimer.Update(time.Since(t0))
}(time.Now())
defer close(done)
var promoteAddrs []common.Address
if dirtyAccounts != nil && reset == nil {
// Only dirty accounts need to be promoted, unless we're resetting.
@@ -1391,6 +1432,9 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest,
pool.changesSinceReorg = 0 // Reset change counter
pool.mu.Unlock()
// Transfer transactions from OverflowPool to MainPool for new block import
pool.transferTransactions()
// Notify subsystems for newly added transactions
for _, tx := range promoted {
addr, _ := types.Sender(pool.signer, tx)
@@ -2038,3 +2082,50 @@ func (t *lookup) RemotesBelowTip(threshold *big.Int) types.Transactions {
func numSlots(tx *types.Transaction) int {
return int((tx.Size() + txSlotSize - 1) / txSlotSize)
}
// transferTransactions moves transactions from OverflowPool to MainPool
func (pool *LegacyPool) transferTransactions() {
// Fail fast if the overflow pool is empty
if pool.localBufferPool.Size() == 0 {
return
}
maxMainPoolSize := int(pool.config.GlobalSlots + pool.config.GlobalQueue)
// Use pool.all.Slots() to get the total slots used by all transactions
currentMainPoolSize := pool.all.Slots()
if currentMainPoolSize >= maxMainPoolSize {
return
}
extraSlots := maxMainPoolSize - currentMainPoolSize
extraTransactions := (extraSlots + 3) / 4 // Since a transaction can take up to 4 slots
log.Debug("Will attempt to transfer from OverflowPool to MainPool", "transactions", extraTransactions)
txs := pool.localBufferPool.Flush(extraTransactions)
if len(txs) == 0 {
return
}
pool.Add(txs, true, false)
}
func (pool *LegacyPool) availableSlotsOverflowPool() int {
maxOverflowPoolSize := int(pool.config.OverflowPoolSlots)
availableSlots := maxOverflowPoolSize - pool.localBufferPool.Size()
if availableSlots > 0 {
return availableSlots
}
return 0
}
func (pool *LegacyPool) PrintTxStats() {
for _, l := range pool.pending {
for _, transaction := range l.txs.items {
from, _ := types.Sender(pool.signer, transaction)
fmt.Println("from: ", from, " Pending:", transaction.Hash().String(), transaction.GasFeeCap(), transaction.GasTipCap())
}
}
pool.localBufferPool.PrintTxStats()
fmt.Println("length of all: ", pool.all.Slots())
fmt.Println("----------------------------------------------------")
}

View File

@@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"github.com/stretchr/testify/assert"
)
var (
@@ -1739,6 +1740,7 @@ func TestRepricingKeepsLocals(t *testing.T) {
// Note, local transactions are never allowed to be dropped.
func TestUnderpricing(t *testing.T) {
t.Parallel()
testTxPoolConfig.OverflowPoolSlots = 5
// Create the pool to test the pricing enforcement with
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
@@ -1931,6 +1933,8 @@ func TestUnderpricingDynamicFee(t *testing.T) {
pool.config.GlobalSlots = 2
pool.config.GlobalQueue = 2
pool.config.OverflowPoolSlots = 0
// Keep track of transaction events to ensure all executables get announced
events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events)
@@ -1955,7 +1959,6 @@ func TestUnderpricingDynamicFee(t *testing.T) {
// Import the batch and that both pending and queued transactions match up
pool.addRemotes(txs) // Pend K0:0, K0:1; Que K1:1
pool.addLocal(ltx) // +K2:0 => Pend K0:0, K0:1, K2:0; Que K1:1
pending, queued := pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
@@ -1995,9 +1998,9 @@ func TestUnderpricingDynamicFee(t *testing.T) {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
if queued != 2 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
}
if err := validateEvents(events, 2); err != nil {
if err := validateEvents(events, 2); err != nil { // todo make it 4...After this validateEvents the pending becomes 3?!
t.Fatalf("additional event firing failed: %v", err)
}
if err := validatePoolInternals(pool); err != nil {
@@ -2012,11 +2015,12 @@ func TestUnderpricingDynamicFee(t *testing.T) {
if err := pool.addLocal(ltx); err != nil {
t.Fatalf("failed to add new underpriced local transaction: %v", err)
}
pending, queued = pool.Stats()
if pending != 3 {
if pending != 3 { // 3
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
if queued != 1 {
if queued != 1 { // 1
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
}
if err := validateEvents(events, 2); err != nil {
@@ -2032,41 +2036,51 @@ func TestUnderpricingDynamicFee(t *testing.T) {
func TestDualHeapEviction(t *testing.T) {
t.Parallel()
testTxPoolConfig.OverflowPoolSlots = 1
pool, _ := setupPoolWithConfig(eip1559Config)
defer pool.Close()
pool.config.GlobalSlots = 10
pool.config.GlobalQueue = 10
pool.config.GlobalSlots = 2
pool.config.GlobalQueue = 2
pool.config.OverflowPoolSlots = 1
var (
highTip, highCap *types.Transaction
baseFee int
highCapValue int64
highTipValue int64
)
check := func(tx *types.Transaction, name string) {
if pool.all.GetRemote(tx.Hash()) == nil {
t.Fatalf("highest %s transaction evicted from the pool", name)
t.Fatalf("highest %s transaction evicted from the pool, gasTip: %s, gasFeeCap: %s, hash: %s", name, highTip.GasTipCap().String(), highCap.GasFeeCap().String(), tx.Hash().String())
}
}
add := func(urgent bool) {
for i := 0; i < 20; i++ {
for i := 0; i < 4; i++ {
var tx *types.Transaction
// Create a test accounts and fund it
key, _ := crypto.GenerateKey()
testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000000))
if urgent {
tx = dynamicFeeTx(0, 100000, big.NewInt(int64(baseFee+1+i)), big.NewInt(int64(1+i)), key)
highTip = tx
if int64(1+i) > highTipValue || (int64(1+i) == highTipValue && int64(baseFee+1+i) > highTip.GasFeeCap().Int64()) {
highTipValue = int64(1 + i)
highTip = tx
}
} else {
tx = dynamicFeeTx(0, 100000, big.NewInt(int64(baseFee+200+i)), big.NewInt(1), key)
highCap = tx
if int64(baseFee+200+i) > highCapValue {
highCapValue = int64(baseFee + 200 + i)
highCap = tx
}
}
pool.addRemotesSync([]*types.Transaction{tx})
}
pending, queued := pool.Stats()
if pending+queued != 20 {
t.Fatalf("transaction count mismatch: have %d, want %d", pending+queued, 10)
if pending+queued != 4 {
t.Fatalf("transaction count mismatch: have %d, want %d, pending %d, queued %d, OverflowPool %d", pending+queued, 5, pending, queued, pool.localBufferPool.Size())
}
}
@@ -2231,6 +2245,50 @@ func TestReplacement(t *testing.T) {
}
}
func TestTransferTransactions(t *testing.T) {
t.Parallel()
testTxPoolConfig.OverflowPoolSlots = 1
pool, _ := setupPoolWithConfig(eip1559Config)
defer pool.Close()
pool.config.GlobalSlots = 1
pool.config.GlobalQueue = 2
// Create a number of test accounts and fund them
keys := make([]*ecdsa.PrivateKey, 5)
for i := 0; i < len(keys); i++ {
keys[i], _ = crypto.GenerateKey()
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
}
tx := dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[0])
from, _ := types.Sender(pool.signer, tx)
pool.addToOverflowPool([]*types.Transaction{tx}, true)
pending, queue := pool.Stats()
assert.Equal(t, 0, pending, "pending transactions mismatched")
assert.Equal(t, 0, queue, "queued transactions mismatched")
assert.Equal(t, 1, pool.statsOverflowPool(), "OverflowPool size unexpected")
tx2 := dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[1])
pool.addToOverflowPool([]*types.Transaction{tx2}, true)
assert.Equal(t, 1, pool.statsOverflowPool(), "OverflowPool size unexpected")
<-pool.requestPromoteExecutables(newAccountSet(pool.signer, from))
pending, queue = pool.Stats()
assert.Equal(t, 0, pending, "pending transactions mismatched")
assert.Equal(t, 1, queue, "queued transactions mismatched")
assert.Equal(t, 0, pool.statsOverflowPool(), "OverflowPool size unexpected")
tx3 := dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[2])
pool.addToOverflowPool([]*types.Transaction{tx3}, true)
pending, queue = pool.Stats()
assert.Equal(t, 1, pending, "pending transactions mismatched")
assert.Equal(t, 0, queue, "queued transactions mismatched")
assert.Equal(t, 1, pool.statsOverflowPool(), "OverflowPool size unexpected")
}
// Tests that the pool rejects replacement dynamic fee transactions that don't
// meet the minimum price bump required.
func TestReplacementDynamicFee(t *testing.T) {

View File

@@ -0,0 +1,171 @@
package legacypool
import (
"container/heap"
"fmt"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// txHeapItem implements the Interface interface (https://pkg.go.dev/container/heap#Interface) of heap so that it can be heapified
type txHeapItem struct {
tx *types.Transaction
timestamp int64 // Unix timestamp (nanoseconds) of when the transaction was added
index int
}
type txHeap []*txHeapItem
func (h txHeap) Len() int { return len(h) }
func (h txHeap) Less(i, j int) bool {
return h[i].timestamp < h[j].timestamp
}
func (h txHeap) Swap(i, j int) {
if i < 0 || j < 0 || i >= len(h) || j >= len(h) {
return // Silently fail if indices are out of bounds
}
h[i], h[j] = h[j], h[i]
if h[i] != nil {
h[i].index = i
}
if h[j] != nil {
h[j].index = j
}
}
func (h *txHeap) Push(x interface{}) {
item, ok := x.(*txHeapItem)
if !ok {
return
}
n := len(*h)
item.index = n
*h = append(*h, item)
}
func (h *txHeap) Pop() interface{} {
old := *h
n := len(old)
if n == 0 {
return nil // Return nil if the heap is empty
}
item := old[n-1]
old[n-1] = nil // avoid memory leak
*h = old[0 : n-1]
if item != nil {
item.index = -1 // for safety
}
return item
}
type TxOverflowPool struct {
txHeap txHeap
index map[common.Hash]*txHeapItem
mu sync.RWMutex
maxSize uint64
totalSize int
}
func NewTxOverflowPoolHeap(estimatedMaxSize uint64) *TxOverflowPool {
return &TxOverflowPool{
txHeap: make(txHeap, 0, estimatedMaxSize),
index: make(map[common.Hash]*txHeapItem, estimatedMaxSize),
maxSize: estimatedMaxSize,
}
}
func (tp *TxOverflowPool) Add(tx *types.Transaction) {
tp.mu.Lock()
defer tp.mu.Unlock()
if _, exists := tp.index[tx.Hash()]; exists {
// Transaction already in pool, ignore
return
}
if uint64(len(tp.txHeap)) >= tp.maxSize {
// Remove the oldest transaction to make space
oldestItem, ok := heap.Pop(&tp.txHeap).(*txHeapItem)
if !ok || oldestItem == nil {
return
}
delete(tp.index, oldestItem.tx.Hash())
tp.totalSize -= numSlots(oldestItem.tx)
OverflowPoolGauge.Dec(1)
}
item := &txHeapItem{
tx: tx,
timestamp: time.Now().UnixNano(),
}
heap.Push(&tp.txHeap, item)
tp.index[tx.Hash()] = item
tp.totalSize += numSlots(tx)
OverflowPoolGauge.Inc(1)
}
func (tp *TxOverflowPool) Get(hash common.Hash) (*types.Transaction, bool) {
tp.mu.RLock()
defer tp.mu.RUnlock()
if item, ok := tp.index[hash]; ok {
return item.tx, true
}
return nil, false
}
func (tp *TxOverflowPool) Remove(hash common.Hash) {
tp.mu.Lock()
defer tp.mu.Unlock()
if item, ok := tp.index[hash]; ok {
heap.Remove(&tp.txHeap, item.index)
delete(tp.index, hash)
tp.totalSize -= numSlots(item.tx)
OverflowPoolGauge.Dec(1)
}
}
func (tp *TxOverflowPool) Flush(n int) []*types.Transaction {
tp.mu.Lock()
defer tp.mu.Unlock()
if n > tp.txHeap.Len() {
n = tp.txHeap.Len()
}
txs := make([]*types.Transaction, n)
for i := 0; i < n; i++ {
item, ok := heap.Pop(&tp.txHeap).(*txHeapItem)
if !ok || item == nil {
continue
}
txs[i] = item.tx
delete(tp.index, item.tx.Hash())
tp.totalSize -= numSlots(item.tx)
}
OverflowPoolGauge.Dec(int64(n))
return txs
}
func (tp *TxOverflowPool) Len() int {
tp.mu.RLock()
defer tp.mu.RUnlock()
return tp.txHeap.Len()
}
func (tp *TxOverflowPool) Size() int {
tp.mu.RLock()
defer tp.mu.RUnlock()
return tp.totalSize
}
func (tp *TxOverflowPool) PrintTxStats() {
tp.mu.RLock()
defer tp.mu.RUnlock()
for _, item := range tp.txHeap {
tx := item.tx
fmt.Printf("Hash: %s, Timestamp: %d, GasFeeCap: %s, GasTipCap: %s\n",
tx.Hash().String(), item.timestamp, tx.GasFeeCap().String(), tx.GasTipCap().String())
}
}

View File

@@ -0,0 +1,266 @@
package legacypool
import (
"math/big"
rand2 "math/rand"
"testing"
"time"
"github.com/cometbft/cometbft/libs/rand"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Helper function to create a test transaction
func createTestTx(nonce uint64, gasPrice *big.Int) *types.Transaction {
to := common.HexToAddress("0x1234567890123456789012345678901234567890")
return types.NewTransaction(nonce, to, big.NewInt(1000), 21000, gasPrice, nil)
}
func TestNewTxOverflowPoolHeap(t *testing.T) {
pool := NewTxOverflowPoolHeap(0)
if pool == nil {
t.Fatal("NewTxOverflowPoolHeap returned nil")
}
if pool.Len() != 0 {
t.Errorf("New pool should be empty, got length %d", pool.Len())
}
}
func TestTxOverflowPoolHeapAdd(t *testing.T) {
pool := NewTxOverflowPoolHeap(1)
tx := createTestTx(1, big.NewInt(1000))
pool.Add(tx)
if pool.Len() != 1 {
t.Errorf("Pool should have 1 transaction, got %d", pool.Len())
}
// Add the same transaction again
pool.Add(tx)
if pool.Len() != 1 {
t.Errorf("Pool should still have 1 transaction after adding duplicate, got %d", pool.Len())
}
}
func TestTxOverflowPoolHeapGet(t *testing.T) {
pool := NewTxOverflowPoolHeap(1)
tx := createTestTx(1, big.NewInt(1000))
pool.Add(tx)
gotTx, exists := pool.Get(tx.Hash())
if !exists {
t.Fatal("Get returned false for existing transaction")
}
if gotTx.Hash() != tx.Hash() {
t.Errorf("Get returned wrong transaction. Want %v, got %v", tx.Hash(), gotTx.Hash())
}
_, exists = pool.Get(common.Hash{})
if exists {
t.Error("Get returned true for non-existent transaction")
}
}
func TestTxOverflowPoolHeapRemove(t *testing.T) {
pool := NewTxOverflowPoolHeap(1)
tx := createTestTx(1, big.NewInt(1000))
pool.Add(tx)
pool.Remove(tx.Hash())
if pool.Len() != 0 {
t.Errorf("Pool should be empty after removing the only transaction, got length %d", pool.Len())
}
// Try to remove non-existent transaction
pool.Remove(common.Hash{})
if pool.Len() != 0 {
t.Error("Removing non-existent transaction should not affect pool size")
}
}
func TestTxOverflowPoolHeapPopN(t *testing.T) {
pool := NewTxOverflowPoolHeap(3)
tx1 := createTestTx(1, big.NewInt(1000))
tx2 := createTestTx(2, big.NewInt(2000))
tx3 := createTestTx(3, big.NewInt(3000))
pool.Add(tx1)
time.Sleep(time.Millisecond) // Ensure different timestamps
pool.Add(tx2)
time.Sleep(time.Millisecond)
pool.Add(tx3)
popped := pool.Flush(2)
if len(popped) != 2 {
t.Fatalf("PopN(2) should return 2 transactions, got %d", len(popped))
}
if popped[0].Hash() != tx1.Hash() || popped[1].Hash() != tx2.Hash() {
t.Error("PopN returned transactions in wrong order")
}
if pool.Len() != 1 {
t.Errorf("Pool should have 1 transaction left, got %d", pool.Len())
}
// Pop more than available
popped = pool.Flush(2)
if len(popped) != 1 {
t.Fatalf("PopN(2) should return 1 transaction when only 1 is left, got %d", len(popped))
}
if popped[0].Hash() != tx3.Hash() {
t.Error("PopN returned wrong transaction")
}
if pool.Len() != 0 {
t.Errorf("Pool should be empty, got length %d", pool.Len())
}
}
func TestTxOverflowPoolHeapOrdering(t *testing.T) {
pool := NewTxOverflowPoolHeap(3)
tx1 := createTestTx(1, big.NewInt(1000))
tx2 := createTestTx(2, big.NewInt(2000))
tx3 := createTestTx(3, big.NewInt(3000))
pool.Add(tx2)
time.Sleep(time.Millisecond) // Ensure different timestamps
pool.Add(tx1)
pool.Add(tx3) // Added immediately after tx1, should have same timestamp but higher sequence
popped := pool.Flush(3)
if len(popped) != 3 {
t.Fatalf("PopN(3) should return 3 transactions, got %d", len(popped))
}
if popped[0].Hash() != tx2.Hash() || popped[1].Hash() != tx1.Hash() || popped[2].Hash() != tx3.Hash() {
t.Error("Transactions not popped in correct order (earliest timestamp first, then by sequence)")
}
}
func TestTxOverflowPoolHeapLen(t *testing.T) {
pool := NewTxOverflowPoolHeap(2)
if pool.Len() != 0 {
t.Errorf("New pool should have length 0, got %d", pool.Len())
}
pool.Add(createTestTx(1, big.NewInt(1000)))
if pool.Len() != 1 {
t.Errorf("Pool should have length 1 after adding a transaction, got %d", pool.Len())
}
pool.Add(createTestTx(2, big.NewInt(2000)))
if pool.Len() != 2 {
t.Errorf("Pool should have length 2 after adding another transaction, got %d", pool.Len())
}
pool.Flush(1)
if pool.Len() != 1 {
t.Errorf("Pool should have length 1 after popping a transaction, got %d", pool.Len())
}
}
// Helper function to create a random test transaction
func createRandomTestTx() *types.Transaction {
nonce := uint64(rand.Intn(1000000))
to := common.BytesToAddress(rand.Bytes(20))
amount := new(big.Int).Rand(rand2.New(rand2.NewSource(rand.Int63())), big.NewInt(1e18))
gasLimit := uint64(21000)
gasPrice := new(big.Int).Rand(rand2.New(rand2.NewSource(rand.Int63())), big.NewInt(1e9))
data := rand.Bytes(100)
return types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data)
}
func createRandomTestTxs(n int) []*types.Transaction {
txs := make([]*types.Transaction, n)
for i := 0; i < n; i++ {
txs[i] = createRandomTestTx()
}
return txs
}
// goos: darwin
// goarch: arm64
// pkg: github.com/ethereum/go-ethereum/core/txpool/legacypool
// BenchmarkTxOverflowPoolHeapAdd-8 813326 2858 ns/op
func BenchmarkTxOverflowPoolHeapAdd(b *testing.B) {
pool := NewTxOverflowPoolHeap(uint64(b.N))
txs := createRandomTestTxs(b.N)
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.Add(txs[i])
}
}
// BenchmarkTxOverflowPoolHeapGet-8 32613938 35.63 ns/op
func BenchmarkTxOverflowPoolHeapGet(b *testing.B) {
pool := NewTxOverflowPoolHeap(1000)
txs := createRandomTestTxs(1000)
for _, tx := range txs {
pool.Add(tx)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.Get(txs[i%1000].Hash())
}
}
// BenchmarkTxOverflowPoolHeapRemove-8 3020841 417.8 ns/op
func BenchmarkTxOverflowPoolHeapRemove(b *testing.B) {
pool := NewTxOverflowPoolHeap(uint64(b.N))
txs := createRandomTestTxs(b.N)
for _, tx := range txs {
pool.Add(tx)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.Remove(txs[i].Hash())
}
}
// BenchmarkTxOverflowPoolHeapFlush-8 42963656 29.90 ns/op
func BenchmarkTxOverflowPoolHeapFlush(b *testing.B) {
pool := NewTxOverflowPoolHeap(1000)
txs := createRandomTestTxs(1000)
for _, tx := range txs {
pool.Add(tx)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.Flush(10)
}
}
// BenchmarkTxOverflowPoolHeapLen-8 79147188 20.07 ns/op
func BenchmarkTxOverflowPoolHeapLen(b *testing.B) {
pool := NewTxOverflowPoolHeap(1000)
txs := createRandomTestTxs(1000)
for _, tx := range txs {
pool.Add(tx)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.Len()
}
}
// BenchmarkTxOverflowPoolHeapAddRemove-8 902896 1546 ns/op
func BenchmarkTxOverflowPoolHeapAddRemove(b *testing.B) {
pool := NewTxOverflowPoolHeap(uint64(b.N))
txs := createRandomTestTxs(b.N)
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.Add(txs[i])
pool.Remove(txs[i].Hash())
}
}
// BenchmarkTxOverflowPoolHeapAddFlush-8 84417 14899 ns/op
func BenchmarkTxOverflowPoolHeapAddFlush(b *testing.B) {
pool := NewTxOverflowPoolHeap(uint64(b.N * 10))
txs := createRandomTestTxs(b.N * 10)
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < 10; j++ {
pool.Add(txs[i*10+j])
}
pool.Flush(10)
}
}

View File

@@ -1,10 +1,9 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package ethapi
package types
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common/hexutil"
)

View File

@@ -0,0 +1,43 @@
package types
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
type AccountStorage struct {
StorageRoot *common.Hash
StorageSlots map[common.Hash]common.Hash
}
func (a *AccountStorage) UnmarshalJSON(data []byte) error {
var hash common.Hash
if err := json.Unmarshal(data, &hash); err == nil {
a.StorageRoot = &hash
return nil
}
return json.Unmarshal(data, &a.StorageSlots)
}
func (a AccountStorage) MarshalJSON() ([]byte, error) {
if a.StorageRoot != nil {
return json.Marshal(*a.StorageRoot)
}
return json.Marshal(a.StorageSlots)
}
type KnownAccounts map[common.Address]AccountStorage
// It is known that marshaling is broken
// https://github.com/golang/go/issues/55890
//go:generate go run github.com/fjl/gencodec -type TransactionOpts -out gen_tx_opts_json.go
type TransactionOpts struct {
KnownAccounts KnownAccounts `json:"knownAccounts"`
BlockNumberMin *hexutil.Uint64 `json:"blockNumberMin,omitempty"`
BlockNumberMax *hexutil.Uint64 `json:"blockNumberMax,omitempty"`
TimestampMin *hexutil.Uint64 `json:"timestampMin,omitempty"`
TimestampMax *hexutil.Uint64 `json:"timestampMax,omitempty"`
}

View File

@@ -1,4 +1,4 @@
package ethapi_test
package types
import (
"encoding/json"
@@ -7,7 +7,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/ethapi"
)
func ptr(hash common.Hash) *common.Hash {
@@ -23,15 +22,15 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
name string
input string
mustFail bool
expected ethapi.TransactionOpts
expected TransactionOpts
}{
{
"StateRoot",
`{"knownAccounts":{"0x6b3A8798E5Fb9fC5603F3aB5eA2e8136694e55d0":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563"}}`,
false,
ethapi.TransactionOpts{
KnownAccounts: map[common.Address]ethapi.AccountStorage{
common.HexToAddress("0x6b3A8798E5Fb9fC5603F3aB5eA2e8136694e55d0"): ethapi.AccountStorage{
TransactionOpts{
KnownAccounts: map[common.Address]AccountStorage{
common.HexToAddress("0x6b3A8798E5Fb9fC5603F3aB5eA2e8136694e55d0"): AccountStorage{
StorageRoot: ptr(common.HexToHash("0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")),
},
},
@@ -41,9 +40,9 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
"StorageSlots",
`{"knownAccounts":{"0x6b3A8798E5Fb9fC5603F3aB5eA2e8136694e55d0":{"0xc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8":"0x0000000000000000000000000000000000000000000000000000000000000000"}}}`,
false,
ethapi.TransactionOpts{
KnownAccounts: map[common.Address]ethapi.AccountStorage{
common.HexToAddress("0x6b3A8798E5Fb9fC5603F3aB5eA2e8136694e55d0"): ethapi.AccountStorage{
TransactionOpts{
KnownAccounts: map[common.Address]AccountStorage{
common.HexToAddress("0x6b3A8798E5Fb9fC5603F3aB5eA2e8136694e55d0"): AccountStorage{
StorageRoot: nil,
StorageSlots: map[common.Hash]common.Hash{
common.HexToHash("0xc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8"): common.HexToHash("0x"),
@@ -56,15 +55,15 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
"EmptyObject",
`{"knownAccounts":{}}`,
false,
ethapi.TransactionOpts{
KnownAccounts: make(map[common.Address]ethapi.AccountStorage),
TransactionOpts{
KnownAccounts: make(map[common.Address]AccountStorage),
},
},
{
"EmptyStrings",
`{"knownAccounts":{"":""}}`,
true,
ethapi.TransactionOpts{
TransactionOpts{
KnownAccounts: nil,
},
},
@@ -72,7 +71,7 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
"BlockNumberMin",
`{"blockNumberMin":"0x1"}`,
false,
ethapi.TransactionOpts{
TransactionOpts{
BlockNumberMin: u64Ptr(1),
},
},
@@ -80,7 +79,7 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
"BlockNumberMax",
`{"blockNumberMin":"0x1", "blockNumberMax":"0x2"}`,
false,
ethapi.TransactionOpts{
TransactionOpts{
BlockNumberMin: u64Ptr(1),
BlockNumberMax: u64Ptr(2),
},
@@ -89,7 +88,7 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
"TimestampMin",
`{"timestampMin":"0xffff"}`,
false,
ethapi.TransactionOpts{
TransactionOpts{
TimestampMin: u64Ptr(0xffff),
},
},
@@ -97,7 +96,7 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
"TimestampMax",
`{"timestampMax":"0xffffff"}`,
false,
ethapi.TransactionOpts{
TransactionOpts{
TimestampMax: u64Ptr(0xffffff),
},
},
@@ -105,7 +104,7 @@ func TestTransactionOptsJSONUnMarshalTrip(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var opts ethapi.TransactionOpts
var opts TransactionOpts
err := json.Unmarshal([]byte(test.input), &opts)
if test.mustFail && err == nil {
t.Errorf("Test %s should fail", test.name)

View File

@@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -737,7 +736,7 @@ func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) er
//
// If the transaction was a contract creation use the TransactionReceipt method to get the
// contract address after the transaction has been mined.
func (ec *Client) SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error {
func (ec *Client) SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts types.TransactionOpts) error {
data, err := tx.MarshalBinary()
if err != nil {
return err

View File

@@ -34,7 +34,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
@@ -770,9 +769,9 @@ func sendTransactionConditional(ec *Client) error {
}
root := common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
return ec.SendTransactionConditional(context.Background(), tx, ethapi.TransactionOpts{
KnownAccounts: map[common.Address]ethapi.AccountStorage{
testAddr: ethapi.AccountStorage{
return ec.SendTransactionConditional(context.Background(), tx, types.TransactionOpts{
KnownAccounts: map[common.Address]types.AccountStorage{
testAddr: types.AccountStorage{
StorageRoot: &root,
},
},

View File

@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
@@ -39,7 +38,7 @@ import (
// TransactionConditionalSender injects the conditional transaction into the pending pool for execution after verification.
type TransactionConditionalSender interface {
SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts ethapi.TransactionOpts) error
SendTransactionConditional(ctx context.Context, tx *types.Transaction, opts types.TransactionOpts) error
}
// Client exposes the methods provided by the Ethereum RPC client.

View File

@@ -2314,7 +2314,7 @@ func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.B
// SendRawTransactionConditional will add the signed transaction to the transaction pool.
// The sender/bundler is responsible for signing the transaction
func (s *TransactionAPI) SendRawTransactionConditional(ctx context.Context, input hexutil.Bytes, opts TransactionOpts) (common.Hash, error) {
func (s *TransactionAPI) SendRawTransactionConditional(ctx context.Context, input hexutil.Bytes, opts types.TransactionOpts) (common.Hash, error) {
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(input); err != nil {
return common.Hash{}, err
@@ -2324,7 +2324,7 @@ func (s *TransactionAPI) SendRawTransactionConditional(ctx context.Context, inpu
if state == nil || err != nil {
return common.Hash{}, err
}
if err := opts.Check(header.Number.Uint64(), header.Time, state); err != nil {
if err := TxOptsCheck(opts, header.Number.Uint64(), header.Time, state); err != nil {
return common.Hash{}, err
}
return SubmitTransaction(ctx, s.b, tx)

View File

@@ -2,52 +2,15 @@ package ethapi
import (
"bytes"
"encoding/json"
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
)
type AccountStorage struct {
StorageRoot *common.Hash
StorageSlots map[common.Hash]common.Hash
}
func (a *AccountStorage) UnmarshalJSON(data []byte) error {
var hash common.Hash
if err := json.Unmarshal(data, &hash); err == nil {
a.StorageRoot = &hash
return nil
}
return json.Unmarshal(data, &a.StorageSlots)
}
func (a AccountStorage) MarshalJSON() ([]byte, error) {
if a.StorageRoot != nil {
return json.Marshal(*a.StorageRoot)
}
return json.Marshal(a.StorageSlots)
}
type KnownAccounts map[common.Address]AccountStorage
// It is known that marshaling is broken
// https://github.com/golang/go/issues/55890
//go:generate go run github.com/fjl/gencodec -type TransactionOpts -out gen_tx_opts_json.go
type TransactionOpts struct {
KnownAccounts KnownAccounts `json:"knownAccounts"`
BlockNumberMin *hexutil.Uint64 `json:"blockNumberMin,omitempty"`
BlockNumberMax *hexutil.Uint64 `json:"blockNumberMax,omitempty"`
TimestampMin *hexutil.Uint64 `json:"timestampMin,omitempty"`
TimestampMax *hexutil.Uint64 `json:"timestampMax,omitempty"`
}
const MaxNumberOfEntries = 1000
func (o *TransactionOpts) Check(blockNumber uint64, timeStamp uint64, statedb *state.StateDB) error {
func TxOptsCheck(o types.TransactionOpts, blockNumber uint64, timeStamp uint64, statedb *state.StateDB) error {
if o.BlockNumberMin != nil && blockNumber < uint64(*o.BlockNumberMin) {
return errors.New("BlockNumberMin condition not met")
}
@@ -71,10 +34,10 @@ func (o *TransactionOpts) Check(blockNumber uint64, timeStamp uint64, statedb *s
if counter > MaxNumberOfEntries {
return errors.New("knownAccounts too large")
}
return o.CheckStorage(statedb)
return TxOptsCheckStorage(o, statedb)
}
func (o *TransactionOpts) CheckStorage(statedb *state.StateDB) error {
func TxOptsCheckStorage(o types.TransactionOpts, statedb *state.StateDB) error {
for address, accountStorage := range o.KnownAccounts {
if accountStorage.StorageRoot != nil {
rootHash := statedb.GetRoot(address)