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

core/types: create block's bloom by merging receipts' bloom #31129

Merged
merged 3 commits into from
Feb 13, 2025
Merged
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
5 changes: 3 additions & 2 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 5 additions & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions core/rawdb/accessors_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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
Expand Down Expand Up @@ -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(),
Expand All @@ -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})
Expand Down
2 changes: 1 addition & 1 deletion core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
8 changes: 7 additions & 1 deletion core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand All @@ -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 {
Expand Down
39 changes: 21 additions & 18 deletions core/types/bloom9.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
// 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
}

// LogsBloom returns the bloom bytes for the given logs
func LogsBloom(logs []*Log) []byte {
buf := make([]byte, 6)
// 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 _, log := range logs {
bin.add(log.Address.Bytes(), buf)
for _, b := range log.Topics {
bin.add(b[:], buf)
for _, receipt := range receipts {
if len(receipt.Logs) != 0 {
bl := receipt.Bloom.Bytes()
for i := range bin {
bin[i] |= bl[i]
}
}
}
return bin[:]
return bin
}

// Bloom9 returns the bloom filter for the given data
Expand Down
52 changes: 48 additions & 4 deletions core/types/bloom9_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
for i := 0; i < b.N; i++ {
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-createbloom", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
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 = CreateBloom(rSmall)
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", func(b *testing.B) {
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 = CreateBloom(rLarge)
bl = MergeBloom(rLarge)
}
b.StopTimer()

var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes())
if got != exp {
Expand Down
2 changes: 1 addition & 1 deletion core/types/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
12 changes: 6 additions & 6 deletions core/types/receipt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion eth/filters/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Loading