zkBitcoin
Use zero-knowledge applications (zkapps) on Bitcoin! (Currently only on testnet.)
How does it work? Write your zkapp in circom and deploy it on Bitcoin by sending a transaction to our multi-party wallet run by a committee of nodes.
To use a zkapp, provide a correct proof of execution using snarkjs to our multi-party wallet which will trigger a threshold signature, eventually allowing funds to move out of the zkapp.
Check the whitepaper here. You can also watch a demo here.
Installation
Jump straight to usage if you want to see some examples, but make sure to read this section otherwise things won't work!
Circom/snarkjs
We build on top of the well-known circom/snarkjs stack.
To install circom
, please follow their guide.
To install snarkjs
, just run:
npm install -g snarkjs@latest
Bitcoin wallet
On top that, you'll need your own Bitcoin node/wallet. This application will perform queries to your node/wallet in order to fund your zkapp transactions.
All the following commands expects the following environment variables to be set so that it can communicate with your node/wallet:
export RPC_WALLET="walletname"
export RPC_ADDRESS="http://127.0.01:18331"
export RPC_AUTH="username:password"
zkbtc: the zkBitcoin CLI
To install zkbtc
, run the following command:
cargo install --git https://github.com/sigma0-xyz/zkbitcoin.git
Usage
There are two types of zkapps: stateless and stateful.
Stateless zkapps
A stateless zkapp is single-use, and the bitcoin it locks can be redeemed by anyone who can provide a proof of correct execution. An example of a stateless zkapp is in examples/circuit/stateless.circom
(which releases funds to anyone who can find the preimage of a hash function).
A stateless zkapp must always contains one public input that authenticates the transaction that spends it:
// circom code
template Main() {
signal input truncated_txid;
// TRUNCATED...
}
component main{public [truncated_txid]} = Main();
The zkapp doesn't have to do anything with the truncated_txid
field (although it can if it wants to).
You can deploy a stateless zkapp with the following command:
$ zkbtc deploy-zkapp --circom-circuit-path examples/circuit/stateless.circom --satoshi-amount 1000
This will lock 1,000 satoshis in the zkapp and return the transaction ID of the transaction that deployed the zkapp. A stateless zkapp can be referenced by that transaction ID.
Bob can then unlock the funds from the stateless zkapp with the following command:
$ zkbtc use-zkapp --txid "e793bdd8dfdd9912d971790a5f385ad3f1215dce97e25dbefe5449faba632836" --circom-circuit-path examples/circuit/stateless.circom --proof-inputs '{"preimage":["1"]}' --recipient-address "tb1q6nkpv2j9lxrm6h3w4skrny3thswgdcca8cx9k6"
Stateful zkapps
A stateful zkapp is a zkapp that has a state, and which state can be updated without consuming the zkapp.
An example of a stateful zkapp is in examples/circuit/stateful.circom
. A stateful zkapp must always contains a number of additional public inputs, allowing an execution to authenticate the zkapp state transition, as well as the amounts being withdrawn and deposited:
// circom code
template Main() {
signal output new_state;
signal input prev_state;
signal input truncated_txid; // this should not affect output
signal input amount_out;
signal input amount_in;
// TRUNCATED...
}
component main{public [prev_state, truncated_txid, amount_out, amount_in]} = Main();
You can deploy a stateful zkapp with the following command:
$ zkbtc deploy-zkapp --circom-circuit-path examples/circuit/stateful.circom --initial-state "1" --satoshi-amount 1000
You can use a stateful zkapps with the following command:
$ zkbtc use-zkapp --circom-circuit-path examples/circuit/stateful.circom --proof-inputs '{"amount_in":["1000"], "amount_out":["1000"]}' --recipient-address "tb1q6vjawwska63qxf77rrm5uwqev0ma8as8d0mkrt" --txid "76763d6130ee460ede2739e0f38ea4d61cc940b00af5eab83e5afb0fcc837b91"
specifying the following inputs:
amount_out
: amount being withdrawnamount_in
: amount being deposited
Other inputs will be automatically filled in (for example, it will use the zkapp's state as prev_state
input).
Get information about a zkapp
You can retrieve information about a specific zkapp by running the following command with the zkapp's transaction id:
$ zkbtc get-zkapp 7f08eeb5a4cba9bed161ba54bb28db4fc6ce51273e48d40969d5d89fdab61770
List all deployed zkapps
You can list all currently-deployed zkapps in the following way:
$ zkbtc list-zkapps
Tell me more
You can read more about zkBitcoin in our whitepaper, our documentation, and about advanced usage in our developer documentation.