diff --git a/core/blockchain.go b/core/blockchain.go index b4c1716a92..ccb197c872 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2103,7 +2103,7 @@ func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { return bc.hc.GetHeaderByNumber(number) } -// Config retrieves the blockchain's chain configuration. +// Config retrieves the chain's fork configuration. func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } // Engine retrieves the blockchain's consensus engine. diff --git a/eth/enr.go b/eth/enr.go new file mode 100644 index 0000000000..7486c71d1d --- /dev/null +++ b/eth/enr.go @@ -0,0 +1,245 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package eth + +import ( + "encoding/binary" + "errors" + "fmt" + "math" + "math/big" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/ethereum/go-ethereum/params" +) + +var ( + // errENRGenesisMismatch is returned by the ENR validator if the local genesis + // checksum doesn't match with one contained in a remote ENR record. + errENRGenesisMismatch = errors.New("genesis mismatch") + + // errENRRemoteStale is returned by the ENR validator if a remote fork checksum + // is a subset of our already applied forks, but the announced next fork block is + // not on our already passed chain. + errENRRemoteStale = errors.New("remote needs update") + + // errENRLocalStale is returned by the ENR validator if a remote fork checksum + // does not match any local checksum variation, signalling that the two chains have + // diverged in the past at some point. + errENRLocalStale = errors.New("local needs update") +) + +// ENR is the "eth" Ethereum Node Record, holding the genesis hash checksum, +// the enabled fork checksum and the next scheduled fork number. +type ENR [12]byte + +// NewENR calculates the Ethereum network ENR from the chain config and head. +// https://eips.ethereum.org/EIPS/eip-2124 +func NewENR(chain *core.BlockChain) ENR { + return newENR( + chain.Config(), + chain.Genesis().Hash(), + chain.CurrentHeader().Number.Uint64(), + ) +} + +// newENR is the internal version of NewENR, which takes extracted values as its +// arguments instead of a chain. The reason is to allow testing the ENRs without +// having to simulate an entire blockchain. +func newENR(config *params.ChainConfig, genesis common.Hash, head uint64) ENR { + // Calculate the fork checksum and the next fork block + var ( + forkSum uint32 + forkNext uint32 + ) + for _, fork := range gatherForks(config) { + if fork <= head { + forkSum ^= uint32(fork) + continue + } + forkNext = uint32(fork) + break + } + // Aggregate everything into a single binary blob + var entry ENR + + binary.BigEndian.PutUint32(entry[0:], makeGenesisChecksum(genesis)) + binary.BigEndian.PutUint32(entry[4:], forkSum) + binary.BigEndian.PutUint32(entry[8:], forkNext) + + return entry +} + +// ENRKey implements enr.Entry, returning the key for the chain config. +func (e ENR) ENRKey() string { return "eth" } + +// NewENRFilter creates an ENR filter that returns if a record should be rejected +// or not (may be rejected by another filter). +func NewENRFilter(chain *core.BlockChain) func(r *enr.Record) error { + return newENRFilter( + chain.Config(), + chain.Genesis().Hash(), + func() uint64 { + return chain.CurrentHeader().Number.Uint64() + }, + ) +} + +// newENRFilter is the internal version of NewENRFilter which takes closures as +// its arguments instead of a chain. The reason is to allow testing it without +// having to simulate an entire blockchain. +func newENRFilter(config *params.ChainConfig, genesis common.Hash, headfn func() uint64) func(r *enr.Record) error { + // Calculate the genesis checksum and all the valid fork checksum and block combos + var ( + gensum = makeGenesisChecksum(genesis) + forks = gatherForks(config) + sums = make([]uint32, len(forks)+1) // 0th is no-forks + ) + for i, fork := range forks { + sums[i+1] = sums[i] ^ uint32(fork) + } + // Add two sentries to simplify the fork checks and don't require special + // casing the last one. + forks = append(forks, math.MaxUint32) // Last fork will never be passed + sums = append(sums, sums[len(sums)-1]) // Last checksum is a noop + + // Create a validator that will filter out incompatible chains + return func(r *enr.Record) error { + // Retrieve the remote chain ENR entry, accept record if not found + var entry ENR + if err := r.Load(&entry); err != nil { + return nil + } + // Cross reference the genesis checksum and reject on mismatch + if binary.BigEndian.Uint32(entry[:4]) != gensum { + return errENRGenesisMismatch + } + // Run the fork checksum validation ruleset: + // 1. If local and remote FORK_CSUM matches, connect. + // The two nodes are in the same fork state currently. They might know + // of differing future forks, but that's not relevant until the fork + // triggers (might be postponed, nodes might be updated to match). + // 2. If the remote FORK_CSUM is a subset of the local past forks and the + // remote FORK_NEXT matches with the locally following fork block number, + // connect. + // Remote node is currently syncing. It might eventually diverge from + // us, but at this current point in time we don't have enough information. + // 3. If the remote FORK_CSUM is a superset of the local past forks and can + // be completed with locally known future forks, connect. + // Local node is currently syncing. It might eventually diverge from + // the remote, but at this current point in time we don't have enough + // information. + // 4. Reject in all other cases. + var ( + head = headfn() + remoteSum = binary.BigEndian.Uint32(entry[4:8]) + remoteNext = binary.BigEndian.Uint32(entry[8:12]) + ) + for i, fork := range forks { + // If our head is beyond this fork, continue to the next (we have a dummy + // fork of maxuint32 as the last item to always fail this check eventually). + if head > fork { + continue + } + // Found the first unpassed fork block, check if our current state matches + // the remote checksum (rule #1). + if sums[i] == remoteSum { + // Yay, fork checksum matched, ignore any upcoming fork + return nil + } + // The local and remote nodes are in different forks currently, check if the + // remote checksum is a subset of our local forks (rule #2). + for j := 0; j < i; j++ { + if sums[j] == remoteSum { + // Remote checksum is a subset, validate based on the announced next fork + if uint32(forks[j]) != remoteNext { + return errENRRemoteStale + } + return nil + } + } + // Remote chain is not a subset of our local one, check if it's a superset by + // any chance, signalling that we're simply out of sync (rule #3). + for j := i + 1; j < len(sums); j++ { + if sums[j] == remoteSum { + // Yay, remote checksum is a superset, ignore upcoming forks + return nil + } + } + // No exact, subset or superset match. We are on differing chains, reject. + return errENRLocalStale + } + log.Error("Impossible eth ENR validation", "record", fmt.Sprintf("%x", entry)) + return nil // Something's very wrong, accept rather than reject + } +} + +// makeGenesisChecksum calculates the ENR checksum for the genesis block. +func makeGenesisChecksum(hash common.Hash) uint32 { + var checksum uint32 + for i := 0; i < 8; i++ { + for j := 0; j < 4; j++ { + checksum ^= uint32(hash[i*4+j]) << uint32(24-8*j) + } + } + return checksum +} + +// gatherForks gathers all the known forks and creates a sorted list out of them. +func gatherForks(config *params.ChainConfig) []uint64 { + // Gather all the fork block numbers via reflection + kind := reflect.TypeOf(params.ChainConfig{}) + conf := reflect.ValueOf(config).Elem() + + var forks []uint64 + for i := 0; i < kind.NumField(); i++ { + // Fetch the next field and skip non-fork rules + field := kind.Field(i) + if !strings.HasSuffix(field.Name, "Block") { + continue + } + if field.Type != reflect.TypeOf(new(big.Int)) { + continue + } + // Extract the fork rule block number and aggregate it + rule := conf.Field(i).Interface().(*big.Int) + if rule != nil { + forks = append(forks, rule.Uint64()) + } + } + // Sort the fork block numbers to permit chronologival XOR + for i := 0; i < len(forks); i++ { + for j := i + 1; j < len(forks); j++ { + if forks[i] > forks[j] { + forks[i], forks[j] = forks[j], forks[i] + } + } + } + // Deduplicate block number applying multiple forks and return + for i := 1; i < len(forks); i++ { + if forks[i] == forks[i-1] { + forks = append(forks[:i], forks[i+1:]...) + i-- + } + } + return forks +} diff --git a/eth/enr_test.go b/eth/enr_test.go new file mode 100644 index 0000000000..f9d9699f37 --- /dev/null +++ b/eth/enr_test.go @@ -0,0 +1,184 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package eth + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/ethereum/go-ethereum/params" +) + +// TestENRCreation tests that different genesis and fork rule combinations result +// in the correct announced chain ENR entry. +func TestENRCreation(t *testing.T) { + type testcase struct { + head uint64 + want ENR + } + tests := []struct { + config *params.ChainConfig + genesis common.Hash + cases []testcase + }{ + // Mainnet test cases + { + params.MainnetChainConfig, + params.MainnetGenesisHash, + []testcase{ + {0, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x8c, 0x30}}, // Unsynced + {1149999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x8c, 0x30}}, // Last Frontier block + {1150000, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x11, 0x8c, 0x30, 0x00, 0x1d, 0x4c, 0x00}}, // First Homestead block + {1919999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x11, 0x8c, 0x30, 0x00, 0x1d, 0x4c, 0x00}}, // Last Homestead block + {1920000, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x0c, 0xc0, 0x30, 0x00, 0x25, 0x95, 0x18}}, // First DAO block + {2462999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x0c, 0xc0, 0x30, 0x00, 0x25, 0x95, 0x18}}, // Last DAO block + {2463000, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x29, 0x55, 0x28, 0x00, 0x28, 0xd1, 0x38}}, // First Tangerine block + {2674999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x29, 0x55, 0x28, 0x00, 0x28, 0xd1, 0x38}}, // Last Tangerine block + {2675000, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x01, 0x84, 0x10, 0x00, 0x42, 0xae, 0x50}}, // First Spurious block + {4369999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x01, 0x84, 0x10, 0x00, 0x42, 0xae, 0x50}}, // Last Spurious block + {4370000, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x6f, 0x15, 0x80}}, // First Byzantium block + {7279999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x6f, 0x15, 0x80}}, // Last Byzantium block + {7280000, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x2c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00}}, // First and last Constantinople, first Petersburg block + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x2c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00}}, // Today Petersburg block + }, + }, + // Ropsten test cases + { + params.TestnetChainConfig, + params.TestnetGenesisHash, + []testcase{ + {0, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}}, // Unsynced, last Frontier, Homestead and first Tangerine block + {9, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}}, // Last Tangerine block + {10, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x19, 0xf0, 0xa0}}, // First Spurious block + {1699999, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x19, 0xf0, 0xa0}}, // Last Spurious block + {1700000, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x19, 0xf0, 0xaa, 0x00, 0x40, 0x8b, 0x70}}, // First Byzantium block + {4229999, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x19, 0xf0, 0xaa, 0x00, 0x40, 0x8b, 0x70}}, // Last Byzantium block + {4230000, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x59, 0x7b, 0xda, 0x00, 0x4b, 0x5e, 0x82}}, // First Constantinople block + {4939393, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x59, 0x7b, 0xda, 0x00, 0x4b, 0x5e, 0x82}}, // Last Constantinople block + {4939394, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x12, 0x25, 0x58, 0x00, 0x00, 0x00, 0x00}}, // First Petersburg block + {5822692, ENR{0xe4, 0x91, 0x9a, 0xeb, 0x00, 0x12, 0x25, 0x58, 0x00, 0x00, 0x00, 0x00}}, // Today Petersburg block + }, + }, + // Rinkeby test cases + { + params.RinkebyChainConfig, + params.RinkebyGenesisHash, + []testcase{ + {0, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, // Unsynced, last Frontier block + {1, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02}}, // First and last Homestead block + {2, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03}}, // First and last Tangerine block + {3, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcc, 0x25}}, // First Spurious block + {1035300, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcc, 0x25}}, // Last Spurious block + {1035301, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x0f, 0xcc, 0x25, 0x00, 0x37, 0xdb, 0x77}}, // First Byzantium block + {3660662, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x0f, 0xcc, 0x25, 0x00, 0x37, 0xdb, 0x77}}, // Last Byzantium block + {3660663, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x38, 0x17, 0x52, 0x00, 0x41, 0xef, 0xd2}}, // First Constantinople block + {4321233, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x38, 0x17, 0x52, 0x00, 0x41, 0xef, 0xd2}}, // Last Constantinople block + {4321234, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x79, 0xf8, 0x80, 0x00, 0x00, 0x00, 0x00}}, // First Petersburg block + {4586649, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x79, 0xf8, 0x80, 0x00, 0x00, 0x00, 0x00}}, // Today Petersburg block + }, + }, + // Goerli test cases + { + params.GoerliChainConfig, + params.GoerliGenesisHash, + []testcase{ + {0, ENR{0xc7, 0x24, 0x73, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block + {795329, ENR{0xc7, 0x24, 0x73, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, // Today Petersburg block + }, + }, + } + for i, tt := range tests { + for j, ttt := range tt.cases { + if have := newENR(tt.config, tt.genesis, ttt.head); have != ttt.want { + t.Errorf("test %d, case %d: chain ENR mismatch: have %x, want %x", i, j, have, ttt.want) + } + } + } +} + +// TestENRValidation tests that a local peer correctly validates and accets or +// rejects a remotely announced ENR entry. +func TestENRValidation(t *testing.T) { + tests := []struct { + head uint64 + enr ENR + err error + }{ + // Local is mainnet Petersburg, remote announces the same. No future fork is announced. + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x2c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00}, nil}, + + // Local is mainnet Petersburg, remote announces the same. Remote also announces a next fork + // at block 0xffffffff, but that is uncertain. + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x2c, 0x3f, 0xc0, 0xff, 0xff, 0xff, 0xff}, nil}, + + // Local is mainnet currently in Byzantium only (so it's aware of Petersburg), remote announces + // also Byzantium, but it's not yet aware of Petersburg (e.g. non updated node before the fork). + // In this case we don't know if Petersburg passed yet or not. + {7279999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x00, 0x00, 0x00}, nil}, + + // Local is mainnet currently in Byzantium only (so it's aware of Petersburg), remote announces + // also Byzantium, and it's also aware of Petersburg (e.g. updated node before the fork). We + // don't know if Petersburg passed yet (will pass) or not. + {7279999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x6f, 0x15, 0x80}, nil}, + + // Local is mainnet currently in Byzantium only (so it's aware of Petersburg), remote announces + // also Byzantium, and it's also aware of some random fork (e.g. misconfigured Petersburg). As + // neither forks passed at neither nodes, they may mismatch, but we still connect for now. + {7279999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0xff, 0xff, 0xff, 0xff}, nil}, + + // Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg. Remote + // is simply out of sync, accept. + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x6f, 0x15, 0x80}, nil}, + + // Local is mainnet Petersburg, remote announces Spurious + knowledge about Byzantium. Remote + // is definitely out of sync. It may or may not need the Petersburg update, we don't know yet. + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x01, 0x84, 0x10, 0x00, 0x42, 0xae, 0x50}, nil}, + + // Local is mainnet Byzantium, remote announces Petersburg. Local is out of sync, accept. + {7279999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x2c, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00}, nil}, + + // Local is mainnet Spurious, remote announces Byzantium, but is not aware of Petersburg. Local + // out of sync. Local also knows about a future fork, but that is uncertain yet. + {4369999, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x00, 0x00, 0x00}, nil}, + + // Local is mainnet Petersburg, and isn't aware of more forks. Remote announces Petersburg + + // 0xffffffff. Local needs software update, reject. + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0xff, 0xd3, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00}, errENRLocalStale}, + + // Local is mainnet Byzantium, and is aware of Petersburg. Remote announces Petersburg + + // 0xffffffff. Local needs software update, reject. + {7279999, ENR{0x52, 0xba, 0xab, 0x2d, 0xff, 0xd3, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00}, errENRLocalStale}, + + // Local is mainnet Petersburg. remote announces Byzantium but is not aware of further forks. + // Remote needs software update. + {7987396, ENR{0x52, 0xba, 0xab, 0x2d, 0x00, 0x43, 0x2a, 0x40, 0x00, 0x00, 0x00, 0x00}, errENRRemoteStale}, + + // Local is mainnet Petersburg, remote is Rinkeby Petersburg. + {7987396, ENR{0xca, 0xb4, 0xc3, 0x84, 0x00, 0x79, 0xf8, 0x80, 0x00, 0x00, 0x00, 0x00}, errENRGenesisMismatch}, + } + for i, tt := range tests { + filter := newENRFilter(params.MainnetChainConfig, params.MainnetGenesisHash, func() uint64 { return tt.head }) + + r := new(enr.Record) + r.Set(tt.enr) + + if err := filter(r); err != tt.err { + t.Errorf("test %d: validation error mismatch: have %v, want %v", i, err, tt.err) + } + } +} diff --git a/eth/handler.go b/eth/handler.go index db6901a23a..51d878dbaa 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -75,10 +76,9 @@ type ProtocolManager struct { checkpointNumber uint64 // Block number for the sync progress validator to cross reference checkpointHash common.Hash // Block hash for the sync progress validator to cross reference - txpool txPool - blockchain *core.BlockChain - chainconfig *params.ChainConfig - maxPeers int + txpool txPool + blockchain *core.BlockChain + maxPeers int downloader *downloader.Downloader fetcher *fetcher.Fetcher @@ -113,7 +113,6 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh eventMux: mux, txpool: txpool, blockchain: blockchain, - chainconfig: config, peers: newPeerSet(), whitelist: whitelist, newPeerCh: make(chan *peer), @@ -160,9 +159,10 @@ func NewProtocolManager(config *params.ChainConfig, checkpoint *params.TrustedCh // Compatible; initialise the sub-protocol version := version // Closure for the run manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{ - Name: ProtocolName, - Version: version, - Length: ProtocolLengths[i], + Name: ProtocolName, + Version: version, + Length: ProtocolLengths[i], + Attributes: []enr.Entry{NewENR(blockchain)}, Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { peer := manager.newPeer(int(version), p, rw) select { diff --git a/p2p/enr/enr_test.go b/p2p/enr/enr_test.go index 434685e0b6..96a9ced5cf 100644 --- a/p2p/enr/enr_test.go +++ b/p2p/enr/enr_test.go @@ -70,7 +70,7 @@ func TestGetSetIPv6(t *testing.T) { assert.Equal(t, ip, ip2) } -// TestGetSetDiscPort tests encoding/decoding and setting/getting of the DiscPort key. +// TestGetSetUDP tests encoding/decoding and setting/getting of the UDP key. func TestGetSetUDP(t *testing.T) { port := UDP(30309) var r Record