-
Notifications
You must be signed in to change notification settings - Fork 10
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
Implement the RPCBlockHeaderSubscriber
for indexing finalized results
#728
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request introduces several enhancements to the Flow EVM Gateway, focusing on event ingestion and deployment processes. The changes include updating the Makefile with new targets for testnet and mainnet environments, modifying the event subscription mechanism in the bootstrap process, and updating various dependencies. A new Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
10a8bdd
to
4fd4a5d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a couple small comments, but otherwise this looks good. let's get it running against one of the live networks.
…ersFromStartHeight
…or function resuse
@peterargue Thanks for the review 🙌 I've addressed all the comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
services/ingestion/block_tracking_subscriber.go (1)
137-142
: Simplify loop by removing redundant context check.Since you're already handling context cancellation within the
select
statement using<-ctx.Done()
, the loop conditionfor ctx.Err() == nil
is redundant. Simplify the loop by usingfor {}
to improve code readability.Apply this diff to simplify the loop:
- for ctx.Err() == nil { + for { select { case <-ctx.Done(): r.logger.Info().Msg("event ingestion received done signal") return // ...services/requester/cross-spork_client.go (1)
262-265
: Avoid type assertion to*grpc.Client
; use an interface to ensure compatibility.Direct type assertion to
*grpc.Client
can be fragile and may break if the underlying implementation changes. Consider defining an interface that includes theSubscribeBlockHeadersFromStartHeight
method and updating your clients to implement this interface. This approach enhances flexibility and maintainability.For example, define an interface:
type BlockHeaderSubscriber interface { SubscribeBlockHeadersFromStartHeight(ctx context.Context, startHeight uint64, blockStatus flow.BlockStatus) (<-chan flow.BlockHeader, <-chan error, error) }And ensure that your clients implement this interface. Then, modify the code:
- grpcClient, ok := (client).(*grpc.Client) - if !ok { - return nil, nil, fmt.Errorf("unable to convert to Flow grpc.Client") - } - return grpcClient.SubscribeBlockHeadersFromStartHeight(ctx, startHeight, blockStatus) + subscriberClient, ok := client.(BlockHeaderSubscriber) + if !ok { + return nil, nil, fmt.Errorf("client does not implement BlockHeaderSubscriber interface") + } + return subscriberClient.SubscribeBlockHeadersFromStartHeight(ctx, startHeight, blockStatus)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
go.sum
is excluded by!**/*.sum
tests/go.sum
is excluded by!**/*.sum
📒 Files selected for processing (6)
Makefile
(1 hunks)bootstrap/bootstrap.go
(1 hunks)go.mod
(5 hunks)services/ingestion/block_tracking_subscriber.go
(1 hunks)services/requester/cross-spork_client.go
(2 hunks)tests/go.mod
(5 hunks)
🧰 Additional context used
🪛 Gitleaks (8.21.2)
Makefile
243-243: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
260-260: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (3)
bootstrap/bootstrap.go (1)
145-145
: Change toNewRPCBlockTrackingSubscriber
looks good.Replacing
NewRPCEventSubscriber
withNewRPCBlockTrackingSubscriber
appropriately integrates the new block tracking functionality into the event ingestion process.go.mod (1)
9-12
: Verify compatibility with updated dependencies.The dependency updates look reasonable, but please verify:
- Compatibility between
flow-go-sdk v1.3.0
and the new block header subscription implementation.- Impact of OpenTelemetry instrumentation updates on existing metrics.
Run this script to check for any breaking changes in the updated dependencies:
Also applies to: 185-186, 208-210
✅ Verification successful
Dependencies are compatible with existing implementation
The verification shows:
- Block header subscription implementation is compatible with flow-go-sdk v1.3.0
- No active OpenTelemetry instrumentation in the codebase, so the updates have no impact
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for breaking changes in updated dependencies # Check release notes and changelogs echo "Checking flow-go-sdk changelog..." curl -s https://api.github.com/repos/onflow/flow-go-sdk/releases/tags/v1.3.0 | jq -r '.body' echo "Checking OpenTelemetry changelog..." curl -s https://api.github.com/repos/open-telemetry/opentelemetry-go-contrib/releases/tags/v0.49.0 | jq -r '.body'Length of output: 1220
Script:
#!/bin/bash # Check block header subscription and OpenTelemetry usage # Find block header subscription usage echo "Checking block header subscription usage..." rg -A 5 "SubscribeBlocks|SubscribeBlockHeaders" --type go # Check OpenTelemetry imports and usage echo -e "\nChecking OpenTelemetry imports and instrumentation..." rg "go.opentelemetry.io/otel" go.mod rg -A 3 "otel\." --type go # Look for metric initialization echo -e "\nChecking metric initialization patterns..." rg -A 3 "NewMeterProvider|NewMeter" --type goLength of output: 2663
tests/go.mod (1)
7-15
: LGTM! Dependency versions are consistent.The dependency updates in tests/go.mod correctly mirror the updates in the main go.mod file, maintaining consistency between main and test code.
if strings.Contains(errors.Unwrap(err).Error(), "DeadlineExceeded") || | ||
strings.Contains(errors.Unwrap(err).Error(), "unexpected EOF") { | ||
blockHeadersChan, errChan, err = r.client.SubscribeBlockHeadersFromStartHeight( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use error types instead of string matching for error handling.
Using strings.Contains
to check error messages is not robust and can lead to unexpected behavior if the error messages change. Instead, use errors.Is
or compare against specific error variables like context.DeadlineExceeded
and io.EOF
to handle errors reliably.
Apply this diff to improve error handling:
- if strings.Contains(errors.Unwrap(err).Error(), "DeadlineExceeded") ||
- strings.Contains(errors.Unwrap(err).Error(), "unexpected EOF") {
+ unwrappedErr := errors.Unwrap(err)
+ if errors.Is(unwrappedErr, context.DeadlineExceeded) ||
+ errors.Is(unwrappedErr, io.EOF) {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if strings.Contains(errors.Unwrap(err).Error(), "DeadlineExceeded") || | |
strings.Contains(errors.Unwrap(err).Error(), "unexpected EOF") { | |
blockHeadersChan, errChan, err = r.client.SubscribeBlockHeadersFromStartHeight( | |
unwrappedErr := errors.Unwrap(err) | |
if errors.Is(unwrappedErr, context.DeadlineExceeded) || | |
errors.Is(unwrappedErr, io.EOF) { | |
blockHeadersChan, errChan, err = r.client.SubscribeBlockHeadersFromStartHeight( |
.PHONY: start-testnet | ||
start-testnet: | ||
rm -rf testnet-db-block-headers/ | ||
rm -rf metrics/data/ | ||
go run cmd/main.go run \ | ||
--database-dir=testnet-db-block-headers \ | ||
--access-node-grpc-host=access.devnet.nodes.onflow.org:9000 \ | ||
--access-node-spork-hosts=access-001.devnet51.nodes.onflow.org:9000 \ | ||
--flow-network-id=flow-testnet \ | ||
--init-cadence-height=211176670 \ | ||
--ws-enabled=true \ | ||
--coinbase=FACF71692421039876a5BB4F10EF7A439D8ef61E \ | ||
--coa-address=0x62631c28c9fc5a91 \ | ||
--coa-key=2892fba444f1d5787739708874e3b01160671924610411ac787ac1379d420f49 \ | ||
--gas-price=100 \ | ||
--log-level=info | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Secure sensitive values and improve code reusability.
- Security: Move sensitive values (API keys, addresses) to environment variables instead of hardcoding them.
- Code structure: Extract common cleanup commands into a reusable target.
Apply this diff to improve security and reusability:
+.PHONY: clean-metrics
+clean-metrics:
+ rm -rf metrics/data/
+
.PHONY: start-testnet
start-testnet:
rm -rf testnet-db-block-headers/
- rm -rf metrics/data/
+ $(MAKE) clean-metrics
go run cmd/main.go run \
--database-dir=testnet-db-block-headers \
--access-node-grpc-host=access.devnet.nodes.onflow.org:9000 \
--access-node-spork-hosts=access-001.devnet51.nodes.onflow.org:9000 \
--flow-network-id=flow-testnet \
--init-cadence-height=211176670 \
--ws-enabled=true \
- --coinbase=FACF71692421039876a5BB4F10EF7A439D8ef61E \
- --coa-address=0x62631c28c9fc5a91 \
- --coa-key=2892fba444f1d5787739708874e3b01160671924610411ac787ac1379d420f49 \
+ --coinbase=$(TESTNET_COINBASE) \
+ --coa-address=$(TESTNET_COA_ADDRESS) \
+ --coa-key=$(TESTNET_COA_KEY) \
--gas-price=100 \
--log-level=info
.PHONY: start-mainnet
start-mainnet:
rm -rf mainnet-db-block-headers/
- rm -rf metrics/data/
+ $(MAKE) clean-metrics
go run cmd/main.go run \
--database-dir=mainnet-db-block-headers \
--access-node-grpc-host=access.mainnet.nodes.onflow.org:9000 \
--access-node-spork-hosts=access-001.mainnet25.nodes.onflow.org:9000 \
--flow-network-id=flow-mainnet \
--init-cadence-height=85981135 \
--ws-enabled=true \
- --coinbase=FACF71692421039876a5BB4F10EF7A439D8ef61E \
- --coa-address=0xf1ab99c82dee3526 \
- --coa-key=2892fba444f1d5787739708874e3b01160671924610411ac787ac1379d420f49 \
+ --coinbase=$(MAINNET_COINBASE) \
+ --coa-address=$(MAINNET_COA_ADDRESS) \
+ --coa-key=$(MAINNET_COA_KEY) \
--gas-price=100 \
--log-level=info
Add these variables at the top of the Makefile:
# Network-specific configuration
TESTNET_COINBASE ?= FACF71692421039876a5BB4F10EF7A439D8ef61E
TESTNET_COA_ADDRESS ?= 0x62631c28c9fc5a91
TESTNET_COA_KEY ?= # Set via environment variable
MAINNET_COINBASE ?= FACF71692421039876a5BB4F10EF7A439D8ef61E
MAINNET_COA_ADDRESS ?= 0xf1ab99c82dee3526
MAINNET_COA_KEY ?= # Set via environment variable
Also applies to: 247-262
🧰 Tools
🪛 Gitleaks (8.21.2)
243-243: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
services/ingestion/block_tracking_subscriber.go
(1 hunks)
🔇 Additional comments (5)
services/ingestion/block_tracking_subscriber.go (5)
1-2
: File structure and package declaration look good.
31-55
: Constructor’s logging strategy is consistent.
Using logger fields for “component” is a clean approach for log filtering and scoping. Looks good!
66-71
: Graceful closure of eventsChan is well-handled.
The deferredclose(eventsChan)
ensures the channel is properly cleaned up when the goroutine exits. Nicely done.
191-193
: Use error types instead of string matching for error handling.- if strings.Contains(errors.Unwrap(err).Error(), "DeadlineExceeded") || - strings.Contains(errors.Unwrap(err).Error(), "unexpected EOF") { + unwrappedErr := errors.Unwrap(err) + if errors.Is(unwrappedErr, context.DeadlineExceeded) || + errors.Is(unwrappedErr, io.EOF) {
72-93
: Verify single-invocation usage of Subscribe.
This logic backfills events from previous sporks and updatesr.height
. Ensure that no other process or goroutine callsSubscribe
concurrently, or consider adding concurrency protection to prevent data races.✅ Verification successful
Concurrent usage of Subscribe is properly controlled
The codebase shows thatSubscribe
is used correctly with a single-subscription pattern, primarily called by the engine's main loop. No concurrent invocations were found, and the existing buffered channel (capacity 1000) safely handles event processing.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Searching for other call sites of Subscribe to ensure single usage rg -A 3 'Subscribe('Length of output: 93
Script:
#!/bin/bash # Find Subscribe method declaration ast-grep --pattern 'func $_($_ *BlockTrackingSubscriber) Subscribe($$$) { $$$ }' # Find Subscribe method calls with proper escaping rg -p 'Subscribe\(' -A 3 # Find goroutine usages with BlockTrackingSubscriber rg -p 'go .*BlockTrackingSubscriber'Length of output: 2772
type RPCBlockTrackingSubscriber struct { | ||
*RPCEventSubscriber | ||
|
||
logger zerolog.Logger | ||
client *requester.CrossSporkClient | ||
chain flowGo.ChainID | ||
keyLock requester.KeyLock | ||
height uint64 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Potential concurrency issue with height
.
While height
is updated within this struct (e.g., lines 86, 92), consider guarding it with a mutex or using atomic operations if multiple goroutines might invoke or access this subscriber concurrently. This will help prevent data races and undefined behavior.
if len(evts) != 1 && len(evts[0].Events) != 1 { | ||
return flow.BlockEvents{}, fmt.Errorf( | ||
"received unexpected number of EVM events for height: %d, got: %d, expected: 1", | ||
height, | ||
len(evts), | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent potential out-of-bounds errors when checking for events.
This condition uses logical AND (“&&”) to check both array length and the length of the first item in evts
. If evts
is empty, evts[0]
will be invalid and cause a panic. Consider splitting these checks or using safer indexing to avoid out-of-range access.
-if len(evts) != 1 && len(evts[0].Events) != 1 {
+if len(evts) != 1 || len(evts[0].Events) != 1 {
return flow.BlockEvents{}, fmt.Errorf(
"received unexpected number of EVM events for height: %d, got: %d, expected: 1",
height,
len(evts),
)
}
Also applies to: 265-271
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👆 good catch rabbit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@peterargue Thank you for confirming! I'm glad I could help identify this potential issue.
(\ /)
(。◕‿◕。)
c(")(")
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
// subscribe to events by the provided height and handle any errors. | ||
// | ||
// Subscribing to EVM specific events and handle any disconnection errors | ||
// as well as context cancellations. | ||
func (r *RPCBlockTrackingSubscriber) subscribe(ctx context.Context, height uint64) <-chan models.BlockEvents { | ||
eventsChan := make(chan models.BlockEvents) | ||
|
||
blockHeadersChan, errChan, err := r.client.SubscribeBlockHeadersFromStartHeight( | ||
ctx, | ||
height, | ||
flow.BlockStatusFinalized, | ||
) | ||
if err != nil { | ||
eventsChan <- models.NewBlockEventsError( | ||
fmt.Errorf( | ||
"failed to subscribe for finalized block headers on height: %d, with: %w", | ||
height, | ||
err, | ||
), | ||
) | ||
return eventsChan | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper channel closure on subscription failure.
When SubscribeBlockHeadersFromStartHeight
returns an error on lines 122-130, you return eventsChan
without closing it. This can leave consumers of eventsChan
blocked. Consider closing the channel before returning.
if err != nil {
eventsChan <- models.NewBlockEventsError(
fmt.Errorf(
"failed to subscribe for finalized block headers on height: %d, with: %w",
height,
err,
),
)
+ close(eventsChan)
return eventsChan
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// subscribe to events by the provided height and handle any errors. | |
// | |
// Subscribing to EVM specific events and handle any disconnection errors | |
// as well as context cancellations. | |
func (r *RPCBlockTrackingSubscriber) subscribe(ctx context.Context, height uint64) <-chan models.BlockEvents { | |
eventsChan := make(chan models.BlockEvents) | |
blockHeadersChan, errChan, err := r.client.SubscribeBlockHeadersFromStartHeight( | |
ctx, | |
height, | |
flow.BlockStatusFinalized, | |
) | |
if err != nil { | |
eventsChan <- models.NewBlockEventsError( | |
fmt.Errorf( | |
"failed to subscribe for finalized block headers on height: %d, with: %w", | |
height, | |
err, | |
), | |
) | |
return eventsChan | |
} | |
// subscribe to events by the provided height and handle any errors. | |
// | |
// Subscribing to EVM specific events and handle any disconnection errors | |
// as well as context cancellations. | |
func (r *RPCBlockTrackingSubscriber) subscribe(ctx context.Context, height uint64) <-chan models.BlockEvents { | |
eventsChan := make(chan models.BlockEvents) | |
blockHeadersChan, errChan, err := r.client.SubscribeBlockHeadersFromStartHeight( | |
ctx, | |
height, | |
flow.BlockStatusFinalized, | |
) | |
if err != nil { | |
eventsChan <- models.NewBlockEventsError( | |
fmt.Errorf( | |
"failed to subscribe for finalized block headers on height: %d, with: %w", | |
height, | |
err, | |
), | |
) | |
close(eventsChan) | |
return eventsChan | |
} |
logger zerolog.Logger | ||
client *requester.CrossSporkClient | ||
chain flowGo.ChainID | ||
keyLock requester.KeyLock | ||
height uint64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like all of these are also available from the event subscriber, so you don't need to explicitly add them here
flow-evm-gateway/services/ingestion/event_subscriber.go
Lines 33 to 43 in 314e7cc
type RPCEventSubscriber struct { | |
logger zerolog.Logger | |
client *requester.CrossSporkClient | |
chain flowGo.ChainID | |
keyLock requester.KeyLock | |
height uint64 | |
recovery bool | |
recoveredEvents []flow.Event | |
} |
eventSubscriber := NewRPCEventSubscriber( | ||
logger, | ||
client, | ||
chainID, | ||
keyLock, | ||
startHeight, | ||
) | ||
logger = logger.With().Str("component", "subscriber").Logger() | ||
|
||
return &RPCBlockTrackingSubscriber{ | ||
RPCEventSubscriber: eventSubscriber, | ||
logger: logger, | ||
client: client, | ||
chain: chainID, | ||
keyLock: keyLock, | ||
height: startHeight, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider shortening
eventSubscriber := NewRPCEventSubscriber( | |
logger, | |
client, | |
chainID, | |
keyLock, | |
startHeight, | |
) | |
logger = logger.With().Str("component", "subscriber").Logger() | |
return &RPCBlockTrackingSubscriber{ | |
RPCEventSubscriber: eventSubscriber, | |
logger: logger, | |
client: client, | |
chain: chainID, | |
keyLock: keyLock, | |
height: startHeight, | |
} | |
return &RPCBlockTrackingSubscriber{ | |
RPCEventSubscriber: NewRPCEventSubscriber( | |
logger.With().Str("component", "subscriber").Logger(), | |
client, | |
chainID, | |
keyLock, | |
startHeight, | |
) | |
} |
|
||
var _ EventSubscriber = &RPCBlockTrackingSubscriber{} | ||
|
||
type RPCBlockTrackingSubscriber struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add a big warning about the limitations
type RPCBlockTrackingSubscriber struct { | |
// RPCBlockTrackingSubscriber subscribes to new EVM block events for unsealed finalized blocks. | |
// This is accomplished by following finalized blocks from the upstream Access node, and using the | |
// polling endpoint to fetch the events for each finalized block. | |
// | |
// IMPORTANT: Since data is downloaded and processed from unsealed blocks, it's possible for the | |
// data that was downloaded to be incorrect. This subscriber provides no handling or detection for | |
// cases where the received data differs from the data that was ultimately sealed. The operator must | |
// handle this manually. | |
// Since it's not reasonable to expect operators to do this manual tracking, this features should NOT | |
// be used outside of a limited Proof of Concept. Use at own risk. | |
// | |
// A future version of the RPCEventSubscriber will provide this detection and handling functionality | |
// at which point this subscriber will be removed. | |
type RPCBlockTrackingSubscriber struct { |
if len(evts) != 1 && len(evts[0].Events) != 1 { | ||
return flow.BlockEvents{}, fmt.Errorf( | ||
"received unexpected number of EVM events for height: %d, got: %d, expected: 1", | ||
height, | ||
len(evts), | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👆 good catch rabbit
return flow.BlockEvents{}, err | ||
} | ||
|
||
if len(evts) != 1 && len(evts[0].Events) != 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if len(evts) != 1 && len(evts[0].Events) != 1 { | |
if len(evts) != 1 || len(evts[0].Events) != 1 { |
blockEvents.Events = append(blockEvents.Events, txEvents.Events...) | ||
|
||
return blockEvents, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider refactoring this a bit to make it clearer
func (r *RPCBlockTrackingSubscriber) evmEventsForBlock(
ctx context.Context,
blockID flow.Identifier,
) (flow.BlockEvents, error) {
eventTypes := blocksFilter(r.chain).EventTypes
// evm Block events
blockEvents, err := r.getEventsByType(ctx, blockID, eventTypes[0])
if err != nil {
return flow.BlockEvents{}, err
}
payload, err := events.DecodeBlockEventPayload(blockEvents.Events[0].Value)
if err != nil {
return flow.BlockEvents{}, err
}
if payload.TransactionHashRoot == types.EmptyTxsHash {
return blockEvents, nil
}
// evm TX events
txEvents, err := r.getEventsByType(ctx, blockID, eventTypes[1])
if err != nil {
return flow.BlockEvents{}, err
}
// combine block and tx events to be processed together
blockEvents.Events = append(blockEvents.Events, txEvents.Events...)
return blockEvents, nil
}
func (r *RPCBlockTrackingSubscriber) getEventsByType(
ctx context.Context,
blockID flow.Identifier,
eventType string,
) (flow.BlockEvents, error) {
evts, err := r.client.GetEventsForBlockIDs(
ctx,
eventType,
[]flow.Identifier{blockID},
)
if err != nil {
return flow.BlockEvents{}, err
}
if len(evts) != 1 {
// this shouldn't happen and probably indicates a bug on the Access node.
return flow.BlockEvents{}, fmt.Errorf(
"received unexpected number of block events: got: %d, expected: 1",
len(evts),
)
}
if len(evts[0].Events) != 1 {
return flow.BlockEvents{}, fmt.Errorf(
"received unexpected number of events in block: got: %d, expected: 1",
len(evts[0].Events),
)
}
return evts[0], nil
}
eventTypes := blocksFilter(r.chain).EventTypes | ||
evmBlockEvent := eventTypes[0] | ||
|
||
evts, err := r.client.GetEventsForHeightRange( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an important detail from the issue that I missed in the last review is that this needs to use GetEventsForBlockIDs
instead of the height range version. The range endpoint will restrict the request to sealed blocks, which defeats the purpose of this change. GetEventsForBlockIDs
will search any blocks you provide allowing us to query finalized blocks as well.
Work Towards: #727
Description
For contributor use:
master
branchFiles changed
in the Github PR explorerSummary by CodeRabbit
New Features
Dependency Updates
Performance Improvements