mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
core/types: create block's bloom by merging receipts' bloom
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
This commit is contained in:
parent
c4ad459bd2
commit
1715f60b38
4 changed files with 63 additions and 2 deletions
|
|
@ -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.
|
// Validate the received block's bloom with the one derived from the generated receipts.
|
||||||
// For valid blocks this should always validate to true.
|
// 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 {
|
if rbloom != header.Bloom {
|
||||||
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -237,6 +237,9 @@ type extblock struct {
|
||||||
//
|
//
|
||||||
// The body elements and the receipts are used to recompute and overwrite the
|
// The body elements and the receipts are used to recompute and overwrite the
|
||||||
// relevant portions of the header.
|
// 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 {
|
func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block {
|
||||||
if body == nil {
|
if body == nil {
|
||||||
body = &Body{}
|
body = &Body{}
|
||||||
|
|
@ -260,7 +263,10 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
|
||||||
b.header.ReceiptHash = EmptyReceiptsHash
|
b.header.ReceiptHash = EmptyReceiptsHash
|
||||||
} else {
|
} else {
|
||||||
b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
|
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 {
|
if len(uncles) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,23 @@ func CreateBloom(receipts Receipts) Bloom {
|
||||||
return bin
|
return bin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MergeBloom merges the already calculated bloom in Receipts
|
||||||
|
// without recalculating. So it assumes receipt.Bloom is populated
|
||||||
|
// with the correct bloom already.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// LogsBloom returns the bloom bytes for the given logs
|
// LogsBloom returns the bloom bytes for the given logs
|
||||||
func LogsBloom(logs []*Log) []byte {
|
func LogsBloom(logs []*Log) []byte {
|
||||||
buf := make([]byte, 6)
|
buf := make([]byte, 6)
|
||||||
|
|
|
||||||
|
|
@ -152,4 +152,38 @@ func BenchmarkCreateBloom(b *testing.B) {
|
||||||
b.Errorf("Got %x, exp %x", 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(Receipts{receipt})
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
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(Receipts{receipt})
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
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 {
|
||||||
|
b.Errorf("Got %x, exp %x", got, exp)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue