Spend Scroll outputs
A Bitcoin output carrying a Scroll charm is locked to an
address controlled by the scrolls_bitcoin_v15 canister — no single private key
can spend it. To spend it, you build the transaction, sign your own inputs, and
ask the canister to sign its inputs and broadcast. This guide uses the canister’s
sign_and_submit method.
How it works
Section titled “How it works”The canister will sign a Scroll input only if the transaction:
- carries a valid Charms spell, and
- pays the configured Scrolls protocol fee.
So you can’t move Scroll-controlled funds arbitrarily — only via a transaction whose spell is correct. That is the whole point of Scrolls: programmable custody enforced by Charms logic.
-
Build the spell transaction. Prove a spell that spends the Scroll output and pays the fee output, producing an (unsigned) Bitcoin transaction — for example with
charms spell prove(you’ll need a prover server for Scroll spells). The result is yourtx_to_sign. -
Sign your own inputs. Sign every input that is not Scroll-controlled (e.g. your funding UTXOs). Leave the Scroll inputs unsigned. The canister requires that your inputs are already signed and its inputs are not.
-
Call
sign_and_submit. Pass the network, the Scroll input indexes to sign, the prerequisite transactions, and the partially-signed transaction:Terminal window icp canister call --network ic rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \'("main", record {sign_inputs = vec { 0 : nat32 }; # indexes of the Scroll inputsprev_txs = vec { "0200000000…" }; # txs that created the spent outputstx_to_sign = "0200000000…"; # your partially-signed txv14_sign_inputs = null;})'Use
"main"or"testnet4"for the network. -
Get the txid. On success the canister verifies the spell, checks the fee, signs its inputs, broadcasts the transaction, and returns
{ txid, wtxid }. Re-broadcasting an already-confirmed transaction is idempotent.
Calling programmatically
Section titled “Calling programmatically”Call the v15 canister with any Internet Computer agent (ic-agent/agent-rs) from
your application code instead of the icp CLI.
The scrolls-api HTTP wrapper (POST /{network}/sign) targets the older v14
canister and its nonce-based addresses — use it only for legacy v14 Scroll UTXOs,
not for v15.
See the Scrolls canister reference for the full
method signatures and the SignRequest shape.