fix(sdk): honor explicit outputSatoshis user parameter in stateful method calls#105
Open
E-Jacko wants to merge 1 commit into
Open
fix(sdk): honor explicit outputSatoshis user parameter in stateful method calls#105E-Jacko wants to merge 1 commit into
E-Jacko wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new resolution rung to the SDK's continuation-output satoshi computation so that when a stateful method declares an explicit public ABI parameter named
outputSatoshis, the SDK uses the user-supplied value for the continuation output's amount.Without this fix the SDK silently falls back to the input UTXO's satoshi count, which produces a post-broadcast
OP_EQUALVERIFYfailure (ARC HTTP 461) for any compiled contract that bakes the user'soutputSatoshisinto ahashOutputscovenant.Existing resolution priorities are preserved:
CallOptions.satoshis(caller override) still outranks the new rung, and methods that don't declareoutputSatoshiscontinue to default tocurrent_utxo.satoshis.Problem
Upstream HEAD
packages/runar-rs/src/sdk/contract.rs:720-725:There is no rung in this resolution that consults the user's declared ABI args. If a stateful contract method declares:
…and the user calls it with
outputSatoshis = 3000on an input UTXO that holds 5000 sats, the SDK builds a continuation output of 5000 sats while the contract body computes itshashOutputspreimage with the user's 3000. The on-chainOP_HASH256(serialize(output)) == committed_hashcheck fails, ARC rejects with HTTP 461.How this surfaced
Surfaced while building a stateful contract whose methods accept user-declared continuation-amount arguments. Methods that change the contract's locked satoshi count (split-style, partial-withdrawal-style, value-resize-style patterns) all declare
outputSatoshisas a public ABI param. The compiler bakes the user's value into ahashOutputscovenant check — without SDK-side resolution, the call broadcasts a non-matching-hash output and ARC rejects with HTTP 461. This was first observed on mainnet during a multi-step lifecycle where each step shrinks the contract's locked amount; every method invocation hit the same rejection until a vendored workaround injected the right satoshi value.Fix
Adds a third rung beneath the existing
CallOptions.satoshisfallback:Where
resolve_continuation_satoshisis a newpub fnincontract.rs:The helper is extracted from the inline call site (rather than left inline) so that the regression test can drive it through public surface without standing up a full stateful-contract deploy + call cycle. Production routes through the same helper; there is no "test passes / production diverges" risk.
Candid asymmetry against TS
The TS SDK's continuation-amount default lives at
runar-sdk/src/contract.ts:894:The Rust upstream at
runar-rs/src/sdk/contract.rs:720-725already matches this two-rung shape. This PR introduces a third rung beneath them (read the user's declaredoutputSatoshisABI arg) — and that third rung does not exist in canonical TS today.This is a genuine asymmetry. The shape this PR adds is consistent with how the compiler emits
outputSatoshis-bearing contracts: the compiler bakes the user's value into thehashOutputscovenant, so without SDK-side resolution the call broadcasts a non-matching-hash output and ARC rejects 461. The Rust patch is compiler-aligned with the source of truth (what the contract does on-chain), even though it's not strictly SDK-symmetric with TS today.Framed honestly: the Rust SDK catches up to what the Rust compiler emits. The TS SDK has the same latent gap and is likely to need a twin patch when downstream consumers hit the same on-chain rejection — but that's outside the scope of this PR. Happy to file the TS twin in parallel if maintainers prefer symmetry-first.
Verification
Passes with patch:
Fails without patch (surgical — drop only the user-arg rung in
resolve_continuation_satoshis):The three other tests intentionally lock the non-changed behavior — they pass pre- and post-patch, proving the patch did not regress (a) the
CallOptions.satoshisoverride, (b) the legacy fallback when nooutputSatoshisparam is declared, (c) the behaviour when the param is declared but the arg is not anInt.Backwards compatibility
outputSatoshispublic param see byte-identical behaviour (the new helper falls through to the legacycurrent_utxo.satoshisrung).CallOptions.satoshiscontinues to be the highest-priority override — explicit caller intent always wins.SdkValue::Int(_)(e.g. left asAuto), the helper falls through — locked byr3_param_declared_but_arg_not_int_falls_back.pub fn resolve_continuation_satoshisis genuinely useful pub surface for any third-party test against the SDK's continuation logic; it's not a test-only hatch.Related
runar broadcast and get_transaction: R1 in that PR surfaces the ARC HTTP 461 rejections that R3 actually fixes — the two are paired in the failure timeline (R1 makes the 461 visible; R3 eliminates one of the root causes).