feat(mining): operator-configurable custom extension fields - #199
Conversation
|
Warning Review limit reached
Next review available in: 41 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughMining configuration now accepts custom extension fields, validates and resolves them, propagates them through the mining handle and candidate-generation paths, and appends them to candidate extensions with duplicate and reserved-key checks. ChangesCustom mining extension fields
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant MiningConfig
participant NodeBoot
participant MiningHandle
participant CandidateBuilder
participant ExtensionBuilder
MiningConfig->>NodeBoot: resolve_extension_fields()
NodeBoot->>MiningHandle: with_extension_fields(fields)
MiningHandle->>CandidateBuilder: custom_extension_fields()
CandidateBuilder->>ExtensionBuilder: build_candidate_extension_fields(custom_fields)
ExtensionBuilder-->>CandidateBuilder: assembled extension fields
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ergo-mining/tests/engine_published_parity.rs (1)
475-475: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExercise a non-empty custom field through the engine path.
Every updated call passes
&[]. Add abuild_and_publishtest usingMiningHandle::with_extension_fields(...)and assert the published candidate contains the field. This protects the handle → engine → candidate wiring, not just the builder.Also applies to: 813-813, 949-949, 1046-1046, 1104-1104, 1123-1123, 1292-1292, 1311-1311, 1399-1399, 1527-1527, 1559-1559
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ergo-mining/tests/engine_published_parity.rs` at line 475, Update the engine-path tests around build_and_publish so at least one test uses MiningHandle::with_extension_fields(...) with a non-empty custom field instead of &[]. Assert that the published candidate contains that field, covering handle-to-engine-to-candidate propagation while preserving the existing empty-field cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@ergo-mining/tests/engine_published_parity.rs`:
- Line 475: Update the engine-path tests around build_and_publish so at least
one test uses MiningHandle::with_extension_fields(...) with a non-empty custom
field instead of &[]. Assert that the published candidate contains that field,
covering handle-to-engine-to-candidate propagation while preserving the existing
empty-field cases.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3a604d34-7673-48fc-8019-b1e5d774376f
📒 Files selected for processing (7)
ergo-mining/src/candidate.rsergo-mining/src/config.rsergo-mining/src/engine.rsergo-mining/src/extension_builder.rsergo-mining/src/handle.rsergo-mining/tests/engine_published_parity.rsergo-node/src/node/boot.rs
A general, opt-in mechanism for a miner to inject arbitrary optional
extension key-values into every block candidate — the merge-mining /
commitment hook (e.g. an Aegis 0xAE00 block commitment). Deliberately
general, not sidechain-specific: this is the reference for what the
Scala node would need, since Scala's CandidateGenerator has no such hook.
- extension_builder: validate_custom_extension_fields enforces rule 404
(value <= 64B), a reserved-namespace guard (first key byte not in
{0x00 params, 0x01 interlinks, 0x02 validation}), and rule 405 (no
dup keys); build_candidate_extension_fields appends validated custom
fields after interlinks/epoch and does a final all-field dup sweep.
- MiningHandle::with_extension_fields (validating, builder-style like
with_rent_config) + accessor; threaded through generate_candidate and
both engine call sites.
- Unknown extension keys are consensus-legal, so this never forks Ergo.
fmt + clippy -D clean; ergo-mining 127 lib + integration tests green.
Operator-facing config for the custom-extension-field mechanism, so it
is configurable via ergo-node.toml (not just the Rust builder):
[mining]
extension_fields = [ { key = "ae00", value = "01<32-byte aegis id>" } ]
- MiningConfig.extension_fields (Vec<CustomExtensionField> of hex
key/value), validated in MiningConfig::validate at startup (hex-
decodable, 2-byte key, then the consensus checks via
validate_custom_extension_fields) so a misconfig refuses to boot.
- resolve_extension_fields() decodes to (key, value) byte pairs.
- boot wires them onto the handle via .with_extension_fields(...)?.
ergo-mining: fmt + clippy -D clean, 129 lib + integration tests green.
Note: ergo-node lib does not build on this local checkout due to a
PRE-EXISTING ApiNodeEvent field mismatch (snapshot_emit.rs vs
ergo-api::types) reproducible on pristine main and unrelated to this
change; the full ergo-node gate needs a consistent main base.
…propagation Adds an engine-path test that configures a non-empty custom field via MiningHandle::with_extension_fields, runs build_and_publish, and proves the published candidate carries it: the served work msg commits to the extension_root, so it must equal the on-loop oracle built WITH the same field (whose candidate is asserted to contain it directly) and differ from a no-field build. New on_loop_build_with_fields helper; existing empty-field on_loop_build cases unchanged.
aa8b017 to
f9511e4
Compare
What
Adds an opt-in, operator-configurable mechanism for a miner to inject
arbitrary optional key-value fields into every block candidate's
Extensionsection — the general merge-mining / commitment hook.
Ergo's candidate builder currently assembles the extension from only
protocol-defined fields (NiPoPoW interlinks, and the parameter map /
validation-settings at voting-epoch boundaries). There is no way for an
operator to add a custom field, and because the extension's Merkle root is
inside the bytes Autolykos hashes, the commitment must be present at
candidate-build time (the external miner grinds a fixed
msg). This PR addsthat missing hook.
It is deliberately general, not tied to any one sidechain: any commitment
use case (a merge-mined chain, an anchoring/timestamp commitment, etc.) can
configure a field. Unknown extension keys are consensus-legal, so a candidate
carrying one is a valid Ergo block regardless of whether other nodes
understand it — this never forks the chain.
How
ergo-mining/extension_builder.rsvalidate_custom_extension_fields: enforces rule 404 (value ≤EXTENSION_FIELD_VALUE_MAX_SIZE), a reserved-namespace guard (a customkey's first byte may not be
0x00params /0x01interlinks /0x02validation, so it can never overwrite a consensus field), and rule 405
(no duplicate keys).
build_candidate_extension_fieldstakes acustom_fieldsargument,appends the validated fields after interlinks/epoch fields, and runs a
final duplicate-key sweep across the whole assembled extension.
MiningHandle::with_extension_fields— a validating, builder-style setter(mirrors
with_rent_config), plus an accessor; threaded throughgenerate_candidateand both engine call sites.[mining]) —MiningConfig.extension_fields, validated atstartup in
MiningConfig::validateso a misconfiguration refuses to boot;resolve_extension_fieldsdecodes the hex form;boot.rswires it onto thehandle.
Off by default (empty), so nodes not using it are unaffected.
Test plan
cargo fmt --all -- --check— cleancargo clippy --workspace --all-targets --all-features -- -D warnings— cleancargo build --workspace— cleancargo test -p ergo-mining— 129 lib + integration tests pass, including newcoverage: custom field appended after interlinks;
validate_*rejects areserved namespace / oversize value / duplicate key; config
resolve+validateround-trips and rejections.cargo test -p ergo-node --lib config:: / mining— 123 + 39 pass (config loadNotes
custom fields are additive and orthogonal to that path.
feature would need — Scala's
CandidateGeneratorhas no custom-field hooktoday, so cross-implementation merge-mining depends on a matching change
there.
Summary by CodeRabbit