fix(coprocessor): use block hash to identify transaction#2098
fix(coprocessor): use block hash to identify transaction#2098
Conversation
9bdd318 to
dd87cb8
Compare
🧪 CI InsightsHere's what we observed from your CI run for ba3a8bb. 🟢 All jobs passed!But CI Insights is watching 👀 |
fd5809b to
707a3db
Compare
Coprocessor Changed Lines CoverageCoverage of added/modified lines in Per-file breakdownDiff CoverageDiff: origin/main...HEAD, staged and unstaged changes
Summary
coprocessor/fhevm-engine/scheduler/src/dfg.rscoprocessor/fhevm-engine/scheduler/src/dfg/scheduler.rs |
707a3db to
60650da
Compare
60650da to
b582cca
Compare
|
@claude /pr-review |
...engine/db-migration/migrations/20260309163043_concurrent_index_computations_block_hash_2.sql
Outdated
Show resolved
Hide resolved
b582cca to
9f0a2e9
Compare
1b633ec to
b3736cc
Compare
b3736cc to
586b47e
Compare
|
@claude /pr-review |
|
Run was cancelled before completion. — View run |
|
@claude /pr-review |
|
The review has been posted successfully. Here's a summary of what was reviewed and found: Review Posted ✅PR #2098: Key Finding
Clean Areas
NitRedundant |
|
Run was cancelled before completion. — View run |
|
@claude /pr-review |
There was a problem hiding this comment.
[AUTOMATED]
Code Review Summary
This PR changes transaction identification in the coprocessor from using transaction_id alone to a composite key (transaction_id, block_hash). The change is well-structured — the new Transaction struct cleanly encapsulates the composite identity, and the SQL queries, scheduler, and worker are all consistently updated.
Overall: Sound architectural change with one blocking database migration issue and a couple of minor nits.
Key Observations
- ✅ Good: The new
Transactiontype provides a clean abstraction for the composite key - ✅ Good:
set_computation_errornow checksrows_affected() == 0and warns — this is a meaningful improvement over silently ignoring the result - ✅ Good: Concurrent index creation avoids locking the table during migration
- ✅ Good: Tests and helpers consistently updated with
block_hash: ...::ZERO ⚠️ Blocking: Old unique index not dropped (see inline comment)- ℹ️ sqlx-cli version bump from 0.7.2 → 0.8.6 is bundled in — presumably needed for the new query patterns
|
|
||
| -- For next release, we should remove the default values for block_hash and block_number. | ||
| -- ALTER TABLE computations ALTER COLUMN block_hash DROP DEFAULT; | ||
| -- ALTER TABLE computations ALTER COLUMN block_number DROP DEFAULT; |
There was a problem hiding this comment.
[AUTOMATED] Bug (Confidence: 95/100): The existing unique index idx_computations_no_tenant ON computations (output_handle, transaction_id) (created in migration 20260128095635_remove_tenants.sql, line 88) is not dropped by any of the new migrations.
This means:
- The old 2-column unique constraint
(output_handle, transaction_id)is still enforced - You cannot insert two rows with the same
(output_handle, transaction_id)but differentblock_hashvalues — the old index will reject them - The
ON CONFLICT (output_handle, transaction_id, block_hash) DO NOTHINGclause targets the new 3-column unique index, so a conflict on the old 2-column index would raise an error rather than being silently handled
This defeats the purpose of the PR — the whole point of adding block_hash to the key is to allow the same (output_handle, transaction_id) to exist across different blocks (e.g., during reorgs).
Suggested fix: Add a migration step before creating the new index:
DROP INDEX IF EXISTS idx_computations_no_tenant;| .node_weight(*consumer) | ||
| .ok_or(SchedulerError::DataflowGraphError)?; | ||
| error!(target: "scheduler", { producer_id = ?hex::encode(prod.transaction_id.clone()), consumer_id = ?hex::encode(cons.transaction_id.clone()) }, | ||
| error!(target: "scheduler", { producer = ?prod.transaction.clone(), consumer_id = ?cons.transaction.clone() }, |
There was a problem hiding this comment.
[AUTOMATED] Nit (Confidence: 85/100): Inconsistent structured log field naming — one field is producer and the other is consumer_id:
error!(... { producer = ?prod.transaction.clone(), consumer_id = ?cons.transaction.clone() }, ...)Since the values are now Transaction structs (not IDs), consider using consistent naming like producer / consumer or producer_tx / consumer_tx. The _id suffix on only one of them is misleading. This also applies to the similar log line earlier in the same function.
|
The review was successfully posted. Let me provide a summary. Review Posted Successfully ✅The review has been posted to PR #2098 with the following findings: 🔴 Critical Issue (1)Missing
💛 Nit (1)Inconsistent log field naming in ✅ Positive Observations
|
fa0cfd7 to
c88a87a
Compare
9be5ded to
bc4b51d
Compare
|
@claude /pr-review |
|
Claude timed out while processing the request. — View run |
|
@claude /pr-review |
1 similar comment
|
@claude /pr-review |
There was a problem hiding this comment.
[AUTOMATED]
Code Review
Summary
This PR correctly addresses a critical bug where blockchain reorganizations (reorgs) could cause transaction ID collisions, leading to circular dependency cycles in the computation scheduler. The fix adds block_hash as part of the composite key (output_handle, transaction_id, block_hash) to uniquely identify computations.
What was reviewed
- Bug analysis (2 independent passes): No runtime bugs found. All SQL queries, Rust type changes, and data flows are internally consistent.
- Guideline compliance: Code follows project conventions (Angular commit format, Rust patterns).
- Error handling: No silent failures introduced. The addition of
rows_affected()check inset_computation_erroris a positive improvement over the previouslet _ = query!(...)pattern.
Changes verified
| Area | Status |
|---|---|
DB migration adds block_hash to PK and unique index |
✅ Correct |
Transaction struct with (transaction_id, block_hash) |
✅ Well-designed |
SQL SELECT, INSERT, UPDATE queries include block_hash |
✅ Consistent |
ON CONFLICT clause updated to composite key |
✅ Correct |
HashMap grouping uses Transaction as key |
✅ Hash/Eq properly derived |
| All scheduler/DFG type signatures updated | ✅ Complete |
Test helpers updated with block_hash: ZERO |
✅ Appropriate |
| sqlx-cli version bump (0.7.2 → 0.8.6) | ✅ |
| CI logs now include db-migration container | ✅ Nice addition |
Nits (non-blocking)
- Nit: Commit message body typos —
"butkeeping"→"but keeping","sametx"→"same tx"in the commit body. Minor, but worth noting since PRs are squash-merged. - Nit: Redundant
PartialEqimpl — The manualimpl PartialEq<Transaction> for &Transactionintypes.rsis redundant with the derivedPartialEqonTransaction. Rust's auto-deref handles&Transaction == Transactioncomparisons already. Not harmful, but could be removed for clarity.
Verdict
Clean, well-scoped fix. The composite key approach is the right solution for disambiguating transactions across reorgs. All data paths (ingest → DB → scheduler → worker → DB update) are consistently updated. No bugs or security issues found.
|
The review has been posted successfully. Here's a summary of what was done: PR Review Complete ✅PR #2098: Review Process
Verdict: APPROVEDClean, well-scoped fix with consistent changes across DB schema, Rust types, SQL queries, and the scheduler/worker pipeline. Two minor nits noted (commit body typos and a redundant Review posted at: #2098 (review) |
22a3d3a to
e032e6b
Compare
|
@claude /pr-review |
There was a problem hiding this comment.
[AUTOMATED]
Code Review Summary
This PR correctly adds block_hash to the composite key identifying computations, enabling proper handling of blockchain reorgs. The changes are thorough and consistent across the DB migration, SQL queries, and Rust code.
What was reviewed
- Database migration for adding
block_hashto the primary key and unique index - SQL query updates (INSERT, SELECT, UPDATE) across host-listener and tfhe-worker
- New
Transactionstruct in scheduler types and its propagation through the DFG - Error handling improvements in
set_computation_error - Test helper updates
- sqlx-cli version bump and CI logging addition
Findings
1 low-severity observation, 1 nit — neither blocking.
Overall the PR is well-structured with consistent changes across all layers. The rows_affected() == 0 warning in set_computation_error is a nice defensive improvement.
| @@ -0,0 +1,26 @@ | |||
| ALTER TABLE computations | |||
| ADD COLUMN IF NOT EXISTS block_hash BYTEA NOT NULL DEFAULT '\x00'::BYTEA, | |||
| ADD COLUMN IF NOT EXISTS block_number BIGINT NOT NULL DEFAULT 0; | |||
There was a problem hiding this comment.
[AUTOMATED] Nit: ADD COLUMN IF NOT EXISTS block_number is a no-op here
The previous migration 20260319120000_add_block_number_for_state_revert.sql already added block_number BIGINT NULL DEFAULT NULL to computations. Since IF NOT EXISTS is used, this line silently does nothing — the column retains its original NULL DEFAULT NULL constraint rather than becoming NOT NULL DEFAULT 0 as written here.
This is harmless because:
- The INSERT in
tfhe_event_propagate.rsalways provides an explicitblock_numbervalue - The
tfhe-workerSELECT query doesn't readblock_number
But it may be misleading to future readers who expect block_number to be NOT NULL. Consider either:
- Removing the
block_numberpart from this migration (since it's already handled) - Or adding an explicit
ALTER TABLE computations ALTER COLUMN block_number SET NOT NULL, ALTER COLUMN block_number SET DEFAULT 0;if theNOT NULLconstraint is desired
Confidence: 95/100
|
The review has been posted successfully. Here's a summary of the review: PR Review: fix(coprocessor): use block hash to identify transaction (#2098)Review Posted ✅The review was posted as a COMMENT (non-blocking) with inline comments on 2 files. SummaryThis PR adds No bugs found. The changes are thorough and consistent. Two non-blocking nits were noted:
|
945e257 to
2b30338
Compare
fixes a bug where 2 transactions are swapped in a reorg but keeping the same tx id and being dependent on each other the 4 apparent tx are merged to 2 tx and create a cycle
2b30338 to
f11fe50
Compare
|
@claude /pr-review |
|
Claude timed out while processing the request. — View run |
No description provided.