Skip to content

Commit

Permalink
Merge pull request #2269 from CortexFoundation/dev
Browse files Browse the repository at this point in the history
create block's bloom by merging receipts' bloom and filter test fix
  • Loading branch information
ucwong authored Feb 18, 2025
2 parents 6a5b84c + bd0eb57 commit e454638
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 72 deletions.
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

0 comments on commit e454638

Please sign in to comment.