Scheme
Let be defined as in the section PoseidonHash Function.
Transfer
This function transfers value by burning a set of coins , and minting a set of coins, such that the value spent and created are equal.
- Wallet:
- Builder:
src/contract/money/src/client/transfer_v1/builder.rs
- Convenience methods:
src/contract/money/src/client/transfer_v1/mod.rs
- Build proofs:
src/contract/money/src/client/transfer_v1/proof.rs
- Builder:
- WASM VM code:
src/contract/money/src/entrypoint/transfer_v1.rs
- ZK proofs:
src/contract/money/proof/burn_v1.zk
src/contract/money/proof/mint_v1.zk
Function Params
Let be defined as in Inputs and Outputs.
Define the Money transfer function params
/// Parameters for `Money::Transfer` and `Money::OtcSwap`
pub struct MoneyTransferParamsV1 {
/// Anonymous inputs
pub inputs: Vec<Input>,
/// Anonymous outputs
pub outputs: Vec<Output>,
}
Contract Statement
Let be defined as in ZK Proofs.
ZK Proofs
Mint_V1
Using the Mint_V1
circuit, we are able to create outputs
in our UTXO set. It is used along with the Burn_V1
circuit in
MoneyFunction::TransferV1
where we perform a payment to some address
on the network.
Denote this proof by .
Circuit witnesses:
- - Public key of the recipient which goes into the coin commitment (pallas curve point)
- - Value of the coin commitment (unsigned 64-bit integer)
- - Token ID of the coin commitment (pallas base field element)
- - Unique serial number of the coin commitment (pallas base field element)
- - Spend hook, allows composing this ZK proof to invoke other contracts (pallas base field element)
- - Data passed from this coin to the invoked contract (pallas base field element)
- - Random blinding factor for a Pedersen commitment to (pallas scalar field element)
- - Random blinding factor for a commitment to (pallas base field element)
Circuit public inputs:
- - Coin commitment
- - Pedersen commitment to
- - Token ID commitment
Circuit:
and are constant well-known generators that are in the codebase
as VALUE_COMMIT_VALUE
and VALUE_COMMIT_RANDOM
:
src/sdk/src/crypto/constants/fixed_bases/value_commit_v.rs
src/sdk/src/crypto/constants/fixed_bases/value_commit_r.rs
Burn_V1
Using the Burn_V1
circuit, we are able to create inputs in
our UTXO set. It is used along with the Mint_V1
circuit in
MoneyFunction::TransferV1
where we perform a payment to some address
on the network.
Denote this proof by .
Circuit witnesses:
- - Value of the coin being spent (unsigned 64-bit integer)
- - Token ID of the coin being spent (pallas curve base field element)
- - Random blinding factor for a Pedersen commitment to (pallas scalar field element)
- - Random blinding factor for a commitment to (pallas base field element)
- - Unique serial number of the coin commitment (pallas base field element)
- - Spend hook, allows composing this ZK proof to invoke other contracts (pallas base field element)
- - Data passed from this coin to the invoked contract (pallas base field element)
- - Blinding factor for encrypting (pallas base field element)
- - Secret key used to derive (nullifier) and (public key) from the coin (pallas base field element)
- - Leaf position of in the Merkle tree of all coin commitments (unsigned 32-bit integer)
- - Merkle path to the coin in the Merkle tree (array of 32 pallas base field elements)
- - Secret key used to derive public key for the tx signature
Circuit public inputs:
- - Published nullifier to prevent double spending
- - Pedersen commitment to
- - Token ID commitment
- - Merkle root calculated from and
- - Commitment to
- - Spend hook
- - Public key derived from used for transaction signing
Circuit:
and are the same generators used in Mint_V1
, is the
generator in the codebase known as NULLIFIER_K
:
src/sdk/src/crypto/constants/fixed_bases/nullifier_k.rs
ZeroCond
is a conditional selection: f(a, b) = if a == 0 {a} else {b}
.
We use this because the Merkle tree is instantiated with a fake coin of
value 0 and so we're able to produce dummy inputs of value 0.
Contract call creation
Assuming a coin exists on the blockchain on leaf position and does not have a corresponding published nullifier , it can be spent. To create the necessary proofs, Alice uses the known values of her coin and picks other values that are needed to create a new coin that will be minted to Bob after is spent.
Values for Burn_V1
:
- Alice picks a random element from to use as the secret key in order to sign the transaction.
- Alice picks a random element from to use as the blinding factor for .
- Alice picks a random element from to use as the blinding factor for .
- Alice creates the
Burn_V1
ZK proof using the existing known values of her coin and the values picked above.
Values for Mint_V1
:
- Alice picks a random element from to use as a unique serial number for the new coin .
- Alice optionally chooses a contract ID to use as or uses
ZERO
if does not have to call another contract. - Alice optionally chooses necessary data for or uses
ZERO
if no data has to be passed. - Alice chooses the corresponding to be able to enforce the Pedersen commitment correctness ( has to evaluate to )
- Alice creates the
Mint_V1
ZK proof using the existing known values and the values picked above.
After creating the proofs, Alice builds a transaction containing a
number of inputs that were created with Burn_V1
and a number of
outputs created with Mint_V1
.
/// Parameters for `Money::Transfer` and `Money::OtcSwap`
pub struct MoneyTransferParamsV1 {
/// Anonymous inputs
pub inputs: Vec<Input>,
/// Anonymous outputs
pub outputs: Vec<Output>,
}
This gets encoded into the Transaction
format and the transaction is
signed with a Schnorr signature scheme using the secret key chosen
in Burn_V1
.
Contract call execution
For MoneyFunction::TransferV1
, we have the following functions, in
order: