diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md index bdc1f9c3b..a6f3da5de 100644 --- a/doc/src/SUMMARY.md +++ b/doc/src/SUMMARY.md @@ -32,11 +32,6 @@ - [Anonymous assets](arch/anonymous_assets.md) - [Blockchain](arch/blockchain.md) - [Consensus](arch/consensus.md) - - [GenesisStake](arch/consensus/genesis_stake.md) - - [Stake](arch/consensus/stake.md) - - [Proposal](arch/consensus/proposal.md) - - [UnstakeRequest](arch/consensus/unstake_request.md) - - [Unstake](arch/consensus/unstake.md) - [Transactions](arch/tx_lifetime.md) - [Smart Contracts](arch/smart_contracts.md) - [Bridge](arch/bridge.md) diff --git a/doc/src/arch/consensus.md b/doc/src/arch/consensus.md index 3942d2c8b..97b2cc5d6 100644 --- a/doc/src/arch/consensus.md +++ b/doc/src/arch/consensus.md @@ -1,14 +1,5 @@ # Consensus -To understand how the consensus smart contract works and how anonymous -staking and unstaking is achieved, read the following chapters: - -* [Genesis stake](consensus/genesis_stake.md) -* [Stake](consensus/stake.md) -* [Proposal](consensus/proposal.md) -* [Unstake request](consensus/unstake_request.md) -* [Unstake](consensus/unstake.md) - This section of the book describes how nodes participating in the DarkFi blockchain achieve consensus. diff --git a/doc/src/arch/consensus/genesis_stake.md b/doc/src/arch/consensus/genesis_stake.md deleted file mode 100644 index 888dddc8d..000000000 --- a/doc/src/arch/consensus/genesis_stake.md +++ /dev/null @@ -1,66 +0,0 @@ -Genesis stake -============= - -The `Consensus::GenesisStake` function is used for bootstrapping the -Proof of Stake (PoS) network. Using this, we are able to create an -initial staking coin that participates in consensus and is able to -propose blocks. We can gather any number of these calls/transactions -and hardcode them into a constant genesis block, so anyone is able -to deterministically reproduce the genesis block and begin syncing -the blockchain. - -The parameters to execute this function are a single clear input, -and a single anonymous output: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/consensus/src/model.rs:ConsensusGenesisStakeParams}} -``` - -For transparency, we use a clear input in order to show how many -tokens are initially minted at genesis, and an anonymous output -in order to anonymise the staker. - -The ZK proof we use to prove the minting of the anonymous output -is the `ConsensusMint_V1` circuit: - -``` -{{#include ../../../../src/contract/consensus/proof/consensus_mint_v1.zk}} -``` - -Important to note here is that in the case of genesis, this mint will -have `epoch` set to 0 (zero) in order for these stakers to be able to -immediately propose blocks without a grace period in order to advance -the blockchain. - -## Contract logic - -### [`get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/genesis_stake_v1.rs#L39) - -In the `consensus_genesis_stake_get_metadata_v1` function, we gather -the public key used to verify the transaction signature from the clear -input, and we extract the necessary public inputs that go into the -`ConsensusMint_V1` proof verification. - -### [`process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/genesis_stake_v1.rs#L73) - -In the `consensus_genesis_stake_process_instruction_v1` function, we -perform the state transition. We enforce that: - -* The verifying slot for this function is actually the genesis slot (0) -* The _token ID_ from the clear input is the native network token -* The output coin was not already seen in the set of staked or unstaked coins -* The value commitments in the clear input and anon output match - -If these checks pass, we create a state update with the output coin: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/consensus/src/model.rs:ConsensusGenesisStakeUpdate}} -``` - -### [`process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/stake_v1.rs#L176) - -For the state update, we use the `consensus_stake_process_update_v1` -function. This will simply take the state update produced by -`consensus_genesis_stake_process_instruction_v1` and add the coin to -the set of seen coins in the consensus state, and append it to the -Merkle tree of coins in the consensus Merkle tree of coins. diff --git a/doc/src/arch/consensus/proposal.md b/doc/src/arch/consensus/proposal.md deleted file mode 100644 index 6d65475be..000000000 --- a/doc/src/arch/consensus/proposal.md +++ /dev/null @@ -1,70 +0,0 @@ -Proposal -======== - -The `Consensus::Proposal` function is used whenever a consensus -participant is able to produce a winning proof and wants to prove -they're the current consensus leader and are eligible to propose a -block. By itself, this smart contract has nothing to do with blocks -themself, it is up to the leader to choose which transactions to -include in the block they're proposing. The `Consensus::Proposal` -function simply serves as a way to verify that the block proposer is -indeed an eligible leader. - -The parameters to execute this function are 1 anonymous input and 1 -anonymous output, and other necessary metadata. Essentially we burn -the winning coin, and mint a new one in order to compete in further -slots. Every time a proposer wins the leader election, they have to -burn their competing coin, prove they're the winner, and then mint -a new coin that includes the block reward and is eligible to compete -in upcoming future slots. - - -```rust,no_run,no_playground -{{#include ../../../../src/contract/consensus/src/model.rs:ConsensusProposalParams}} -``` - -The ZK proof we use for this is a single circuit, -`ConsensusProposal_V1`: - -``` -{{#include ../../../../src/contract/consensus/proof/consensus_proposal_v1.zk}} -``` - -## Contract logic - -### [`get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/proposal_v1.rs#L46) - -In the `consensus_proposal_get_metadata_v1` function, we gather -the necessary metadata that we use to verify the ZK proof and the -transaction signature. Inside this function, we also verify the -VRF proof executed by the proposer using a deterministic input and -the proposer's revealed public key. This public key is derived from -the input (burned) coin in ZK and is also used to sign the entire -transaction. - -### [`process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/proposal_v1.rs#L167) - -In the `consensus_proposal_process_instruction_v1` function, we -perform the state transition. We enforce that: - -* The timelock of the burned coin has passed and the coin is eligible to compete -* The Merkle inclusion proof of the burned coin is valid -* The revealed nullifier of the burned coin has not been seen before -* The value commitments match, this is done as `input+reward=output` -* The newly minted coin was not seen before - -If these checks pass, we create a state update with the burned -nullifier and the minted coin: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/consensus/src/model.rs:ConsensusProposalUpdate}} -``` - -### [`process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/proposal_v1.rs#L252) - -For the state update, we use the `consensus_proposal_process_update_v1` -function. This takes the state update produced by -`consensus_proposal_process_instruction_v1` and appends the new -nullifier to the set of seen nullifiers, adds the minted coin to the -set of coins and appends it to the Merkle tree of all coins in the -consensus state. diff --git a/doc/src/arch/consensus/stake.md b/doc/src/arch/consensus/stake.md deleted file mode 100644 index 863628f97..000000000 --- a/doc/src/arch/consensus/stake.md +++ /dev/null @@ -1,119 +0,0 @@ -Stake -===== - -The `Money::Stake` and `Consensus::Stake` functions are used in order -to apply to become eligible for participation in the block proposal -process, commonly known as Consensus. - -The _Stake_ transaction consists of two contract calls, calling the -above mentioned functions. The parameters, respectively, are: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/money/src/model.rs:MoneyStakeParams}} - -{{#include ../../../../src/contract/money/src/model.rs:ConsensusStakeParams}} -``` - -These two contract calls need to happen atomically, meaning they -should be part of a single transaction being executed on the network. -On a high level, what is happening in the _stake_ process is burning -a coin in the state of _Money_ and minting a coin in the state of -_Consensus_ in order to start being able to participate in consensus -and propose blocks. - -The contract calls execute in sequence: - -1. `Money::Stake` -2. `Consensus::Stake` - -The ZK proof we use to prove burning of the coin in _Money_ is the -`Burn_V1` circuit: - -``` -{{#include ../../../../src/contract/money/proof/burn_v1.zk}} -``` - -The ZK proof we use to prove minting of the coin in _Consensus_ is the -`ConsensusMint_V1` circuit: - -``` -{{#include ../../../../src/contract/consensus/proof/consensus_mint_v1.zk}} -``` - -## Contract logic - -### [`Money::get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/money/src/entrypoint/stake_v1.rs#L40) - -In the `money_stake_get_metadata_v1` function, we gather the input -pubkey for signature verification, and extract necessary public inputs -for verifying the money burn ZK proof. - -### [`Money::process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/money/src/entrypoint/stake_v1.rs#L87) - -In the `money_stake_process_instruction_v1` function, we perform the -state transition. We enforce that: - -* The input `spend_hook` is 0 (zero) (for now we don't have protocol-owned stake) -* The input _token ID_ corresponds to the native network token (the commitment blind is revealed in the params) -* The input coin Merkle inclusion proof is valid -* The input nullifier was not published before -* The next `call_idx` is a call to the `Consensus::StakeV1` function -* The input in the params to the next function is the same as the current input - -If these checks pass, we create a state update with the revealed -_nullifier_: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/money/src/model.rs:MoneyStakeUpdate}} -``` - -### [`Money::process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/money/src/entrypoint/stake_v1.rs#L169) - -For the _Money_ state update, we use the -`money_stake_process_update_v1` function. This will simply append -the revealed _nullifier_ to the existing set of nullifiers in order -to prevent double-spending. - -After the `Money::Stake` state transition has passed, we move on to -executing the `Consensus::Stake` state transition. This is supposed -to mint the new coin in the _Consensus_ state. - -### [`Consensus::get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/stake_v1.rs#L41) - -In `consensus_stake_get_metadata_v1` we grab the current epoch of -the slot where we're executing this contract call and use it as one -of the public inputs for the ZK proof of minting the new coin. This -essentially serves as a timelock where we can enforce a grace period -for this staked coin before it is able to start proposing blocks. More -information on this can be found in the [Proposal](proposal.md) page. -Additionally we extract the coin and the value commitment to use as -the proof's public inputs. - -### [`Consensus::process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/stake_v1.rs#L75) - -In `consensus_stake_process_instruction_v1` we perform the state -transition. We enforce that: - -* The previous `call_idx` is a call to `Money::StakeV1` -* The `Input` from the current call is the same as the `Input` from - the previous call (essentially copying it) -* The value commitments in the `Input` and `ConsensusOutput` match -* The `Input` coin's Merkle inclusion proof is valid in the _Money_ state -* The input's _nullifier_ is revealed and exists in the _Money_ state -* The `ConsensusOutput` coin hasn't existed in the _Consensus_ state before -* The `ConsensusOutput` coin hasn't existed in the _Unstaked Consensus_ state before - -If these checks pass we create a state update with the minted coin -that is now considered staked in _Consensus_: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/money/src/model.rs:ConsensusStakeUpdate}} -``` - -### [`Consensus::process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/stake_v1.rs#L176) - -For the state update, we use the `consensus_stake_process_update_v1` -function. This takes the coin from the `ConsensusOutput` and adds -it to the set of staked coins, and appends it to the Merkle tree of -staked coins so participants are able to create inclusion proofs in -the future. diff --git a/doc/src/arch/consensus/unstake.md b/doc/src/arch/consensus/unstake.md deleted file mode 100644 index 554b3ac42..000000000 --- a/doc/src/arch/consensus/unstake.md +++ /dev/null @@ -1,112 +0,0 @@ -Unstake -======= - -The `Consensus::Unstake` and `Money::Unstake` functions are used in -order to fully exit from the consensus participation and move back -the staked funds into the _Money_ state. - -The _Unstake_ transaction consists of two contract calls, calling the -above mentioned functions. The parameters, respectively, are: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/money/src/model.rs:ConsensusUnstakeParams}} - -{{#include ../../../../src/contract/money/src/model.rs:MoneyUnstakeParams}} -``` - -These two contract calls need to happen atomically, meaning they should -be part of a single transaction being executed on the network. On a -high level, what is happening in the _unstake_ process is burning the -coin previously created through [`UnstakeRequest`](unstake_request.md) -in the _Consensus_ state and minting a new coin in the _Money_ state -where it can then again be used for other functionality outside -of consensus. - -The contract calls execute in sequence: - -1. `Consensus::Unstake` -2. `Money::Unstake` - -The ZK proof we use to prove burning of the coin in _Consensus_ is the -`ConsensusBurn_V1` circuit: - -``` -{{#include ../../../../src/contract/consensus/proof/consensus_burn_v1.zk}} -``` - -The ZK proof we use to prove minting of the coin in _Money_ is the -`Mint_V1` circuit: - -``` -{{#include ../../../../src/contract/money/proof/mint_v1.zk}} -``` - -## Contract logic - -### [`Consensus::get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/unstake_v1.rs#L39) - -In the `consensus_unstake_get_metadata_v1` function, we gather the -public inputs necessary to verify the `ConsensusBurn_V1` ZK proof, -and additionally the public key used to verify the transaction -signature. This pubkey is also derived and enforced in ZK. - -### [`Consensus::process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/unstake_v1.rs#L84) - -For the _Consensus_ state transition, we use the -`consensus_unstake_process_instruction_v1` function. We enforce that: - -* The next `call_idx` is a call to the `Money::UnstakeV1` function -* The input in the params to the next function is the same as current input -* The timelock from [`UnstakeRequest`](unstake_request.md) has expired -* The input coin Merkle inclusion proof is valid -* The input nullifier was not published before - -If these checks pass, we create a state update with the revealed -_nullifier_: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/money/src/model.rs:ConsensusUnstakeUpdate}} -``` - -### [`Consensus::process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/unstake_v1.rs#L169) - -For the _Consensus_ state update, we use the -`consensus_unstake_process_update_v1` function. This will simply -append the revealed _nullifier_ to the existing set of nullifiers in -order to prevent double-spending. - -After the `Consensus::Unstake` state transition has passed, we move on -to executing the `Money::Unstake` state transition. This is supposed -to mint the new coin in the _Money_ state. - -### [`Money::get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/money/src/entrypoint/unstake_v1.rs#L41) - -In the `money_unstake_get_metadata_v1` function, we gather the public -inputs necessary to verify the `Mint_V1` ZK proof. It is not necessary -to grab any public keys for signature verification, as they're already -collected in `Consensus::get_metadata()`. - -### [`Money::process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/money/src/entrypoint/unstake_v1.rs#L79) - -In the `money_unstake_process_instruction_v1` function, we perform -the state transition. We enforce that: - -* The previous `call_idx` is a call to the `Consensus::UnstakeV1` function -* The token pedersen commitment is a commitment to the native network token -* The value pedersen commitments in the input and output match -* The input coin Merkle inclusion proof is valid for _Consensus_ -* The input nullifier was published in _Consensus_ -* The output coin was not seen before in the set of coins in _Money_ - -If these checks pass, we create a state update with the revealed -minted coin: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/money/src/model.rs:MoneyUnstakeUpdate}} -``` - -### [`Money::process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/money/src/entrypoint/unstake_v1.rs#L194) - -In `money_unstake_process_update_v1` we simply append the newly minted -coin to the set of seen coins in _Money_, and we add it to the Merkle -tree of coins in _Money_ so further inclusion proofs can be validated. diff --git a/doc/src/arch/consensus/unstake_request.md b/doc/src/arch/consensus/unstake_request.md deleted file mode 100644 index 5a9cecb55..000000000 --- a/doc/src/arch/consensus/unstake_request.md +++ /dev/null @@ -1,74 +0,0 @@ -Unstake request -=============== - -The `Consensus::UnstakeRequest` function is used when a consensus -participant wants to exit participation and plans to unstake their -staked coin. What the user is essentially doing here is burning -their coin they have been using for consensus participation, -and minting a new coin that isn't able to compete anymore, and is -timelocked for a predefined amount of time. This new coin then has to -wait until the timelock is expired, and then it can be used in the -[`Unstake`](unstake.md) function in order to be redeemed back into -the _Money_ state. - -The parameters to execute this function are 1 anonymous input and 1 -anonymous output: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/consensus/src/model.rs:ConsensusUnstakeRequestParams}} -``` - -In this function, we have two ZK proofs, `ConsensusBurn_V1` and -`ConsensusMint_V1`: - -``` -{{#include ../../../../src/contract/consensus/proof/consensus_burn_v1.zk}} -``` - -``` -{{#include ../../../../src/contract/consensus/proof/consensus_mint_v1.zk}} -``` - -## Contract logic - -### [`get_metadata()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/unstake_request_v1.rs#L43) - -In the `consensus_unstake_request_get_metadata_v1` function, we gather -the public inputs necessary to verify the given ZK proofs. It's pretty -straightforward, and more or less the same as other `get_metadata` -functions in this smart contract. - -### [`process_instruction()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/unstake_request_v1.rs#L99) - -We perform the state transition in -`consensus_unstake_request_process_instruction_v1`. We enforce that: - -* The timelock of the burned coin has passed and the coin is eligible for unstaking -* The Merkle inclusion proof of the burned coin is valid -* The revealed nullifier of the burned coin has not been seen before -* The input and output value commitments are the same -* The output/minted coin has not been seen before - -When this is done, and everything passes, we create a state update -with the burned nullifier and the minted coin. Here we use the same -parameters like we do in [`Proposal`](proposal.md) - a nullifier and -a coin: - -```rust,no_run,no_playground -{{#include ../../../../src/contract/consensus/src/model.rs:ConsensusProposalUpdate}} -``` - -### [`process_update()`](https://github.com/darkrenaissance/darkfi/blob/master/src/contract/consensus/src/entrypoint/unstake_request_v1.rs#L174) - -For the state update, we use the -`consensus_unstake_request_process_update_v1` -function. This takes the state update produced by -`consensus_unstake_request_process_instruction_v1`. With it, we -append the revealed nullifier to the set of seen nullifiers. The -minted _coin_, in this case however, does _not_ get added to the -Merkle tree of staked coins. Instead, we add it to the Merkle tree -of **unstaked** coins where it lives in a separate state. By doing -this, we essentially disallow the new coin to compete in consensus -again because in that state it does not exist. It only exists in the -unstaked state, and as such can only be operated with other functions -that actually read from this state - namely [`Unstake`](unstake.md)