feat(options): v0.2.0 — curated transfer builder + rehydration helper (#1288) - #2
Conversation
04110e2 to
056520a
Compare
MichaelTaylor3d
left a comment
There was a problem hiding this comment.
REVIEW GATE — PASS (verdict recorded as a comment; self-approval is a 422, branch protection needs 0 approvals)
Reviewed @ 056520a as a fresh, skeptical, security-critical (spend-building/custody) gate. Verdict: PASS.
Scope & spec
- Matches #1288 + the scope-expansion comment exactly: curated
transfer(ctx, owner, created, new_owner_puzzle_hash) -> Result<OptionSpend>+rehydrate/parse_metadata. API shape matches the dig-wallet-backend#12 seam (build_transfer_option/build_exercise_option). - SPEC.md §§1/4/5.6/5.7/7/8 updated in-unit, normative voice, no drift from the code. CHANGELOG + rustdoc on every new item. 0.1.0 → 0.2.0 (minor) correct for additive capability.
§5.1 additive discipline
Diff touches only new files (src/transfer.rs, src/rehydrate.rs) + mod/pub use/rustdoc in lib.rs + CHANGELOG/Cargo/SPEC/tests. create/exercise/clawback/parse/parse_child bodies are untouched — no existing symbol changed, renamed, or repurposed.
Adversarial custody verification (all lenses clear)
- Verified-not-trusted (rehydrate): the reconstructed 1-of-2 path hash binds launcher_id + creator_ph + expiry + amount + strike to
underlying_coin.puzzle_hash; the delegated-puzzle hash andunderlying_coin_idare independently checked. Any wrong term changes a committed hash →InvalidInput, never an operable-but-mistargeted handle. Covered byrehydrate_rejects_wrong_creator. - Fund-safety (transfer): faithfully composes
OptionContract::transfer— SDK emits the recipient hint; only the singleton re-homes at the same amount; the underlying + terms are untouched. Wrong-partyStandardowner rejected up front;Customcorrectly documented as consensus-enforced (PH not derivable). - Keys/custody: key-free types throughout; both new fns are pure builders (no signing, no I/O, no key held).
- Back-compat/replay: additive only; no wire/format/parse change.
Gates
CI green (Format/Clippy/Build/Docs, Coverage >=80%, version-increment, commitlint, CodeQL rust + js). cargo test locally: 20/20 pass. Zero open review threads, no GHAS findings.
Non-gating observation (does NOT block merge)
src/types.rs OptionSpend doc (~L130-138) and CreatedOption doc (~L109-115) still read as if created is Some only for create and terms are unrecoverable — now also true of transfer (returns Some) and lifted by rehydrate. Cosmetic doc-drift; safe to tidy opportunistically in a later touch, not a blocker for this PR.
Add two additive builders (SPEC.md §5.6/§5.7, §5.1-compatible): - transfer(ctx, owner, created, new_owner_puzzle_hash): move the option ticket to a new owner, composing OptionContract::transfer so consumers stop reaching past dig-options into the SDK primitive. Returns the re-homed option as the created handle; guards a wrong-party Standard owner up front. - rehydrate(option, terms, underlying_coin) + parse_metadata(ctx, launcher_solution): reconstruct a full, operable CreatedOption from on-chain state, VERIFIED against the option's commitments. Per the chia-wallet-sdk 0.30 OptionUnderlying derivation the three checks bind disjoint field sets and are jointly load-bearing: the 1-of-2 path hash (launcher id + expiry + creator ph only) catches a wrong creator hash; the delegated-puzzle hash catches a wrong strike type (and amount); the coin-id check rejects a substituted same-shape coin. A wrong term is rejected, never yields an unspendable handle. Tests (22 green): transfer round-trip + wrong-owner guard; rehydrate round-trip + wrong-creator/wrong-strike/wrong-amount rejections. clippy -D warnings clean. Closes #1288. Co-Authored-By: Claude <noreply@anthropic.com>
056520a to
bddfa1b
Compare
Closes DIG-Network/dig_ecosystem#1288.
What
Two additive v0.2.0 builders (SPEC.md §5.6/§5.7; §5.1 additive — no existing symbol edited):
transfer(ctx, owner, created, new_owner_puzzle_hash) -> OptionSpend— curated option-ticket transfer, composingOptionContract::transferso dig-wallet-backend stops reaching past dig-options into the SDK primitive (Appendix B: the expert crate owns option lifecycle logic). Returns the re-homed option ascreated: Some(..); a wrong-partyStandardowner is rejected up front.rehydrate(option, terms, underlying_coin) -> CreatedOption+parse_metadata(ctx, launcher_solution) -> OptionMetadata— reconstruct a full, operableCreatedOptionfrom on-chain state. v0.1.0parse/parse_childrecover only identity fields;rehydraterebuilds theOptionUnderlyingfrom caller-supplied creator ph + metadata-recovered expiry/strike + the observed underlying coin, and VERIFIES it against the option's on-chain commitments (1-of-2 path hash, delegated-puzzle hash, underlying coin id). A wrong term is rejected withInvalidInput— never a handle that builds an unspendable bundle. This unblocks transfer AND exercise of previously-minted options (dig-wallet-backend#12, Lane dig_ecosystem#1123).New public surface:
transfer,rehydrate,parse_metadata,RehydratedTerms,OptionMetadata(re-export).How verified
transfer_moves_option_then_new_owner_exercises— mint→transfer bob→carol→carol exercises; asserts new p2 hash, confirmed re-homed coin, and value conservation (carol nets underlying−strike, original creator alice receives the strike).transfer_rejects_wrong_owner— up-front guard.rehydrate_recovers_operable_option— reconstruct purely from on-chain state (parse singleton, parse_metadata from launcher solution, fetch underlying coin), assert recovered terms == minted, then EXERCISE the rehydrated handle to prove operability.rehydrate_rejects_wrong_creator— wrong creator ph rejected at the 1-of-2 path check.cargo fmt --check,cargo clippy --all-targets -D warnings,cargo doc --no-depsall clean.Blast radius (gitnexus disabled — ripgrep + reads)
Purely additive: two new modules (
transfer.rs,rehydrate.rs) + lib.rs re-exports + SPEC/CHANGELOG/version. No existing symbol edited (confirmed by diff);create/exercise/clawback/parseuntouched. Reuses SDKOptionContract::transfer,OptionContract::parse_metadata,OptionUnderlying— no hand-rolled puzzle logic. Level-00 foundation crate: no DIG-crate deps added.Bump rationale
0.1.0 → 0.2.0 (minor) — new public capability, fully additive, no breaking change (§2.4 SemVer). Release-first: merge cuts the v0.2.0 crates.io tag; dig-wallet-backend adopts on its follow-up.
Branch HEAD: 056520a