Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

param: transactions announced only #1467

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 11 additions & 10 deletions docs/cli/example_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions docs/cli/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
5 changes: 4 additions & 1 deletion eth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -129,6 +130,7 @@ type handler struct {
requiredBlocks map[uint64]common.Hash

enableBlockTracking bool
txAnnouncementOnly bool

// channels for fetcher, syncer, txsyncLoop
quitSync chan struct{}
Expand Down Expand Up @@ -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{}),
Expand Down Expand Up @@ -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
Expand Down
96 changes: 96 additions & 0 deletions eth/handler_eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down
33 changes: 19 additions & 14 deletions internal/cli/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions internal/cli/server/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions internal/cli/server/testdata/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ devfakeauthor = false
nodekey = ""
nodekeyhex = ""
txarrivalwait = "500ms"
txannouncementonly = false
[p2p.discovery]
v4disc = true
v5disc = false
Expand Down
3 changes: 3 additions & 0 deletions p2p/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions packaging/templates/mainnet-v1/archive/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ gcmode = "archive"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
# [p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v4disc = true
# v5disc = false
Expand Down
1 change: 1 addition & 0 deletions packaging/templates/testnet-amoy/archive/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ gcmode = "archive"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv4 = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ syncmode = "full"
# nodekey = ""
# nodekeyhex = ""
# txarrivalwait = "500ms"
# txannouncementonly = false
[p2p.discovery]
# v5disc = false
# bootnodesv5 = []
Expand Down
1 change: 1 addition & 0 deletions scripts/getconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ var nameTagMap = map[string]string{
"maxpeers": "maxpeers",
"maxpendpeers": "maxpendpeers",
"txarrivalwait": "txarrivalwait",
"txannouncementonly": "txannouncementonly",
"nat": "nat",
"nodiscover": "nodiscover",
"v5disc": "v5disc",
Expand Down
Loading