Skip to content

Commit 68de26e

Browse files
minh-bqrjl493456442zsfelfoldi
authored
core/types: create block's bloom by merging receipts' bloom (#31129)
Currently, when calculating block's bloom, we loop through all the receipt logs to calculate the hash value. However, normally, after going through applyTransaction, the receipt's bloom is already calculated based on the receipt log, so the block's bloom can be calculated by just ORing these receipt's blooms. ``` goos: darwin goarch: arm64 pkg: github.com/ethereum/go-ethereum/core/types cpu: Apple M1 Pro BenchmarkCreateBloom BenchmarkCreateBloom/small BenchmarkCreateBloom/small-10 810922 1481 ns/op 104 B/op 5 allocs/op BenchmarkCreateBloom/large BenchmarkCreateBloom/large-10 8173 143764 ns/op 9614 B/op 401 allocs/op BenchmarkCreateBloom/small-mergebloom BenchmarkCreateBloom/small-mergebloom-10 5178918 232.0 ns/op 0 B/op 0 allocs/op BenchmarkCreateBloom/large-mergebloom BenchmarkCreateBloom/large-mergebloom-10 54110 22207 ns/op 0 B/op 0 allocs/op ``` --------- Co-authored-by: Gary Rong <[email protected]> Co-authored-by: Zsolt Felfoldi <[email protected]>
1 parent 7776282 commit 68de26e

File tree

10 files changed

+97
-39
lines changed

10 files changed

+97
-39
lines changed

cmd/evm/internal/t8ntool/execution.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
304304

305305
// Set the receipt logs and create the bloom filter.
306306
receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash)
307-
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
307+
receipt.Bloom = types.CreateBloom(receipt)
308+
308309
// These three are non-consensus fields:
309310
//receipt.BlockHash
310311
//receipt.BlockNumber
@@ -376,7 +377,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
376377
StateRoot: root,
377378
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
378379
ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)),
379-
Bloom: types.CreateBloom(receipts),
380+
Bloom: types.MergeBloom(receipts),
380381
LogsHash: rlpHash(statedb.Logs()),
381382
Receipts: receipts,
382383
Rejected: rejectedTxs,

core/block_validator.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
129129
}
130130
// Validate the received block's bloom with the one derived from the generated receipts.
131131
// For valid blocks this should always validate to true.
132-
rbloom := types.CreateBloom(res.Receipts)
132+
//
133+
// Receipts must go through MakeReceipt to calculate the receipt's bloom
134+
// already. Merge the receipt's bloom together instead of recalculating
135+
// everything.
136+
rbloom := types.MergeBloom(res.Receipts)
133137
if rbloom != header.Bloom {
134138
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
135139
}

core/rawdb/accessors_chain_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ func TestBlockReceiptStorage(t *testing.T) {
338338
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
339339
GasUsed: 111111,
340340
}
341-
receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
341+
receipt1.Bloom = types.CreateBloom(receipt1)
342342

343343
receipt2 := &types.Receipt{
344344
PostState: common.Hash{2}.Bytes(),
@@ -351,7 +351,7 @@ func TestBlockReceiptStorage(t *testing.T) {
351351
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
352352
GasUsed: 222222,
353353
}
354-
receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
354+
receipt2.Bloom = types.CreateBloom(receipt2)
355355
receipts := []*types.Receipt{receipt1, receipt2}
356356

357357
// Check that no receipt entries are in a pristine database
@@ -679,7 +679,7 @@ func TestReadLogs(t *testing.T) {
679679
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
680680
GasUsed: 111111,
681681
}
682-
receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
682+
receipt1.Bloom = types.CreateBloom(receipt1)
683683

684684
receipt2 := &types.Receipt{
685685
PostState: common.Hash{2}.Bytes(),
@@ -692,7 +692,7 @@ func TestReadLogs(t *testing.T) {
692692
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
693693
GasUsed: 222222,
694694
}
695-
receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
695+
receipt2.Bloom = types.CreateBloom(receipt2)
696696
receipts := []*types.Receipt{receipt1, receipt2}
697697

698698
hash := common.BytesToHash([]byte{0x03, 0x14})

core/state_processor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
189189

190190
// Set the receipt logs and create the bloom filter.
191191
receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash)
192-
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
192+
receipt.Bloom = types.CreateBloom(receipt)
193193
receipt.BlockHash = blockHash
194194
receipt.BlockNumber = blockNumber
195195
receipt.TransactionIndex = uint(statedb.TxIndex())

core/types/block.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ type extblock struct {
237237
//
238238
// The body elements and the receipts are used to recompute and overwrite the
239239
// relevant portions of the header.
240+
//
241+
// The receipt's bloom must already calculated for the block's bloom to be
242+
// correctly calculated.
240243
func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block {
241244
if body == nil {
242245
body = &Body{}
@@ -260,7 +263,10 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
260263
b.header.ReceiptHash = EmptyReceiptsHash
261264
} else {
262265
b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
263-
b.header.Bloom = CreateBloom(receipts)
266+
// Receipts must go through MakeReceipt to calculate the receipt's bloom
267+
// already. Merge the receipt's bloom together instead of recalculating
268+
// everything.
269+
b.header.Bloom = MergeBloom(receipts)
264270
}
265271

266272
if len(uncles) == 0 {

core/types/bloom9.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,35 @@ func (b *Bloom) UnmarshalText(input []byte) error {
100100
return hexutil.UnmarshalFixedText("Bloom", input, b[:])
101101
}
102102

103-
// CreateBloom creates a bloom filter out of the give Receipts (+Logs)
104-
func CreateBloom(receipts Receipts) Bloom {
105-
buf := make([]byte, 6)
106-
var bin Bloom
107-
for _, receipt := range receipts {
108-
for _, log := range receipt.Logs {
109-
bin.add(log.Address.Bytes(), buf)
110-
for _, b := range log.Topics {
111-
bin.add(b[:], buf)
112-
}
103+
// CreateBloom creates a bloom filter out of the give Receipt (+Logs)
104+
func CreateBloom(receipt *Receipt) Bloom {
105+
var (
106+
bin Bloom
107+
buf = make([]byte, 6)
108+
)
109+
for _, log := range receipt.Logs {
110+
bin.add(log.Address.Bytes(), buf)
111+
for _, b := range log.Topics {
112+
bin.add(b[:], buf)
113113
}
114114
}
115115
return bin
116116
}
117117

118-
// LogsBloom returns the bloom bytes for the given logs
119-
func LogsBloom(logs []*Log) []byte {
120-
buf := make([]byte, 6)
118+
// MergeBloom merges the precomputed bloom filters in the Receipts without
119+
// recalculating them. It assumes that each receipt’s Bloom field is already
120+
// correctly populated.
121+
func MergeBloom(receipts Receipts) Bloom {
121122
var bin Bloom
122-
for _, log := range logs {
123-
bin.add(log.Address.Bytes(), buf)
124-
for _, b := range log.Topics {
125-
bin.add(b[:], buf)
123+
for _, receipt := range receipts {
124+
if len(receipt.Logs) != 0 {
125+
bl := receipt.Bloom.Bytes()
126+
for i := range bin {
127+
bin[i] |= bl[i]
128+
}
126129
}
127130
}
128-
return bin[:]
131+
return bin
129132
}
130133

131134
// Bloom9 returns the bloom filter for the given data

core/types/bloom9_test.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,26 +126,70 @@ func BenchmarkCreateBloom(b *testing.B) {
126126
for i := 0; i < 200; i += 2 {
127127
copy(rLarge[i:], rSmall)
128128
}
129-
b.Run("small", func(b *testing.B) {
129+
b.Run("small-createbloom", func(b *testing.B) {
130130
b.ReportAllocs()
131+
for i := 0; i < b.N; i++ {
132+
for _, receipt := range rSmall {
133+
receipt.Bloom = CreateBloom(receipt)
134+
}
135+
}
136+
b.StopTimer()
137+
138+
bl := MergeBloom(rSmall)
139+
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
140+
got := crypto.Keccak256Hash(bl.Bytes())
141+
if got != exp {
142+
b.Errorf("Got %x, exp %x", got, exp)
143+
}
144+
})
145+
b.Run("large-createbloom", func(b *testing.B) {
146+
b.ReportAllocs()
147+
for i := 0; i < b.N; i++ {
148+
for _, receipt := range rLarge {
149+
receipt.Bloom = CreateBloom(receipt)
150+
}
151+
}
152+
b.StopTimer()
153+
154+
bl := MergeBloom(rLarge)
155+
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
156+
got := crypto.Keccak256Hash(bl.Bytes())
157+
if got != exp {
158+
b.Errorf("Got %x, exp %x", got, exp)
159+
}
160+
})
161+
b.Run("small-mergebloom", func(b *testing.B) {
162+
for _, receipt := range rSmall {
163+
receipt.Bloom = CreateBloom(receipt)
164+
}
165+
b.ReportAllocs()
166+
b.ResetTimer()
167+
131168
var bl Bloom
132169
for i := 0; i < b.N; i++ {
133-
bl = CreateBloom(rSmall)
170+
bl = MergeBloom(rSmall)
134171
}
135172
b.StopTimer()
173+
136174
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
137175
got := crypto.Keccak256Hash(bl.Bytes())
138176
if got != exp {
139177
b.Errorf("Got %x, exp %x", got, exp)
140178
}
141179
})
142-
b.Run("large", func(b *testing.B) {
180+
b.Run("large-mergebloom", func(b *testing.B) {
181+
for _, receipt := range rLarge {
182+
receipt.Bloom = CreateBloom(receipt)
183+
}
143184
b.ReportAllocs()
185+
b.ResetTimer()
186+
144187
var bl Bloom
145188
for i := 0; i < b.N; i++ {
146-
bl = CreateBloom(rLarge)
189+
bl = MergeBloom(rLarge)
147190
}
148191
b.StopTimer()
192+
149193
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
150194
got := crypto.Keccak256Hash(bl.Bytes())
151195
if got != exp {

core/types/receipt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
291291
}
292292
r.CumulativeGasUsed = stored.CumulativeGasUsed
293293
r.Logs = stored.Logs
294-
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
294+
r.Bloom = CreateBloom((*Receipt)(r))
295295

296296
return nil
297297
}

core/types/receipt_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ func TestTypedReceiptEncodingDecoding(t *testing.T) {
394394

395395
func TestReceiptMarshalBinary(t *testing.T) {
396396
// Legacy Receipt
397-
legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt})
397+
legacyReceipt.Bloom = CreateBloom(legacyReceipt)
398398
have, err := legacyReceipt.MarshalBinary()
399399
if err != nil {
400400
t.Fatalf("marshal binary error: %v", err)
@@ -421,7 +421,7 @@ func TestReceiptMarshalBinary(t *testing.T) {
421421

422422
// 2930 Receipt
423423
buf.Reset()
424-
accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt})
424+
accessListReceipt.Bloom = CreateBloom(accessListReceipt)
425425
have, err = accessListReceipt.MarshalBinary()
426426
if err != nil {
427427
t.Fatalf("marshal binary error: %v", err)
@@ -439,7 +439,7 @@ func TestReceiptMarshalBinary(t *testing.T) {
439439

440440
// 1559 Receipt
441441
buf.Reset()
442-
eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt})
442+
eip1559Receipt.Bloom = CreateBloom(eip1559Receipt)
443443
have, err = eip1559Receipt.MarshalBinary()
444444
if err != nil {
445445
t.Fatalf("marshal binary error: %v", err)
@@ -463,7 +463,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) {
463463
if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil {
464464
t.Fatalf("unmarshal binary error: %v", err)
465465
}
466-
legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt})
466+
legacyReceipt.Bloom = CreateBloom(legacyReceipt)
467467
if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) {
468468
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt)
469469
}
@@ -474,7 +474,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) {
474474
if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil {
475475
t.Fatalf("unmarshal binary error: %v", err)
476476
}
477-
accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt})
477+
accessListReceipt.Bloom = CreateBloom(accessListReceipt)
478478
if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) {
479479
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt)
480480
}
@@ -485,7 +485,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) {
485485
if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil {
486486
t.Fatalf("unmarshal binary error: %v", err)
487487
}
488-
eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt})
488+
eip1559Receipt.Bloom = CreateBloom(eip1559Receipt)
489489
if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) {
490490
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt)
491491
}

eth/filters/filter_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func makeReceipt(addr common.Address) *types.Receipt {
4242
receipt.Logs = []*types.Log{
4343
{Address: addr},
4444
}
45-
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
45+
receipt.Bloom = types.CreateBloom(receipt)
4646
return receipt
4747
}
4848

0 commit comments

Comments
 (0)