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

create block's bloom by merging receipts' bloom and filter test fix #2269

Merged
merged 1 commit into from
Feb 18, 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
6 changes: 5 additions & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,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(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(receipts)
if rbloom != header.Bloom {
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
}
Expand Down
4 changes: 2 additions & 2 deletions core/rawdb/accessors_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,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 @@ -303,7 +303,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
2 changes: 1 addition & 1 deletion core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func MakeReceipt(cvm *vm.CVM, result *ExecutionResult, statedb *state.StateDB, b
}
// Set the receipt logs and create a bloom for filtering
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
5 changes: 4 additions & 1 deletion core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,10 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher Hasher) *B
b.header.ReceiptHash = EmptyRootHash
} 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 @@ -127,26 +127,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
4 changes: 2 additions & 2 deletions core/types/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
for i, log := range stored.Logs {
r.Logs[i] = (*Log)(log)
}
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
r.Bloom = CreateBloom((*Receipt)(r))

return nil
}
Expand All @@ -253,7 +253,7 @@ func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error {
for i, log := range stored.Logs {
r.Logs[i] = (*Log)(log)
}
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)})
r.Bloom = CreateBloom((*Receipt)(r))

return nil
}
Expand Down
2 changes: 1 addition & 1 deletion core/types/receipt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestLegacyReceiptDecoding(t *testing.T) {
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
GasUsed: 111111,
}
receipt.Bloom = CreateBloom(Receipts{receipt})
receipt.Bloom = CreateBloom(receipt)

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
Expand Down
9 changes: 5 additions & 4 deletions ctxc/filters/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ import (
)

var (
errInvalidTopic = errors.New("invalid topic(s)")
errFilterNotFound = errors.New("filter not found")
errInvalidBlockRange = errors.New("invalid block range params")
errExceedMaxTopics = errors.New("exceed max topics")
errInvalidTopic = errors.New("invalid topic(s)")
errFilterNotFound = errors.New("filter not found")
errInvalidBlockRange = errors.New("invalid block range params")
errExceedMaxTopics = errors.New("exceed max topics")
errPendingLogsUnsupported = errors.New("pending logs are not supported")
)

// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
Expand Down
52 changes: 15 additions & 37 deletions ctxc/filters/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"errors"
"math/big"
"slices"

"github.com/CortexFoundation/CortexTheseus/common"
"github.com/CortexFoundation/CortexTheseus/core/bloombits"
Expand Down Expand Up @@ -104,22 +105,12 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
if header == nil {
return nil, errors.New("unknown block")
}
return f.blockLogs(ctx, header, false)
return f.blockLogs(ctx, header)
}

var (
beginPending = f.begin == rpc.PendingBlockNumber.Int64()
endPending = f.end == rpc.PendingBlockNumber.Int64()
)

// special case for pending logs
if beginPending && !endPending {
return nil, errInvalidBlockRange
}

// Short-cut if all we care about is pending logs
if beginPending && endPending {
return f.pendingLogs(), nil
// Disallow pending logs.
if f.begin == rpc.PendingBlockNumber.Int64() || f.end == rpc.PendingBlockNumber.Int64() {
return nil, errPendingLogsUnsupported
}

resolveSpecial := func(number int64) (int64, error) {
Expand Down Expand Up @@ -164,16 +155,7 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
case log := <-logChan:
logs = append(logs, log)
case err := <-errChan:
if err != nil {
// if an error occurs during extraction, we do return the extracted data
return logs, err
}
// Append the pending ones
if endPending {
pendingLogs := f.pendingLogs()
logs = append(logs, pendingLogs...)
}
return logs, nil
return logs, err
}
}
}
Expand Down Expand Up @@ -251,7 +233,7 @@ func (f *Filter) indexedLogs(ctx context.Context, end uint64, logChan chan *type
if header == nil || err != nil {
return err
}
found, err := f.blockLogs(ctx, header, true)
found, err := f.checkMatches(ctx, header)
if err != nil {
return err
}
Expand All @@ -273,10 +255,13 @@ func (f *Filter) unindexedLogs(ctx context.Context, end uint64, logChan chan *ty
if header == nil || err != nil {
return err
}
found, err := f.blockLogs(ctx, header, false)
found, err := f.blockLogs(ctx, header)
if err != nil {
return err
}
if len(found) > 0 {
}

for _, log := range found {
select {
case logChan <- log:
Expand All @@ -289,15 +274,8 @@ func (f *Filter) unindexedLogs(ctx context.Context, end uint64, logChan chan *ty
}

// blockLogs returns the logs matching the filter criteria within a single block.
func (f *Filter) blockLogs(ctx context.Context, header *types.Header, skipBloom bool) ([]*types.Log, error) {
// Fast track: no filtering criteria
if len(f.addresses) == 0 && len(f.topics) == 0 {
list, err := f.sys.cachedGetLogs(ctx, header.Hash(), header.Number.Uint64())
if err != nil {
return nil, err
}
return flatten(list), nil
} else if skipBloom || bloomFilter(header.Bloom, f.addresses, f.topics) {
func (f *Filter) blockLogs(ctx context.Context, header *types.Header) ([]*types.Log, error) {
if bloomFilter(header.Bloom, f.addresses, f.topics) {
return f.checkMatches(ctx, header)
}
return nil, nil
Expand Down Expand Up @@ -365,7 +343,7 @@ func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []comm
if toBlock != nil && toBlock.Int64() >= 0 && toBlock.Uint64() < log.BlockNumber {
return false
}
if len(addresses) > 0 && !includes(addresses, log.Address) {
if len(addresses) > 0 && !slices.Contains(addresses, log.Address) {
return false
}
// If the to filtered topics is greater than the amount of topics in logs, skip.
Expand All @@ -376,7 +354,7 @@ func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []comm
if len(sub) == 0 {
continue // empty rule set == wildcard
}
if !includes(sub, log.Topics[i]) {
if !slices.Contains(sub, log.Topics[i]) {
return false
}
}
Expand Down
10 changes: 9 additions & 1 deletion ctxc/filters/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,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 Expand Up @@ -64,15 +64,19 @@ func BenchmarkFilters(b *testing.B) {
case 2403:
receipt := makeReceipt(addr1)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, nil, nil))
case 1034:
receipt := makeReceipt(addr2)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, nil, nil))
case 34:
receipt := makeReceipt(addr3)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, nil, nil))
case 99999:
receipt := makeReceipt(addr4)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, nil, nil))

}
})
Expand Down Expand Up @@ -127,6 +131,7 @@ func TestFilters(t *testing.T) {
Topics: []common.Hash{hash1},
},
}
receipt.Bloom = types.CreateBloom(receipt)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil))
case 2:
Expand All @@ -137,6 +142,7 @@ func TestFilters(t *testing.T) {
Topics: []common.Hash{hash2},
},
}
receipt.Bloom = types.CreateBloom(receipt)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil))

Expand All @@ -148,6 +154,7 @@ func TestFilters(t *testing.T) {
Topics: []common.Hash{hash3},
},
}
receipt.Bloom = types.CreateBloom(receipt)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(998, common.HexToAddress("0x998"), big.NewInt(998), 998, big.NewInt(998), nil))
case 999:
Expand All @@ -158,6 +165,7 @@ func TestFilters(t *testing.T) {
Topics: []common.Hash{hash4},
},
}
receipt.Bloom = types.CreateBloom(receipt)
gen.AddUncheckedReceipt(receipt)
gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, big.NewInt(999), nil))
}
Expand Down