diff --git a/doc/src/architecture/tx_lifetime.md b/doc/src/architecture/tx_lifetime.md index 9e38c1134..374b0afb3 100644 --- a/doc/src/architecture/tx_lifetime.md +++ b/doc/src/architecture/tx_lifetime.md @@ -194,3 +194,62 @@ pub struct Note { In the blockchain state, every minted coin must be added into a Merkle tree of all existing coins. Once added, the new tree root is used to prove existence of this coin when it's being spent. + +Let's imagine a scenario where Alice has 100 ALICE tokens and wants to +send them to Bob. Alice would create an `Input` object using the info +she has of her coin. She has to derive a `nullifier` given her secret +key and the serial number of the coin, hash the coin bulla so she can +create a merkle path proof, and derive the value and token commitments +using the blinds. + +```rust +let nullifier = poseidon_hash([alice_secret_key, serial]); +let signature_public = alice_secret_key * Generator; +let coin = poseidon_hash([signature_public, value, token_id, blind]); +let merkle_root = calculate_merkle_root(coin); +let value_commit = pedersen_commitment(value, value_blind); +let token_commit = pedersen_commitment(token_id, token_blind); +``` + +The values above, except `coin` become the public inputs for the `Burn` +ZK proof. If everything is correct, this allows Alice to spend her coin. +In DarkFi, the changes have to be atomic, so any payment transaction +that is burning some coins, has to mint new coins at the same time, and +no value must be lost, nor can the token ID change. We enforce this by +using Pedersen commitments. + +Now that Alice has a valid `Burn` proof and can spend her coin, she can +mint a new coin for Bob. + +```rust +let blind = pallas::Base::random(); +let value_blind = ValueBlind::random(); +let token_blind = ValueBlind::random(); +let coin = poseidon_hash([bob_public, value, token_id, blind]); +let value_commit = pedersen_commitment(value, value_blind); +let token_commit = pedersen_commitment(token, token_blind); +``` + +`coin`, `value_commit`, and `token_commit` become the public inputs +for the `Mint` ZK proof. If this proof is valid, it creates a new coin +for Bob with the given parameters. Additionally, Alice would put the +values and blinds in a `Note` which is encrypted with Bob's public key +so only Bob is able to decrypt it. This `Note` has the necessary info +for him to further spend the coin he received. + +At this point Alice should have 1 input and 1 output. The input is the +coin she burned, and the output is the coin she minted for Bob. Along +with this, she has two ZK proofs that prove creation of the input and +output. Now she can build a transaction object, and then use her secret +key she derived in the `Burn` proof to sign the transaction and publish +it to the blockchain. + +The blockchain will execute the smart contract with the given payload +and verify that the Pedersen commitments match, that the nullifier has +not been published before, and also that the merkle authentication path +is valid and therefore the coin existed in a previous state. Outside of +the VM, the validator will also verify the signature(s) and the ZK +proofs. If this is valid, then Alice's coin is now burned and cannot be +used anymore. And since Alice also created an output for Bob, this new +coin is now added to the Merkle tree and is able to be spent by him. +Effectively this means that Alice has sent her tokens to Bob.