Repository navigation
contracts: sign a contract spend only as the wallet showed it - #36
Merged
Merged
Conversation
The engine could sign any spend it built. A wallet must sign for a contract only when five things hold: the template is on its list, it recomputed the output, it ran the program against the final transaction, it showed the template, path, parameters by role and its own balance change, and the key is one reserved for contracts. Approval::prepare checks the first, second, third and fifth, and the chain's locks, and writes the summary the wallet shows (the template by the registry's name, else its commitment root; every parameter by role; the wallet's balance change in every asset beside the contract's, the payments and the fee) with a digest over it. Approval::sign signs only when handed that digest back, after preparing the spend again and running the program once more against the transaction it returns. Spend::finalize is no longer public, so the gate is the only way in. lwk_wasm exposes ContractApproval and Signer.signContractSpend, so a browser wallet shows the summary and signs what it showed.
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.
Signing for a contract under the five-point rule. A wallet signs a contract spend only through
Approval, which checks the rule, shows what is signed, and signs only the digest of what it showed.What it does
Approval::prepare(spend, view, signer)checks:m/8383h/{coin}h/0h, the one the path names.It also checks the chain's locks.
The summary shows:
Approval::sign(shown_digest, signer)refuses any other digest. It prepares the spend again, refuses if anything differs, and runs the program once more against the transaction it returns. A signature made only to run the program before approval is dropped inside the engine.Spend::finalizebecomes crate-private, so the gate is the only way to sign.lwk_wasm:ContractApproval.prepare(spend, signer, viewJson),.summary(),.digest();Signer.signContractSpend(approval, shownDigest).Proof (node v25.2.1,
elementsregtest, Simplicity from genesis,-par=1). Before this change the new tests do not compile (unresolved import lwk_contracts::approval), and the wasm drive fails atContractApprovalundefined.cargo test -p lwk_contracts --test approval, no chain needed:c1a71ea2…46faunregistered, orsequentia/one-key v1 (registered);--test drip_regtestthrough the gate: the drip confirms; the three bad drips are refused by the engine and, forced, in blocks (bad-txns-nonfinal;Assertion failed inside jettwice).lwk_wasm/tests/node/contract_drip_regtest.js, the wallet flow in wasm:sequentia/faucet-drip v1 (registered), all 13 parameters by role, and the wallet's change500.00000000 tSEQ;non-BIP68-final) and in a block (bad-txns-nonfinal);