Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d6f4499
feat: fee history
sbackend123 May 12, 2026
b03a321
feat: draft retry logic with
sbackend123 May 14, 2026
97db71f
feat: clean up retry logic + fixes
sbackend123 May 16, 2026
4e3d724
feat: clean up2 + debugging
sbackend123 May 16, 2026
006bb44
feat: tests, improvement, debugging
sbackend123 May 17, 2026
48b637e
feat: logging, more tests, clean up
sbackend123 May 18, 2026
9dad7f5
fix: metrics
sbackend123 May 18, 2026
b015979
fix: debugging + tests
sbackend123 May 19, 2026
30aa5c7
Merge branch 'master' into feat/new-gas-estimation
sbackend123 May 20, 2026
f681124
fix: cleanup, fix namings
sbackend123 May 20, 2026
32551cb
fix: fix assigning
sbackend123 May 20, 2026
dda24dd
fix: fix old tests
sbackend123 May 20, 2026
279359b
fix: fix mock
sbackend123 May 20, 2026
e57022e
fix: fix contract tests
sbackend123 May 20, 2026
5517301
fix: fix data race
sbackend123 May 20, 2026
185b86c
fix: refactoring
sbackend123 May 28, 2026
aa5b45d
Merge branch 'master' into feat/new-gas-estimation
sbackend123 May 28, 2026
e94aefc
fix: move corner cases logic from branch
sbackend123 Jun 3, 2026
19cd2db
fix: make linter happy
sbackend123 Jun 3, 2026
80f7edb
fix: make linter happy + renaming + test
sbackend123 Jun 3, 2026
8c744de
fix: fix log
sbackend123 Jun 7, 2026
dadfeee
fix: addressing review comments
sbackend123 Jun 9, 2026
3a0d533
fix: linter error
sbackend123 Jun 9, 2026
955285d
fix: big refactoring
sbackend123 Jun 11, 2026
42f6a97
fix: simplify resuming transactions
sbackend123 Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions cmd/bee/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"io"
"math/big"
"os"
"path/filepath"
"strings"
Expand All @@ -17,6 +18,7 @@ import (
"github.com/ethersphere/bee/v2/pkg/log"
"github.com/ethersphere/bee/v2/pkg/node"
"github.com/ethersphere/bee/v2/pkg/swarm"
"github.com/ethersphere/bee/v2/pkg/transaction"
p2pforge "github.com/ipshipyard/p2p-forge/client"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -101,6 +103,14 @@ const (
configKeyBlockchainRpcTLSTimeout = "blockchain-rpc.tls-timeout"
configKeyBlockchainRpcIdleTimeout = "blockchain-rpc.idle-timeout"
configKeyBlockchainRpcKeepalive = "blockchain-rpc.keepalive"

// transaction retry
optionNameTransactionRetryMaxRetries = "transaction-retry-max-retries"
optionNameTransactionRetryDelay = "transaction-retry-delay"
optionNameTransactionRetryGasIncreasePercent = "transaction-retry-gas-increase-percent"
optionNameTransactionRetryMaxTxPriceWei = "transaction-retry-max-tx-price-wei"
optionNameFeeHistoryBlockCount = "fee-history-block-count"
optionNameFeeHistoryRewardPercentiles = "fee-history-reward-percentiles"
)

var blockchainRpcConfigPairs = []struct{ flat, dotted string }{
Expand Down Expand Up @@ -310,6 +320,8 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().String(optionNameStakingAddress, "", "staking contract address")
cmd.Flags().Uint64(optionNameBlockTime, 5, "chain block time")
cmd.Flags().Uint64(optionNameBlockSyncInterval, 10, "block number cache sync interval in blocks")
cmd.Flags().Uint64(optionNameFeeHistoryBlockCount, 100, "eth_feeHistory block count for fee hints")
cmd.Flags().String(optionNameFeeHistoryRewardPercentiles, "10,50,90", "comma-separated reward percentiles for eth_feeHistory")
cmd.Flags().Duration(optionWarmUpTime, time.Minute*5, "maximum node warmup duration; proceeds when stable or after this time")
cmd.Flags().Bool(optionNameMainNet, true, "triggers connect to main net bootnodes.")
cmd.Flags().Bool(optionNameRetrievalCaching, true, "enable forwarded content caching")
Expand All @@ -329,6 +341,10 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().Bool(optionSkipPostageSnapshot, false, "skip postage snapshot")
cmd.Flags().Uint64(optionNameMinimumGasTipCap, 0, "minimum gas tip cap in wei for transactions, 0 means use suggested gas tip cap")
cmd.Flags().Uint64(optionNameGasLimitFallback, 500_000, "gas limit fallback when estimation fails for contract transactions")
cmd.Flags().Int(optionNameTransactionRetryMaxRetries, 5, "maximum broadcast attempts for SendWithRetry (e.g. redistribution txs)")
cmd.Flags().Duration(optionNameTransactionRetryDelay, time.Minute, "how long to wait for a receipt before escalating fees in transactions with retry")
cmd.Flags().Int(optionNameTransactionRetryGasIncreasePercent, 20, "percent increase applied to priority fee after each transactions with retry escalation step")
cmd.Flags().Uint64(optionNameTransactionRetryMaxTxPriceWei, 0, "maximum maxFeePerGas in wei per gas for transactions with retry")
cmd.Flags().Bool(optionNameP2PWSSEnable, false, "Enable Secure WebSocket P2P connections")
cmd.Flags().String(optionP2PWSSAddr, ":1635", "p2p wss address")
cmd.Flags().String(optionNATWSSAddr, "", "WSS NAT exposed address")
Expand Down Expand Up @@ -376,6 +392,18 @@ func (c *command) bindBlockchainRpcConfig(cmd *cobra.Command) {
}
}

func txRetryConfigFromCommand(c *command) transaction.TransactionsRetryConfig {
cfg := transaction.TransactionsRetryConfig{
MaxRetries: c.config.GetInt(optionNameTransactionRetryMaxRetries),
RetryDelay: c.config.GetDuration(optionNameTransactionRetryDelay),
GasIncreasePercent: c.config.GetInt(optionNameTransactionRetryGasIncreasePercent),
}
if v := c.config.GetUint64(optionNameTransactionRetryMaxTxPriceWei); v != 0 {
cfg.MaxTxPrice = new(big.Int).SetUint64(v)
}
return cfg
}

func newLogger(cmd *cobra.Command, verbosity string) (log.Logger, error) {
var (
sink = cmd.OutOrStdout()
Expand Down
8 changes: 8 additions & 0 deletions cmd/bee/cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ func (c *command) initDeployCmd() error {

ctx := cmd.Context()

feeHistoryRewardPerc, err := node.ParseFeeHistoryRewardPercentiles(c.config.GetString(optionNameFeeHistoryRewardPercentiles))
if err != nil {
return err
}

swapBackend, overlayEthAddress, chainID, transactionMonitor, transactionService, err := node.InitChain(
ctx,
logger,
Expand All @@ -60,6 +65,9 @@ func (c *command) initDeployCmd() error {
Keepalive: c.config.GetDuration(configKeyBlockchainRpcKeepalive),
},
c.config.GetUint64(optionNameBlockSyncInterval),
c.config.GetUint64(optionNameFeeHistoryBlockCount),
feeHistoryRewardPerc,
txRetryConfigFromCommand(c),
)
if err != nil {
return err
Expand Down
141 changes: 76 additions & 65 deletions cmd/bee/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo
}
}

feeHistoryRewardPerc, err := node.ParseFeeHistoryRewardPercentiles(c.config.GetString(optionNameFeeHistoryRewardPercentiles))
if err != nil {
return nil, err
}

signerConfig, err := c.configureSigner(cmd, logger)
if err != nil {
return nil, fmt.Errorf("configure signer: %w", err)
Expand Down Expand Up @@ -286,71 +291,77 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo
}

b, err := node.NewBee(ctx, c.config.GetString(optionNameP2PAddr), signerConfig.publicKey, signerConfig.signer, networkID, logger, signerConfig.libp2pPrivateKey, signerConfig.pssPrivateKey, signerConfig.session, &node.Options{
Addr: c.config.GetString(optionNameP2PAddr),
AllowPrivateCIDRs: c.config.GetBool(optionNameAllowPrivateCIDRs),
APIAddr: c.config.GetString(optionNameAPIAddr),
EnableWSS: c.config.GetBool(optionNameP2PWSSEnable),
WSSAddr: c.config.GetString(optionP2PWSSAddr),
AutoTLSStorageDir: filepath.Join(c.config.GetString(optionNameDataDir), "autotls"),
BlockchainRpcEndpoint: c.config.GetString(configKeyBlockchainRpcEndpoint),
BlockchainRpcDialTimeout: c.config.GetDuration(configKeyBlockchainRpcDialTimeout),
BlockchainRpcTLSTimeout: c.config.GetDuration(configKeyBlockchainRpcTLSTimeout),
BlockchainRpcIdleTimeout: c.config.GetDuration(configKeyBlockchainRpcIdleTimeout),
BlockchainRpcKeepalive: c.config.GetDuration(configKeyBlockchainRpcKeepalive),
BlockProfile: c.config.GetBool(optionNamePProfBlock),
BlockTime: networkConfig.blockTime,
BlockSyncInterval: c.config.GetUint64(optionNameBlockSyncInterval),
BootnodeMode: bootNode,
Bootnodes: networkConfig.bootNodes,
CacheCapacity: c.config.GetUint64(optionNameCacheCapacity),
AutoTLSCAEndpoint: c.config.GetString(optionAutoTLSCAEndpoint),
ChainID: networkConfig.chainID,
ChequebookEnable: c.config.GetBool(optionNameChequebookEnable),
CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins),
DataDir: c.config.GetString(optionNameDataDir),
DBBlockCacheCapacity: c.config.GetUint64(optionNameDBBlockCacheCapacity),
DBDisableSeeksCompaction: c.config.GetBool(optionNameDBDisableSeeksCompaction),
DBOpenFilesLimit: c.config.GetUint64(optionNameDBOpenFilesLimit),
DBWriteBufferSize: c.config.GetUint64(optionNameDBWriteBufferSize),
EnableStorageIncentives: c.config.GetBool(optionNameStorageIncentivesEnable),
EnableWS: c.config.GetBool(optionNameP2PWSEnable),
AutoTLSDomain: c.config.GetString(optionAutoTLSDomain),
AutoTLSRegistrationEndpoint: c.config.GetString(optionAutoTLSRegistrationEndpoint),
FullNodeMode: fullNode,
Logger: logger,
MinimumGasTipCap: c.config.GetUint64(optionNameMinimumGasTipCap),
GasLimitFallback: c.config.GetUint64(optionNameGasLimitFallback),
MinimumStorageRadius: c.config.GetUint(optionMinimumStorageRadius),
MutexProfile: c.config.GetBool(optionNamePProfMutex),
NATAddr: c.config.GetString(optionNameNATAddr),
NATWSSAddr: c.config.GetString(optionNATWSSAddr),
NeighborhoodSuggester: neighborhoodSuggester,
PaymentEarly: c.config.GetInt64(optionNamePaymentEarly),
PaymentThreshold: c.config.GetString(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetInt64(optionNamePaymentTolerance),
PostageContractAddress: c.config.GetString(optionNamePostageContractAddress),
PostageContractStartBlock: c.config.GetUint64(optionNamePostageContractStartBlock),
PriceOracleAddress: c.config.GetString(optionNamePriceOracleAddress),
RedistributionContractAddress: c.config.GetString(optionNameRedistributionAddress),
ReserveCapacityDoubling: c.config.GetInt(optionReserveCapacityDoubling),
ResolverConnectionCfgs: resolverCfgs,
Resync: c.config.GetBool(optionNameResync),
RetrievalCaching: c.config.GetBool(optionNameRetrievalCaching),
SkipPostageSnapshot: c.config.GetBool(optionSkipPostageSnapshot),
StakingContractAddress: c.config.GetString(optionNameStakingAddress),
StatestoreCacheCapacity: c.config.GetUint64(optionNameStateStoreCacheCapacity),
StaticNodes: staticNodes,
SwapEnable: c.config.GetBool(optionNameSwapEnable),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapInitialDeposit: c.config.GetString(optionNameSwapInitialDeposit),
TargetNeighborhood: c.config.GetString(optionNameTargetNeighborhood),
TracingEnabled: c.config.GetBool(optionNameTracingEnabled),
TracingEndpoint: tracingEndpoint,
TracingServiceName: c.config.GetString(optionNameTracingServiceName),
TrxDebugMode: c.config.GetBool(optionNameTransactionDebugMode),
WarmupTime: c.config.GetDuration(optionWarmUpTime),
WelcomeMessage: c.config.GetString(optionWelcomeMessage),
WhitelistedWithdrawalAddress: c.config.GetStringSlice(optionNameWhitelistedWithdrawalAddress),
Addr: c.config.GetString(optionNameP2PAddr),
AllowPrivateCIDRs: c.config.GetBool(optionNameAllowPrivateCIDRs),
APIAddr: c.config.GetString(optionNameAPIAddr),
EnableWSS: c.config.GetBool(optionNameP2PWSSEnable),
WSSAddr: c.config.GetString(optionP2PWSSAddr),
AutoTLSStorageDir: filepath.Join(c.config.GetString(optionNameDataDir), "autotls"),
BlockchainRpcEndpoint: c.config.GetString(configKeyBlockchainRpcEndpoint),
BlockchainRpcDialTimeout: c.config.GetDuration(configKeyBlockchainRpcDialTimeout),
BlockchainRpcTLSTimeout: c.config.GetDuration(configKeyBlockchainRpcTLSTimeout),
BlockchainRpcIdleTimeout: c.config.GetDuration(configKeyBlockchainRpcIdleTimeout),
BlockchainRpcKeepalive: c.config.GetDuration(configKeyBlockchainRpcKeepalive),
BlockProfile: c.config.GetBool(optionNamePProfBlock),
BlockTime: networkConfig.blockTime,
BlockSyncInterval: c.config.GetUint64(optionNameBlockSyncInterval),
FeeHistoryBlockCount: c.config.GetUint64(optionNameFeeHistoryBlockCount),
FeeHistoryRewardPercentiles: feeHistoryRewardPerc,
TransactionRetryMaxRetries: c.config.GetInt(optionNameTransactionRetryMaxRetries),
TransactionRetryDelay: c.config.GetDuration(optionNameTransactionRetryDelay),
TransactionRetryGasIncreasePercent: c.config.GetInt(optionNameTransactionRetryGasIncreasePercent),
TransactionRetryMaxTxPriceWei: c.config.GetUint64(optionNameTransactionRetryMaxTxPriceWei),
BootnodeMode: bootNode,
Bootnodes: networkConfig.bootNodes,
CacheCapacity: c.config.GetUint64(optionNameCacheCapacity),
AutoTLSCAEndpoint: c.config.GetString(optionAutoTLSCAEndpoint),
ChainID: networkConfig.chainID,
ChequebookEnable: c.config.GetBool(optionNameChequebookEnable),
CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins),
DataDir: c.config.GetString(optionNameDataDir),
DBBlockCacheCapacity: c.config.GetUint64(optionNameDBBlockCacheCapacity),
DBDisableSeeksCompaction: c.config.GetBool(optionNameDBDisableSeeksCompaction),
DBOpenFilesLimit: c.config.GetUint64(optionNameDBOpenFilesLimit),
DBWriteBufferSize: c.config.GetUint64(optionNameDBWriteBufferSize),
EnableStorageIncentives: c.config.GetBool(optionNameStorageIncentivesEnable),
EnableWS: c.config.GetBool(optionNameP2PWSEnable),
AutoTLSDomain: c.config.GetString(optionAutoTLSDomain),
AutoTLSRegistrationEndpoint: c.config.GetString(optionAutoTLSRegistrationEndpoint),
FullNodeMode: fullNode,
Logger: logger,
MinimumGasTipCap: c.config.GetUint64(optionNameMinimumGasTipCap),
GasLimitFallback: c.config.GetUint64(optionNameGasLimitFallback),
MinimumStorageRadius: c.config.GetUint(optionMinimumStorageRadius),
MutexProfile: c.config.GetBool(optionNamePProfMutex),
NATAddr: c.config.GetString(optionNameNATAddr),
NATWSSAddr: c.config.GetString(optionNATWSSAddr),
NeighborhoodSuggester: neighborhoodSuggester,
PaymentEarly: c.config.GetInt64(optionNamePaymentEarly),
PaymentThreshold: c.config.GetString(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetInt64(optionNamePaymentTolerance),
PostageContractAddress: c.config.GetString(optionNamePostageContractAddress),
PostageContractStartBlock: c.config.GetUint64(optionNamePostageContractStartBlock),
PriceOracleAddress: c.config.GetString(optionNamePriceOracleAddress),
RedistributionContractAddress: c.config.GetString(optionNameRedistributionAddress),
ReserveCapacityDoubling: c.config.GetInt(optionReserveCapacityDoubling),
ResolverConnectionCfgs: resolverCfgs,
Resync: c.config.GetBool(optionNameResync),
RetrievalCaching: c.config.GetBool(optionNameRetrievalCaching),
SkipPostageSnapshot: c.config.GetBool(optionSkipPostageSnapshot),
StakingContractAddress: c.config.GetString(optionNameStakingAddress),
StatestoreCacheCapacity: c.config.GetUint64(optionNameStateStoreCacheCapacity),
StaticNodes: staticNodes,
SwapEnable: c.config.GetBool(optionNameSwapEnable),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapInitialDeposit: c.config.GetString(optionNameSwapInitialDeposit),
TargetNeighborhood: c.config.GetString(optionNameTargetNeighborhood),
TracingEnabled: c.config.GetBool(optionNameTracingEnabled),
TracingEndpoint: tracingEndpoint,
TracingServiceName: c.config.GetString(optionNameTracingServiceName),
TrxDebugMode: c.config.GetBool(optionNameTransactionDebugMode),
WarmupTime: c.config.GetDuration(optionWarmUpTime),
WelcomeMessage: c.config.GetString(optionWelcomeMessage),
WhitelistedWithdrawalAddress: c.config.GetStringSlice(optionNameWhitelistedWithdrawalAddress),
})

return b, err
Expand Down
17 changes: 10 additions & 7 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ const (
SwarmActPublisherHeader = "Swarm-Act-Publisher"
SwarmActHistoryAddressHeader = "Swarm-Act-History-Address"

ImmutableHeader = "Immutable"
GasPriceHeader = "Gas-Price"
GasLimitHeader = "Gas-Limit"
ETagHeader = "ETag"
ImmutableHeader = "Immutable"
GasPriceHeader = "Gas-Price"
GasLimitHeader = "Gas-Limit"
DisableRetryHeader = "Disable-Retry"
ETagHeader = "ETag"

AuthorizationHeader = "Authorization"
AcceptEncodingHeader = "Accept-Encoding"
Expand Down Expand Up @@ -557,8 +558,9 @@ func (s *Service) gasConfigMiddleware(handlerName string) func(h http.Handler) h
logger := s.logger.WithName(handlerName).Build()

headers := struct {
GasPrice *big.Int `map:"Gas-Price"`
GasLimit uint64 `map:"Gas-Limit"`
GasPrice *big.Int `map:"Gas-Price"`
GasLimit uint64 `map:"Gas-Limit"`
DisableRetry bool `map:"Disable-Retry"`
}{}
if response := s.mapStructure(r.Header, &headers); response != nil {
response("invalid header params", logger, w)
Expand All @@ -567,6 +569,7 @@ func (s *Service) gasConfigMiddleware(handlerName string) func(h http.Handler) h
ctx := r.Context()
ctx = sctx.SetGasPrice(ctx, headers.GasPrice)
ctx = sctx.SetGasLimit(ctx, headers.GasLimit)
ctx = sctx.SetDisableRetry(ctx, headers.DisableRetry)

h.ServeHTTP(w, r.WithContext(ctx))
})
Expand All @@ -581,7 +584,7 @@ func (s *Service) corsHandler(h http.Handler) http.Handler {
SwarmTagHeader, SwarmPinHeader, SwarmEncryptHeader, SwarmIndexDocumentHeader, SwarmErrorDocumentHeader, SwarmCollectionHeader,
SwarmPostageBatchIdHeader, SwarmPostageStampHeader, SwarmDeferredUploadHeader, SwarmRedundancyLevelHeader,
SwarmRedundancyStrategyHeader, SwarmRedundancyFallbackModeHeader, SwarmChunkRetrievalTimeoutHeader, SwarmLookAheadBufferSizeHeader,
SwarmFeedIndexHeader, SwarmFeedIndexNextHeader, SwarmSocSignatureHeader, SwarmOnlyRootChunk, GasPriceHeader, GasLimitHeader, ImmutableHeader,
SwarmFeedIndexHeader, SwarmFeedIndexNextHeader, SwarmSocSignatureHeader, SwarmOnlyRootChunk, GasPriceHeader, GasLimitHeader, DisableRetryHeader, ImmutableHeader,
SwarmActHeader, SwarmActTimestampHeader, SwarmActPublisherHeader, SwarmActHistoryAddressHeader,
}
allowedHeadersStr := strings.Join(allowedHeaders, ", ")
Expand Down
Loading
Loading