param: txs announced only (#1467)

This commit is contained in:
jj1980a 2025-03-11 13:47:54 +04:00 committed by GitHub
parent 697b68a54d
commit d72c039a1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 159 additions and 25 deletions

View file

@ -32,16 +32,17 @@ devfakeauthor = false # Run miner without validator set authorization
enable-block-tracking = false # Enables additional logging of information collected while tracking block lifecycle
[p2p]
maxpeers = 50 # Maximum number of network peers (network disabled if set to 0)
maxpendpeers = 50 # Maximum number of pending connection attempts
bind = "0.0.0.0" # Network binding address
port = 30303 # Network listening port
nodiscover = false # Disables the peer discovery mechanism (manual peer addition)
nat = "any" # NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)
netrestrict = "" # Restricts network communication to the given IP networks (CIDR masks)
nodekey = "" # P2P node key file
nodekeyhex = "" # P2P node key as hex
txarrivalwait = "500ms" # Maximum duration to wait before requesting an announced transaction
maxpeers = 50 # Maximum number of network peers (network disabled if set to 0)
maxpendpeers = 50 # Maximum number of pending connection attempts
bind = "0.0.0.0" # Network binding address
port = 30303 # Network listening port
nodiscover = false # Disables the peer discovery mechanism (manual peer addition)
nat = "any" # NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)
netrestrict = "" # Restricts network communication to the given IP networks (CIDR masks)
nodekey = "" # P2P node key file
nodekeyhex = "" # P2P node key as hex
txarrivalwait = "500ms" # Maximum duration to wait before requesting an announced transaction
txannouncementonly = false # Whether to only announce transactions to peers
[p2p.discovery]
v4disc = true # Enables the V4 discovery mechanism
v5disc = false # Enables the experimental RLPx V5 (Topic Discovery) mechanism

View file

@ -242,6 +242,8 @@ The ```bor server``` command runs the Bor client.
- ```txarrivalwait```: Maximum duration to wait for a transaction before explicitly requesting it (default: 500ms)
- ```txannouncementonly```: Whether to only announce transactions to peers (default: false)
- ```v4disc```: Enables the V4 discovery mechanism (default: true)
- ```v5disc```: Enables the experimental RLPx V5 (Topic Discovery) mechanism (default: false)

View file

@ -306,6 +306,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
EthAPI: blockChainAPI,
checker: checker,
enableBlockTracking: eth.config.EnableBlockTracking,
txAnnouncementOnly: eth.p2pServer.TxAnnouncementOnly,
}); err != nil {
return nil, err
}

View file

@ -99,6 +99,7 @@ type handlerConfig struct {
RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges
EthAPI *ethapi.BlockChainAPI // EthAPI to interact
enableBlockTracking bool // Whether to log information collected while tracking block lifecycle
txAnnouncementOnly bool // Whether to only announce txs to peers
}
type handler struct {
@ -129,6 +130,7 @@ type handler struct {
requiredBlocks map[uint64]common.Hash
enableBlockTracking bool
txAnnouncementOnly bool
// channels for fetcher, syncer, txsyncLoop
quitSync chan struct{}
@ -159,6 +161,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
ethAPI: config.EthAPI,
requiredBlocks: config.RequiredBlocks,
enableBlockTracking: config.enableBlockTracking,
txAnnouncementOnly: config.txAnnouncementOnly,
quitSync: make(chan struct{}),
handlerDoneCh: make(chan struct{}),
handlerStartCh: make(chan struct{}),
@ -633,7 +636,7 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
case tx.Size() > txMaxBroadcastSize:
largeTxs++
default:
maybeDirect = true
maybeDirect = !h.txAnnouncementOnly
}
// Send the transaction (if it's small enough) directly to a subset of
// the peers that have not received it yet, ensuring that the flow of

View file

@ -454,6 +454,102 @@ func testTransactionPropagation(t *testing.T, protocol uint) {
}
}
// This test checks that transactions are only announced when txannouncementonly is enabled
func TestSendTransactionAnnouncementsOnly67(t *testing.T) {
testSendTransactionAnnouncementsOnly(t, eth.ETH67)
}
func TestSendTransactionAnnouncementsOnly68(t *testing.T) {
testSendTransactionAnnouncementsOnly(t, eth.ETH68)
}
func testSendTransactionAnnouncementsOnly(t *testing.T, protocol uint) {
t.Parallel()
// Create a source handler that has txannouncementonly enabled
source := newTestHandler()
source.handler.txAnnouncementOnly = true
defer source.close()
sink := newTestHandler()
defer sink.close()
sourcePipe, sinkPipe := p2p.MsgPipe()
defer sourcePipe.Close()
defer sinkPipe.Close()
sourcePeer := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, sourcePipe), sourcePipe, source.txpool)
sinkPeer := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, sinkPipe), sinkPipe, sink.txpool)
defer sourcePeer.Close()
defer sinkPeer.Close()
go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error {
return eth.Handle((*ethHandler)(source.handler), peer)
})
// Run the handshake locally
var (
genesis = source.chain.Genesis()
head = source.chain.CurrentBlock()
td = source.chain.GetTd(head.Hash(), head.Number.Uint64())
)
if err := sinkPeer.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(source.chain), forkid.NewFilter(source.chain)); err != nil {
t.Fatalf("failed to run protocol handshake: %v", err)
}
// Subscribe to all inbound network events on the sink peer
backend := new(testEthHandler)
anns := make(chan []common.Hash)
annSub := backend.txAnnounces.Subscribe(anns)
defer annSub.Unsubscribe()
bcasts := make(chan []*types.Transaction)
bcastSub := backend.txBroadcasts.Subscribe(bcasts)
defer bcastSub.Unsubscribe()
go eth.Handle(backend, sinkPeer)
// Fill the source pool with transactions and wait for them at the sink
txs := make([]*types.Transaction, 1024)
for nonce := range txs {
tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil)
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
txs[nonce] = tx
}
source.txpool.Add(txs, false, false)
// Make sure we get all the transactions as announcements
seen := make(map[common.Hash]struct{})
timeout := false
for len(seen) < len(txs) && !timeout {
switch protocol {
case 67, 68:
select {
case hashes := <-anns:
for _, hash := range hashes {
if _, ok := seen[hash]; ok {
t.Errorf("duplicate transaction announced: %x", hash)
}
seen[hash] = struct{}{}
}
case <-bcasts:
t.Errorf("received tx broadcast when txannouncementonly is true")
case <-time.After(5 * time.Second):
t.Errorf("transaction propagation timed out")
timeout = true
}
default:
panic("unsupported protocol, please extend test")
}
}
for _, tx := range txs {
if _, ok := seen[tx.Hash()]; !ok {
t.Errorf("missing transaction: %x", tx.Hash())
}
}
}
// Tests that blocks are broadcast to a sqrt number of peers only.
func TestBroadcastBlock1Peer(t *testing.T) { testBroadcastBlock(t, 1, 1) }
func TestBroadcastBlock2Peers(t *testing.T) { testBroadcastBlock(t, 2, 1) }

View file

@ -222,6 +222,9 @@ type P2PConfig struct {
// an announced transaction to arrive before explicitly requesting it
TxArrivalWait time.Duration `hcl:"-,optional" toml:"-"`
TxArrivalWaitRaw string `hcl:"txarrivalwait,optional" toml:"txarrivalwait,optional"`
// TxAnnouncementOnly is used to only announce transactions to peers
TxAnnouncementOnly bool `hcl:"txannouncementonly,optional" toml:"txannouncementonly,optional"`
}
type P2PDiscovery struct {
@ -625,14 +628,15 @@ func DefaultConfig() *Config {
RPCBatchLimit: 100,
RPCReturnDataLimit: 100000,
P2P: &P2PConfig{
MaxPeers: 50,
MaxPendPeers: 50,
Bind: "0.0.0.0",
Port: 30303,
NoDiscover: false,
NAT: "any",
NetRestrict: "",
TxArrivalWait: 500 * time.Millisecond,
MaxPeers: 50,
MaxPendPeers: 50,
Bind: "0.0.0.0",
Port: 30303,
NoDiscover: false,
NAT: "any",
NetRestrict: "",
TxArrivalWait: 500 * time.Millisecond,
TxAnnouncementOnly: false,
Discovery: &P2PDiscovery{
DiscoveryV4: true,
V5Enabled: false,
@ -1343,12 +1347,13 @@ func (c *Config) buildNode() (*node.Config, error) {
AllowUnprotectedTxs: c.JsonRPC.AllowUnprotectedTxs,
EnablePersonal: c.JsonRPC.EnablePersonal,
P2P: p2p.Config{
MaxPeers: int(c.P2P.MaxPeers),
MaxPendingPeers: int(c.P2P.MaxPendPeers),
ListenAddr: c.P2P.Bind + ":" + strconv.Itoa(int(c.P2P.Port)),
DiscoveryV4: c.P2P.Discovery.DiscoveryV4,
DiscoveryV5: c.P2P.Discovery.V5Enabled,
TxArrivalWait: c.P2P.TxArrivalWait,
MaxPeers: int(c.P2P.MaxPeers),
MaxPendingPeers: int(c.P2P.MaxPendPeers),
ListenAddr: c.P2P.Bind + ":" + strconv.Itoa(int(c.P2P.Port)),
DiscoveryV4: c.P2P.Discovery.DiscoveryV4,
DiscoveryV5: c.P2P.Discovery.V5Enabled,
TxArrivalWait: c.P2P.TxArrivalWait,
TxAnnouncementOnly: c.P2P.TxAnnouncementOnly,
},
HTTPModules: c.JsonRPC.Http.API,
HTTPCors: c.JsonRPC.Http.Cors,

View file

@ -812,6 +812,13 @@ func (c *Command) Flags(config *Config) *flagset.Flagset {
Default: c.cliConfig.P2P.TxArrivalWait,
Group: "P2P",
})
f.BoolFlag(&flagset.BoolFlag{
Name: "txannouncementonly",
Usage: "Whether to only announce transactions to peers",
Value: &c.cliConfig.P2P.TxAnnouncementOnly,
Default: c.cliConfig.P2P.TxAnnouncementOnly,
Group: "P2P",
})
f.SliceStringFlag(&flagset.SliceStringFlag{
Name: "discovery.dns",
Usage: "Comma separated list of enrtree:// URLs which will be queried for nodes to connect to",

View file

@ -36,6 +36,7 @@ devfakeauthor = false
nodekey = ""
nodekeyhex = ""
txarrivalwait = "500ms"
txannouncementonly = false
[p2p.discovery]
v4disc = true
v5disc = false

View file

@ -172,6 +172,9 @@ type Config struct {
// TxArrivalWait is the duration (ms) that the node will wait after seeing
// an announced transaction before explicitly requesting it
TxArrivalWait time.Duration
// TxAnnouncementOnly is used to only announce transactions to peers
TxAnnouncementOnly bool
}
// Server manages all peer connections.

View file

@ -35,6 +35,7 @@ gcmode = "archive"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
# [p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -34,6 +34,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -38,6 +38,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -37,6 +37,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false

View file

@ -34,6 +34,7 @@ gcmode = "archive"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []

View file

@ -33,6 +33,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []

View file

@ -34,6 +34,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []

View file

@ -35,6 +35,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []

View file

@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []

View file

@ -35,6 +35,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []

View file

@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv5 = []

View file

@ -172,6 +172,7 @@ var nameTagMap = map[string]string{
"maxpeers": "maxpeers",
"maxpendpeers": "maxpendpeers",
"txarrivalwait": "txarrivalwait",
"txannouncementonly": "txannouncementonly",
"nat": "nat",
"nodiscover": "nodiscover",
"v5disc": "v5disc",