diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 16c8808360..7de1eb6949 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -304,7 +304,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, // Set the receipt logs and create the bloom filter. receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.Bloom = types.CreateBloom(receipt) + // These three are non-consensus fields: //receipt.BlockHash //receipt.BlockNumber @@ -376,7 +377,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, StateRoot: root, TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)), ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)), - Bloom: types.CreateBloom(receipts), + Bloom: types.MergeBloom(receipts), LogsHash: rlpHash(statedb.Logs()), Receipts: receipts, Rejected: rejectedTxs, diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index d80d24e272..cc9f44e460 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -75,9 +75,11 @@ func New(ethone consensus.Engine) *Beacon { // isPostMerge reports whether the given block number is assumed to be post-merge. // Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or // PoA chain for unit testing purposes. -func isPostMerge(config *params.ChainConfig, block uint64) bool { +func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool { mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0 - return mergedAtGenesis || config.MergeNetsplitBlock != nil && block >= config.MergeNetsplitBlock.Uint64() + return mergedAtGenesis || + config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() || + config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime } // Author implements consensus.Engine, returning the verified author of the block. @@ -327,7 +329,7 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [ // Prepare implements consensus.Engine, initializing the difficulty field of a // header to conform to the beacon protocol. The changes are done inline. func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - if !isPostMerge(chain.Config(), header.Number.Uint64()) { + if !isPostMerge(chain.Config(), header.Number.Uint64(), header.Time) { return beacon.ethone.Prepare(chain, header) } header.Difficulty = beaconDifficulty @@ -437,7 +439,7 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash { // the difficulty that a new block should have when created at time // given the parent block's time and difficulty. func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - if !isPostMerge(chain.Config(), parent.Number.Uint64()+1) { + if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) { return beacon.ethone.CalcDifficulty(chain, time, parent) } return beaconDifficulty diff --git a/core/block_validator.go b/core/block_validator.go index 5885df9ee2..591e472bc1 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -129,7 +129,11 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD } // Validate the received block's bloom with the one derived from the generated receipts. // For valid blocks this should always validate to true. - rbloom := types.CreateBloom(res.Receipts) + // + // Receipts must go through MakeReceipt to calculate the receipt's bloom + // already. Merge the receipt's bloom together instead of recalculating + // everything. + rbloom := types.MergeBloom(res.Receipts) if rbloom != header.Bloom { return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) } diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index b9684f8e17..efd16d5fa7 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -338,7 +338,7 @@ func TestBlockReceiptStorage(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), GasUsed: 111111, } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) + receipt1.Bloom = types.CreateBloom(receipt1) receipt2 := &types.Receipt{ PostState: common.Hash{2}.Bytes(), @@ -351,7 +351,7 @@ func TestBlockReceiptStorage(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), GasUsed: 222222, } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) + receipt2.Bloom = types.CreateBloom(receipt2) receipts := []*types.Receipt{receipt1, receipt2} // Check that no receipt entries are in a pristine database @@ -679,7 +679,7 @@ func TestReadLogs(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), GasUsed: 111111, } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) + receipt1.Bloom = types.CreateBloom(receipt1) receipt2 := &types.Receipt{ PostState: common.Hash{2}.Bytes(), @@ -692,7 +692,7 @@ func TestReadLogs(t *testing.T) { ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), GasUsed: 222222, } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) + receipt2.Bloom = types.CreateBloom(receipt2) receipts := []*types.Receipt{receipt1, receipt2} hash := common.BytesToHash([]byte{0x03, 0x14}) diff --git a/core/state_processor.go b/core/state_processor.go index 902ff582e8..2c74f6f407 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -189,7 +189,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b // Set the receipt logs and create the bloom filter. receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.Bloom = types.CreateBloom(receipt) receipt.BlockHash = blockHash receipt.BlockNumber = blockNumber receipt.TransactionIndex = uint(statedb.TxIndex()) diff --git a/core/types/block.go b/core/types/block.go index c3db4d89e8..b284fb3b16 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -237,6 +237,9 @@ type extblock struct { // // The body elements and the receipts are used to recompute and overwrite the // relevant portions of the header. +// +// The receipt's bloom must already calculated for the block's bloom to be +// correctly calculated. func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block { if body == nil { body = &Body{} @@ -260,7 +263,10 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher b.header.ReceiptHash = EmptyReceiptsHash } else { b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) - b.header.Bloom = CreateBloom(receipts) + // Receipts must go through MakeReceipt to calculate the receipt's bloom + // already. Merge the receipt's bloom together instead of recalculating + // everything. + b.header.Bloom = MergeBloom(receipts) } if len(uncles) == 0 { diff --git a/core/types/bloom9.go b/core/types/bloom9.go index a560a20724..962ba46d47 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -100,32 +100,35 @@ func (b *Bloom) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedText("Bloom", input, b[:]) } -// CreateBloom creates a bloom filter out of the give Receipts (+Logs) -func CreateBloom(receipts Receipts) Bloom { - buf := make([]byte, 6) - var bin Bloom - for _, receipt := range receipts { - for _, log := range receipt.Logs { - bin.add(log.Address.Bytes(), buf) - for _, b := range log.Topics { - bin.add(b[:], buf) - } - } - } - return bin -} - -// LogsBloom returns the bloom bytes for the given logs -func LogsBloom(logs []*Log) []byte { - buf := make([]byte, 6) - var bin Bloom - for _, log := range logs { +// CreateBloom creates a bloom filter out of the give Receipt (+Logs) +func CreateBloom(receipt *Receipt) Bloom { + var ( + bin Bloom + buf = make([]byte, 6) + ) + for _, log := range receipt.Logs { bin.add(log.Address.Bytes(), buf) for _, b := range log.Topics { bin.add(b[:], buf) } } - return bin[:] + return bin +} + +// MergeBloom merges the precomputed bloom filters in the Receipts without +// recalculating them. It assumes that each receipt’s Bloom field is already +// correctly populated. +func MergeBloom(receipts Receipts) Bloom { + var bin Bloom + for _, receipt := range receipts { + if len(receipt.Logs) != 0 { + bl := receipt.Bloom.Bytes() + for i := range bin { + bin[i] |= bl[i] + } + } + } + return bin } // Bloom9 returns the bloom filter for the given data diff --git a/core/types/bloom9_test.go b/core/types/bloom9_test.go index d3178d112e..07f6446a97 100644 --- a/core/types/bloom9_test.go +++ b/core/types/bloom9_test.go @@ -126,26 +126,70 @@ func BenchmarkCreateBloom(b *testing.B) { for i := 0; i < 200; i += 2 { copy(rLarge[i:], rSmall) } - b.Run("small", func(b *testing.B) { + b.Run("small-createbloom", func(b *testing.B) { b.ReportAllocs() - var bl Bloom for i := 0; i < b.N; i++ { - bl = CreateBloom(rSmall) + for _, receipt := range rSmall { + receipt.Bloom = CreateBloom(receipt) + } } b.StopTimer() + + bl := MergeBloom(rSmall) var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") got := crypto.Keccak256Hash(bl.Bytes()) if got != exp { b.Errorf("Got %x, exp %x", got, exp) } }) - b.Run("large", func(b *testing.B) { + b.Run("large-createbloom", func(b *testing.B) { b.ReportAllocs() - var bl Bloom for i := 0; i < b.N; i++ { - bl = CreateBloom(rLarge) + for _, receipt := range rLarge { + receipt.Bloom = CreateBloom(receipt) + } } b.StopTimer() + + bl := MergeBloom(rLarge) + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") + got := crypto.Keccak256Hash(bl.Bytes()) + if got != exp { + b.Errorf("Got %x, exp %x", got, exp) + } + }) + b.Run("small-mergebloom", func(b *testing.B) { + for _, receipt := range rSmall { + receipt.Bloom = CreateBloom(receipt) + } + b.ReportAllocs() + b.ResetTimer() + + var bl Bloom + for i := 0; i < b.N; i++ { + bl = MergeBloom(rSmall) + } + b.StopTimer() + + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") + got := crypto.Keccak256Hash(bl.Bytes()) + if got != exp { + b.Errorf("Got %x, exp %x", got, exp) + } + }) + b.Run("large-mergebloom", func(b *testing.B) { + for _, receipt := range rLarge { + receipt.Bloom = CreateBloom(receipt) + } + b.ReportAllocs() + b.ResetTimer() + + var bl Bloom + for i := 0; i < b.N; i++ { + bl = MergeBloom(rLarge) + } + b.StopTimer() + var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") got := crypto.Keccak256Hash(bl.Bytes()) if got != exp { diff --git a/core/types/receipt.go b/core/types/receipt.go index 47f16d950a..e52a0c6477 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -291,7 +291,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { } r.CumulativeGasUsed = stored.CumulativeGasUsed r.Logs = stored.Logs - r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) + r.Bloom = CreateBloom((*Receipt)(r)) return nil } diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index fc51eb11a5..78b43c7e49 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -394,7 +394,7 @@ func TestTypedReceiptEncodingDecoding(t *testing.T) { func TestReceiptMarshalBinary(t *testing.T) { // Legacy Receipt - legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) + legacyReceipt.Bloom = CreateBloom(legacyReceipt) have, err := legacyReceipt.MarshalBinary() if err != nil { t.Fatalf("marshal binary error: %v", err) @@ -421,7 +421,7 @@ func TestReceiptMarshalBinary(t *testing.T) { // 2930 Receipt buf.Reset() - accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) + accessListReceipt.Bloom = CreateBloom(accessListReceipt) have, err = accessListReceipt.MarshalBinary() if err != nil { t.Fatalf("marshal binary error: %v", err) @@ -439,7 +439,7 @@ func TestReceiptMarshalBinary(t *testing.T) { // 1559 Receipt buf.Reset() - eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) + eip1559Receipt.Bloom = CreateBloom(eip1559Receipt) have, err = eip1559Receipt.MarshalBinary() if err != nil { t.Fatalf("marshal binary error: %v", err) @@ -463,7 +463,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) { if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil { t.Fatalf("unmarshal binary error: %v", err) } - legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) + legacyReceipt.Bloom = CreateBloom(legacyReceipt) if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) { t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt) } @@ -474,7 +474,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) { if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil { t.Fatalf("unmarshal binary error: %v", err) } - accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) + accessListReceipt.Bloom = CreateBloom(accessListReceipt) if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) { t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt) } @@ -485,7 +485,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) { if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil { t.Fatalf("unmarshal binary error: %v", err) } - eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) + eip1559Receipt.Bloom = CreateBloom(eip1559Receipt) if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) { t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt) } diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 6a3057326d..e2790d91eb 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -42,7 +42,7 @@ func makeReceipt(addr common.Address) *types.Receipt { receipt.Logs = []*types.Log{ {Address: addr}, } - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.Bloom = types.CreateBloom(receipt) return receipt } diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go index d6cd83373b..a0848137fa 100644 --- a/eth/protocols/eth/handler.go +++ b/eth/protocols/eth/handler.go @@ -89,7 +89,7 @@ type TxPool interface { } // MakeProtocols constructs the P2P protocol definitions for `eth`. -func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol { +func MakeProtocols(backend Backend, network uint64, disc enode.Iterator) []p2p.Protocol { protocols := make([]p2p.Protocol, 0, len(ProtocolVersions)) for _, version := range ProtocolVersions { protocols = append(protocols, p2p.Protocol{ @@ -110,7 +110,8 @@ func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2 PeerInfo: func(id enode.ID) interface{} { return backend.PeerInfo(id) }, - Attributes: []enr.Entry{currentENREntry(backend.Chain())}, + DialCandidates: disc, + Attributes: []enr.Entry{currentENREntry(backend.Chain())}, }) } return protocols diff --git a/p2p/config.go b/p2p/config.go index 5ea62e12f5..68a9c0bb5f 100644 --- a/p2p/config.go +++ b/p2p/config.go @@ -18,6 +18,7 @@ package p2p import ( "crypto/ecdsa" + "encoding" "fmt" "github.com/ethereum/go-ethereum/common/mclock" @@ -135,6 +136,13 @@ type configNAT struct { nat.Interface } +func (w *configNAT) MarshalText() ([]byte, error) { + if tm, ok := w.Interface.(encoding.TextMarshaler); ok { + return tm.MarshalText() + } + return nil, fmt.Errorf("NAT specification %#v cannot be marshaled", w.Interface) +} + func (w *configNAT) UnmarshalText(input []byte) error { n, err := nat.Parse(string(input)) if err != nil { diff --git a/version/version.go b/version/version.go index c97634d7a9..9854aa1119 100644 --- a/version/version.go +++ b/version/version.go @@ -19,6 +19,6 @@ package version const ( Major = 1 // Major version component of the current release Minor = 15 // Minor version component of the current release - Patch = 1 // Patch version component of the current release + Patch = 2 // Patch version component of the current release Meta = "stable" // Version metadata to append to the version string )