From 89a5e1a29b69ee07191a5bc84d351c09f3ff2619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Mon, 11 Nov 2024 02:05:58 +0700 Subject: [PATCH] cmd/devp2p, eth: advertise 0 TD on eth/status, ignore received one --- cmd/devp2p/internal/ethtest/chain.go | 6 +---- cmd/devp2p/internal/ethtest/suite.go | 38 ---------------------------- eth/api_backend.go | 7 ----- eth/downloader/downloader.go | 4 --- eth/downloader/downloader_test.go | 7 ----- eth/downloader/peer.go | 2 -- eth/handler.go | 3 +-- eth/handler_eth_test.go | 6 ++--- eth/protocols/eth/handler.go | 19 ++++++-------- eth/protocols/eth/handshake.go | 11 ++------ eth/protocols/eth/handshake_test.go | 12 ++++----- eth/protocols/eth/peer.go | 22 ---------------- 12 files changed, 20 insertions(+), 117 deletions(-) diff --git a/cmd/devp2p/internal/ethtest/chain.go b/cmd/devp2p/internal/ethtest/chain.go index 222c66d4df..a90c53c432 100644 --- a/cmd/devp2p/internal/ethtest/chain.go +++ b/cmd/devp2p/internal/ethtest/chain.go @@ -143,11 +143,7 @@ func (c *Chain) ForkID() forkid.ID { // TD calculates the total difficulty of the chain at the // chain head. func (c *Chain) TD() *big.Int { - sum := new(big.Int) - for _, block := range c.blocks[:c.Len()] { - sum.Add(sum, block.Difficulty()) - } - return sum + return new(big.Int) } // GetBlock returns the block at the specified number. diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go index 5cb9fa0297..12dc5711ac 100644 --- a/cmd/devp2p/internal/ethtest/suite.go +++ b/cmd/devp2p/internal/ethtest/suite.go @@ -18,7 +18,6 @@ package ethtest import ( "crypto/rand" - "math/big" "reflect" "github.com/ethereum/go-ethereum/common" @@ -74,7 +73,6 @@ func (s *Suite) EthTests() []utesting.Test { {Name: "GetBlockBodies", Fn: s.TestGetBlockBodies}, // // malicious handshakes + status {Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake}, - {Name: "MaliciousStatus", Fn: s.TestMaliciousStatus}, // test transactions {Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true}, {Name: "Transaction", Fn: s.TestTransaction}, @@ -453,42 +451,6 @@ func (s *Suite) TestMaliciousHandshake(t *utesting.T) { } } -func (s *Suite) TestMaliciousStatus(t *utesting.T) { - t.Log(`This test sends a malicious eth Status message to the node and expects a disconnect.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.handshake(); err != nil { - t.Fatalf("handshake failed: %v", err) - } - // Create status with large total difficulty. - status := ð.StatusPacket{ - ProtocolVersion: uint32(conn.negotiatedProtoVersion), - NetworkID: s.chain.config.ChainID.Uint64(), - TD: new(big.Int).SetBytes(randBuf(2048)), - Head: s.chain.Head().Hash(), - Genesis: s.chain.GetBlock(0).Hash(), - ForkID: s.chain.ForkID(), - } - if err := conn.statusExchange(s.chain, status); err != nil { - t.Fatalf("status exchange failed: %v", err) - } - // Wait for disconnect. - code, _, err := conn.Read() - if err != nil { - t.Fatalf("error reading from connection: %v", err) - } - switch code { - case discMsg: - break - default: - t.Fatalf("expected disconnect, got: %d", code) - } -} - func (s *Suite) TestTransaction(t *utesting.T) { t.Log(`This test sends a valid transaction to the node and checks if the transaction gets propagated.`) diff --git a/eth/api_backend.go b/eth/api_backend.go index be2101c6ec..90439e8eab 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -242,13 +242,6 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number ui return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil } -func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { - if header := b.eth.blockchain.GetHeaderByHash(hash); header != nil { - return b.eth.blockchain.GetTd(hash, header.Number.Uint64()) - } - return nil -} - func (b *EthAPIBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { if vmConfig == nil { vmConfig = b.eth.blockchain.GetVMConfig() diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 8ac5d2eb31..3f3f9b7f0c 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -20,7 +20,6 @@ package downloader import ( "errors" "fmt" - "math/big" "sync" "sync/atomic" "time" @@ -164,9 +163,6 @@ type BlockChain interface { // CurrentHeader retrieves the head header from the local chain. CurrentHeader() *types.Header - // GetTd returns the total difficulty of a local block. - GetTd(common.Hash, uint64) *big.Int - // InsertHeaderChain inserts a batch of headers into the local chain. InsertHeaderChain([]*types.Header) (int, error) diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 47c89bf768..3a145b1958 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -126,13 +126,6 @@ type downloadTesterPeer struct { chain *core.BlockChain } -// Head constructs a function to retrieve a peer's current head hash -// and total difficulty. -func (dlp *downloadTesterPeer) Head() (common.Hash, *big.Int) { - head := dlp.chain.CurrentBlock() - return head.Hash(), dlp.chain.GetTd(head.Hash(), head.Number.Uint64()) -} - func unmarshalRlpHeaders(rlpdata []rlp.RawValue) []*types.Header { var headers = make([]*types.Header, len(rlpdata)) for i, data := range rlpdata { diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go index 4c43af5270..0848e92a26 100644 --- a/eth/downloader/peer.go +++ b/eth/downloader/peer.go @@ -21,7 +21,6 @@ package downloader import ( "errors" - "math/big" "sync" "time" @@ -57,7 +56,6 @@ type peerConnection struct { // Peer encapsulates the methods required to synchronise with a remote full peer. type Peer interface { - Head() (common.Hash, *big.Int) RequestHeadersByHash(common.Hash, int, int, bool, chan *eth.Response) (*eth.Request, error) RequestHeadersByNumber(uint64, int, int, bool, chan *eth.Response) (*eth.Request, error) diff --git a/eth/handler.go b/eth/handler.go index 9820118173..8893920497 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -253,10 +253,9 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error { head = h.chain.CurrentHeader() hash = head.Hash() number = head.Number.Uint64() - td = h.chain.GetTd(hash, number) ) forkID := forkid.NewID(h.chain.Config(), genesis, number, head.Time) - if err := peer.Handshake(h.networkID, td, hash, genesis.Hash(), forkID, h.forkFilter); err != nil { + if err := peer.Handshake(h.networkID, hash, genesis.Hash(), forkID, h.forkFilter); err != nil { peer.Log().Debug("Ethereum handshake failed", "err", err) return err } diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index ce17345358..622880b097 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -260,9 +260,8 @@ func testRecvTransactions(t *testing.T, protocol uint) { var ( genesis = handler.chain.Genesis() head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) ) - if err := src.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { + if err := src.Handshake(1, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { t.Fatalf("failed to run protocol handshake") } // Send the transaction to the sink and verify that it's added to the tx pool @@ -320,9 +319,8 @@ func testSendTransactions(t *testing.T, protocol uint) { var ( genesis = handler.chain.Genesis() head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) ) - if err := sink.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { + if err := sink.Handshake(1, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { t.Fatalf("failed to run protocol handshake") } // After the handshake completes, the source handler should stream the sink diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go index 28db93a209..d6cd83373b 100644 --- a/eth/protocols/eth/handler.go +++ b/eth/protocols/eth/handler.go @@ -18,7 +18,6 @@ package eth import ( "fmt" - "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -120,11 +119,10 @@ func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2 // NodeInfo represents a short summary of the `eth` sub-protocol metadata // known about the host peer. type NodeInfo struct { - Network uint64 `json:"network"` // Ethereum network ID (1=Mainnet, Holesky=17000) - Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain - Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block - Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules - Head common.Hash `json:"head"` // Hex hash of the host's best owned block + Network uint64 `json:"network"` // Ethereum network ID (1=Mainnet, Holesky=17000) + Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block + Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules + Head common.Hash `json:"head"` // Hex hash of the host's best owned block } // nodeInfo retrieves some `eth` protocol metadata about the running host node. @@ -133,11 +131,10 @@ func nodeInfo(chain *core.BlockChain, network uint64) *NodeInfo { hash := head.Hash() return &NodeInfo{ - Network: network, - Difficulty: chain.GetTd(hash, head.Number.Uint64()), - Genesis: chain.Genesis().Hash(), - Config: chain.Config(), - Head: hash, + Network: network, + Genesis: chain.Genesis().Hash(), + Config: chain.Config(), + Head: hash, } } diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go index 68cf846925..0b6f110e3d 100644 --- a/eth/protocols/eth/handshake.go +++ b/eth/protocols/eth/handshake.go @@ -36,7 +36,7 @@ const ( // Handshake executes the eth protocol handshake, negotiating version number, // network IDs, difficulties, head and genesis blocks. -func (p *Peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error { +func (p *Peer) Handshake(network uint64, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error { // Send out own handshake in a new thread errc := make(chan error, 2) @@ -46,7 +46,7 @@ func (p *Peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis errc <- p2p.Send(p.rw, StatusMsg, &StatusPacket{ ProtocolVersion: uint32(p.version), NetworkID: network, - TD: td, + TD: new(big.Int), // unknown for post-merge tail=pruned networks Head: head, Genesis: genesis, ForkID: forkID, @@ -69,13 +69,6 @@ func (p *Peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis return p2p.DiscReadTimeout } } - p.td, p.head = status.TD, status.Head - - // TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times - // larger, it will still fit within 100 bits - if tdlen := p.td.BitLen(); tdlen > 100 { - return fmt.Errorf("too large total difficulty: bitlen %d", tdlen) - } return nil } diff --git a/eth/protocols/eth/handshake_test.go b/eth/protocols/eth/handshake_test.go index b9fd13d863..1d1de3ec16 100644 --- a/eth/protocols/eth/handshake_test.go +++ b/eth/protocols/eth/handshake_test.go @@ -18,6 +18,7 @@ package eth import ( "errors" + "math/big" "testing" "github.com/ethereum/go-ethereum/common" @@ -39,7 +40,6 @@ func testHandshake(t *testing.T, protocol uint) { var ( genesis = backend.chain.Genesis() head = backend.chain.CurrentBlock() - td = backend.chain.GetTd(head.Hash(), head.Number.Uint64()) forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time) ) tests := []struct { @@ -52,19 +52,19 @@ func testHandshake(t *testing.T, protocol uint) { want: errNoStatusMsg, }, { - code: StatusMsg, data: StatusPacket{10, 1, td, head.Hash(), genesis.Hash(), forkID}, + code: StatusMsg, data: StatusPacket{10, 1, new(big.Int), head.Hash(), genesis.Hash(), forkID}, want: errProtocolVersionMismatch, }, { - code: StatusMsg, data: StatusPacket{uint32(protocol), 999, td, head.Hash(), genesis.Hash(), forkID}, + code: StatusMsg, data: StatusPacket{uint32(protocol), 999, new(big.Int), head.Hash(), genesis.Hash(), forkID}, want: errNetworkIDMismatch, }, { - code: StatusMsg, data: StatusPacket{uint32(protocol), 1, td, head.Hash(), common.Hash{3}, forkID}, + code: StatusMsg, data: StatusPacket{uint32(protocol), 1, new(big.Int), head.Hash(), common.Hash{3}, forkID}, want: errGenesisMismatch, }, { - code: StatusMsg, data: StatusPacket{uint32(protocol), 1, td, head.Hash(), genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}}, + code: StatusMsg, data: StatusPacket{uint32(protocol), 1, new(big.Int), head.Hash(), genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}}, want: errForkIDRejected, }, } @@ -80,7 +80,7 @@ func testHandshake(t *testing.T, protocol uint) { // Send the junk test with one peer, check the handshake failure go p2p.Send(app, test.code, test.data) - err := peer.Handshake(1, td, head.Hash(), genesis.Hash(), forkID, forkid.NewFilter(backend.chain)) + err := peer.Handshake(1, head.Hash(), genesis.Hash(), forkID, forkid.NewFilter(backend.chain)) if err == nil { t.Errorf("test %d: protocol returned nil error, want %q", i, test.want) } else if !errors.Is(err, test.want) { diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index f53782a053..58e1baf721 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -17,7 +17,6 @@ package eth import ( - "math/big" "math/rand" "sync" @@ -50,9 +49,6 @@ type Peer struct { rw p2p.MsgReadWriter // Input/output streams for snap version uint // Protocol version negotiated - head common.Hash // Latest advertised head block hash - td *big.Int // Latest advertised head block total difficulty - txpool TxPool // Transaction pool used by the broadcasters for liveness checks knownTxs *knownCache // Set of transaction hashes known to be known by this peer txBroadcast chan []common.Hash // Channel used to queue transaction propagation requests @@ -108,24 +104,6 @@ func (p *Peer) Version() uint { return p.version } -// Head retrieves the current head hash and total difficulty of the peer. -func (p *Peer) Head() (hash common.Hash, td *big.Int) { - p.lock.RLock() - defer p.lock.RUnlock() - - copy(hash[:], p.head[:]) - return hash, new(big.Int).Set(p.td) -} - -// SetHead updates the head hash and total difficulty of the peer. -func (p *Peer) SetHead(hash common.Hash, td *big.Int) { - p.lock.Lock() - defer p.lock.Unlock() - - copy(p.head[:], hash[:]) - p.td.Set(td) -} - // KnownTransaction returns whether peer is known to already have a transaction. func (p *Peer) KnownTransaction(hash common.Hash) bool { return p.knownTxs.Contains(hash)