[WIP] Policy signing - #282
Draft
bigspider wants to merge 8 commits into
Draft
Conversation
Add the SigningPolicy type and the PSBT global SIGNING_POLICY proprietary field, plus the signing-policy error variants. Introduce the derivation-path binding helpers (signing_policy_chunks / signing_policy_key_path / parse_signing_policy_path): a program's SHA-256 is truncated to four 31-bit chunks that form a standard BIP-32 path m/1347175257'/1'/<account>'/p1/p2/p3/p4. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bigspider
force-pushed
the
policy_signing3
branch
from
July 28, 2026 09:16
e8f7a16 to
20a8a4a
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces signing policies for the Bitcoin app: wallet-policy keys can be bound (via a standard BIP-32 origin path) to small programs that are carried in PSBT globals and evaluated on-device to deny signing or allow silent signing.
Changes:
- Define a PSBT global proprietary format for content-addressed signing-policy programs (hash-based) and add helpers to read/write them.
- Add a policy engine and execution path in the app to enforce policies for both plain keys and
musig(...)participants, including silent-signing behavior. - Extend the client + CLI workflow to compute policy hashes, bind keys via derivation paths, register accounts with programs, and insert programs into PSBTs before signing; update docs accordingly.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/bitcoin/docs/README.md | Documents the signing-policy feature and provides a CLI workflow for hashing/binding/registering/signing with .plc programs. |
| apps/bitcoin/docs/PSBT.md | Extends the PSBT extension spec to include signing-policy programs and the binding scheme via derivation paths. |
| apps/bitcoin/common/src/psbt/signing_policy.rs | Adds the canonical signing-policy PSBT global encoding, hashing, path binding helpers, and tests. |
| apps/bitcoin/common/src/psbt/mod.rs | Exposes the new signing_policy module and re-exports its API. |
| apps/bitcoin/common/src/message/mod.rs | Extends the RegisterAccount request to include signing programs for validating policy-bound internal keys. |
| apps/bitcoin/common/src/errors.rs | Adds error codes/messages for signing-policy parsing/availability/engine support/execution. |
| apps/bitcoin/client/tests/integration_test.rs | Adds an end-to-end test covering a policy-bound account and enforcement behavior. |
| apps/bitcoin/client/src/psbt.rs | Implements raw PSBT mutation to insert signing-policy globals while preserving other bytes/maps. |
| apps/bitcoin/client/src/main.rs | Adds CLI flags for --signing-policy, implements policy file reading/deduplication, and a hash/path helper command. |
| apps/bitcoin/client/src/lib.rs | Re-exports signing-policy helpers/types from common and the client PSBT insertion utility. |
| apps/bitcoin/client/src/client.rs | Updates register_account to send signing programs alongside the account registration request. |
| apps/bitcoin/app/src/policy/mod.rs | Introduces policy evaluation plumbing and engine dispatch/validation functions. |
| apps/bitcoin/app/src/policy/engine/program.rs | Implements the built-in minimal “signing program” language, parser, evaluator, and extensive tests. |
| apps/bitcoin/app/src/policy/engine/mod.rs | Registers the built-in program engine module. |
| apps/bitcoin/app/src/policy/context.rs | Defines the aggregate, read-only PolicyContext and its typed field schema for programs. |
| apps/bitcoin/app/src/main.rs | Wires signing programs into the app request handling (registration path). |
| apps/bitcoin/app/src/handlers/sign_psbt.rs | Enforces signing policies during signing, supports silent signing, and adds integration tests for the feature. |
| apps/bitcoin/app/src/handlers/register_account.rs | Validates policy-bound keys at registration time (program present + compiles + path matches) and updates tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add the policy engine abstraction, the transaction-global PolicyContext, and the built-in tiny program language (tokenizer, parser, tree-walking evaluator) with its fail-closed semantics. Declare the module in the app crate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bigspider
force-pushed
the
policy_signing3
branch
3 times, most recently
from
July 28, 2026 13:35
d73bde1 to
04cfa17
Compare
Carry the full programs in Request::RegisterAccount. During registration, recognize a device-controlled key as policy-bound by its signing-policy origin path, require the matching program, and compile it (fail closed otherwise). The binding rides ordinary key origins, so it is committed by the registration proof and works for musig() keys. The policy hash (if present) is shown on screen for internally controlled keys, allowing the user to independently validate whether it matches the expected one using a trusted source or a third device. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Detect a policy-bound key by its origin path prefix, recompute the path chunks from the supplied program, and gate signing on the policy decision. Derivation is ordinary BIP-32 (no synthetic chaincode). Policies are enforced for musig() participants too: a denied policy makes the device emit neither a round-1 pubnonce nor a round-2 partial signature. Decisions are evaluated once per policy hash; silent approval can skip confirmation only after verification succeeds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Send full programs at registration, insert them into the PSBT global map before signing, and re-export the path helpers. The CLI's signing_policy_hash prints the hash and the origin path (m/1347175257'/1'/<account>'/p1/p2/p3/p4). The e2e test fetches the device xpub at that path and builds the PSBT programmatically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Describe the path-based binding (m/1347175257'/1'/<account>'/p1/p2/p3/p4), the 124-bit chunk derivation, musig() enforcement, and the CLI workflow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keys with signing policies can specify that a transaction can be signed without user approval, but that would be insecure if the transaction has features that might compromise its integrity, like unverified inputs - or sighash flags (currently unsupported). Therefore, we fail explicitly in that case. If desired, a modifier could be added to allow signing policies to change this behavior, but it would need to be done with explicit opt-in.
bigspider
force-pushed
the
policy_signing3
branch
from
July 28, 2026 14:05
04cfa17 to
cf25e1f
Compare
The /asset folder is created for any shared non-code files relevant to multiple crates in the apps/bitcoin V-App workspace.
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.
No description provided.