Просмотр исходного кода

contract/money: decoupled GenesisMintV1 and PoWRewardV1 from TokenMintV1

aggstam 2 лет назад
Родитель
Сommit
4700e85e4b

+ 19 - 5
src/contract/money/src/entrypoint.rs

@@ -29,8 +29,9 @@ use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
 
 use crate::{
     model::{
-        MoneyStakeUpdateV1, MoneyTokenFreezeUpdateV1, MoneyTokenMintUpdateV1,
-        MoneyTransferUpdateV1, MoneyUnstakeUpdateV1,
+        MoneyGenesisMintUpdateV1, MoneyPoWRewardUpdateV1, MoneyStakeUpdateV1,
+        MoneyTokenFreezeUpdateV1, MoneyTokenMintUpdateV1, MoneyTransferUpdateV1,
+        MoneyUnstakeUpdateV1,
     },
     MoneyFunction, MONEY_CONTRACT_COINS_TREE, MONEY_CONTRACT_COIN_MERKLE_TREE,
     MONEY_CONTRACT_COIN_ROOTS_TREE, MONEY_CONTRACT_DB_VERSION, MONEY_CONTRACT_FAUCET_PUBKEYS,
@@ -55,6 +56,7 @@ use swap_v1::{
 mod genesis_mint_v1;
 use genesis_mint_v1::{
     money_genesis_mint_get_metadata_v1, money_genesis_mint_process_instruction_v1,
+    money_genesis_mint_process_update_v1,
 };
 
 /// `Money::TokenMint` functions
@@ -86,7 +88,10 @@ use unstake_v1::{
 
 /// `Money::PoWReward` functions
 mod pow_reward_v1;
-use pow_reward_v1::{money_pow_reward_get_metadata_v1, money_pow_reward_process_instruction_v1};
+use pow_reward_v1::{
+    money_pow_reward_get_metadata_v1, money_pow_reward_process_instruction_v1,
+    money_pow_reward_process_update_v1,
+};
 
 darkfi_sdk::define_contract!(
     init: init_contract,
@@ -309,8 +314,12 @@ fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult {
             Ok(money_otcswap_process_update_v1(cid, update)?)
         }
 
-        MoneyFunction::GenesisMintV1 | MoneyFunction::TokenMintV1 | MoneyFunction::PoWRewardV1 => {
-            // FIXME: GenesisMint and PoWReward use the same update as `TokenMintV1`
+        MoneyFunction::GenesisMintV1 => {
+            let update: MoneyGenesisMintUpdateV1 = deserialize(&update_data[1..])?;
+            Ok(money_genesis_mint_process_update_v1(cid, update)?)
+        }
+
+        MoneyFunction::TokenMintV1 => {
             let update: MoneyTokenMintUpdateV1 = deserialize(&update_data[1..])?;
             Ok(money_token_mint_process_update_v1(cid, update)?)
         }
@@ -329,5 +338,10 @@ fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult {
             let update: MoneyUnstakeUpdateV1 = deserialize(&update_data[1..])?;
             Ok(money_unstake_process_update_v1(cid, update)?)
         }
+
+        MoneyFunction::PoWRewardV1 => {
+            let update: MoneyPoWRewardUpdateV1 = deserialize(&update_data[1..])?;
+            Ok(money_pow_reward_process_update_v1(cid, update)?)
+        }
     }
 }

+ 40 - 9
src/contract/money/src/entrypoint/genesis_mint_v1.rs

@@ -17,10 +17,13 @@
  */
 
 use darkfi_sdk::{
-    crypto::{pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, DARK_TOKEN_ID},
-    db::{db_contains_key, db_lookup},
-    error::ContractError,
-    msg,
+    crypto::{
+        pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, MerkleNode,
+        DARK_TOKEN_ID,
+    },
+    db::{db_contains_key, db_lookup, db_set},
+    error::{ContractError, ContractResult},
+    merkle_add, msg,
     pasta::pallas,
     util::get_verifying_slot,
     ContractCall,
@@ -29,8 +32,10 @@ use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
 
 use crate::{
     error::MoneyError,
-    model::{MoneyTokenMintParamsV1, MoneyTokenMintUpdateV1},
-    MoneyFunction, MONEY_CONTRACT_COINS_TREE, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
+    model::{MoneyGenesisMintParamsV1, MoneyGenesisMintUpdateV1},
+    MoneyFunction, MONEY_CONTRACT_COINS_TREE, MONEY_CONTRACT_COIN_MERKLE_TREE,
+    MONEY_CONTRACT_COIN_ROOTS_TREE, MONEY_CONTRACT_INFO_TREE, MONEY_CONTRACT_LATEST_COIN_ROOT,
+    MONEY_CONTRACT_ZKAS_MINT_NS_V1,
 };
 
 /// `get_metadata` function for `Money::GenesisMintV1`
@@ -40,7 +45,7 @@ pub(crate) fn money_genesis_mint_get_metadata_v1(
     calls: Vec<ContractCall>,
 ) -> Result<Vec<u8>, ContractError> {
     let self_ = &calls[call_idx as usize];
-    let params: MoneyTokenMintParamsV1 = deserialize(&self_.data[1..])?;
+    let params: MoneyGenesisMintParamsV1 = deserialize(&self_.data[1..])?;
 
     // Public inputs for the ZK proofs we have to verify
     let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
@@ -75,7 +80,7 @@ pub(crate) fn money_genesis_mint_process_instruction_v1(
     calls: Vec<ContractCall>,
 ) -> Result<Vec<u8>, ContractError> {
     let self_ = &calls[call_idx as usize];
-    let params: MoneyTokenMintParamsV1 = deserialize(&self_.data[1..])?;
+    let params: MoneyGenesisMintParamsV1 = deserialize(&self_.data[1..])?;
 
     // Verify this contract call is verified against on genesis slot(0).
     let verifying_slot = get_verifying_slot();
@@ -118,10 +123,36 @@ pub(crate) fn money_genesis_mint_process_instruction_v1(
     }
 
     // Create a state update. We only need the new coin.
-    let update = MoneyTokenMintUpdateV1 { coin: params.output.coin };
+    let update = MoneyGenesisMintUpdateV1 { coin: params.output.coin };
     let mut update_data = vec![];
     update_data.write_u8(MoneyFunction::GenesisMintV1 as u8)?;
     update.encode(&mut update_data)?;
 
     Ok(update_data)
 }
+
+/// `process_update` function for `Money::GenesisMintV1`
+pub(crate) fn money_genesis_mint_process_update_v1(
+    cid: ContractId,
+    update: MoneyGenesisMintUpdateV1,
+) -> ContractResult {
+    // Grab all db handles we want to work on
+    let info_db = db_lookup(cid, MONEY_CONTRACT_INFO_TREE)?;
+    let coins_db = db_lookup(cid, MONEY_CONTRACT_COINS_TREE)?;
+    let coin_roots_db = db_lookup(cid, MONEY_CONTRACT_COIN_ROOTS_TREE)?;
+
+    msg!("[GenesisMintV1] Adding new coin to the set");
+    db_set(coins_db, &serialize(&update.coin), &[])?;
+
+    msg!("[GenesisMintV1] Adding new coin to the Merkle tree");
+    let coins = vec![MerkleNode::from(update.coin.inner())];
+    merkle_add(
+        info_db,
+        coin_roots_db,
+        &serialize(&MONEY_CONTRACT_LATEST_COIN_ROOT),
+        &serialize(&MONEY_CONTRACT_COIN_MERKLE_TREE),
+        &coins,
+    )?;
+
+    Ok(())
+}

+ 40 - 9
src/contract/money/src/entrypoint/pow_reward_v1.rs

@@ -18,10 +18,13 @@
 
 use darkfi_sdk::{
     blockchain::{pow_expected_reward, POW_CUTOFF},
-    crypto::{pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, DARK_TOKEN_ID},
-    db::{db_contains_key, db_lookup},
-    error::ContractError,
-    msg,
+    crypto::{
+        pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, MerkleNode,
+        DARK_TOKEN_ID,
+    },
+    db::{db_contains_key, db_lookup, db_set},
+    error::{ContractError, ContractResult},
+    merkle_add, msg,
     pasta::pallas,
     util::get_verifying_slot,
     ContractCall,
@@ -30,8 +33,10 @@ use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
 
 use crate::{
     error::MoneyError,
-    model::{MoneyTokenMintParamsV1, MoneyTokenMintUpdateV1},
-    MoneyFunction, MONEY_CONTRACT_COINS_TREE, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
+    model::{MoneyPoWRewardParamsV1, MoneyPoWRewardUpdateV1},
+    MoneyFunction, MONEY_CONTRACT_COINS_TREE, MONEY_CONTRACT_COIN_MERKLE_TREE,
+    MONEY_CONTRACT_COIN_ROOTS_TREE, MONEY_CONTRACT_INFO_TREE, MONEY_CONTRACT_LATEST_COIN_ROOT,
+    MONEY_CONTRACT_ZKAS_MINT_NS_V1,
 };
 
 /// `get_metadata` function for `Money::PoWRewardV1`
@@ -41,7 +46,7 @@ pub(crate) fn money_pow_reward_get_metadata_v1(
     calls: Vec<ContractCall>,
 ) -> Result<Vec<u8>, ContractError> {
     let self_ = &calls[call_idx as usize];
-    let params: MoneyTokenMintParamsV1 = deserialize(&self_.data[1..])?;
+    let params: MoneyPoWRewardParamsV1 = deserialize(&self_.data[1..])?;
 
     // Public inputs for the ZK proofs we have to verify
     let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
@@ -76,7 +81,7 @@ pub(crate) fn money_pow_reward_process_instruction_v1(
     calls: Vec<ContractCall>,
 ) -> Result<Vec<u8>, ContractError> {
     let self_ = &calls[call_idx as usize];
-    let params: MoneyTokenMintParamsV1 = deserialize(&self_.data[1..])?;
+    let params: MoneyPoWRewardParamsV1 = deserialize(&self_.data[1..])?;
 
     // Verify this contract call is verified against a slot(block height) before PoS transition,
     // excluding genesis.
@@ -136,10 +141,36 @@ pub(crate) fn money_pow_reward_process_instruction_v1(
     }
 
     // Create a state update. We only need the new coin.
-    let update = MoneyTokenMintUpdateV1 { coin: params.output.coin };
+    let update = MoneyPoWRewardUpdateV1 { coin: params.output.coin };
     let mut update_data = vec![];
     update_data.write_u8(MoneyFunction::PoWRewardV1 as u8)?;
     update.encode(&mut update_data)?;
 
     Ok(update_data)
 }
+
+/// `process_update` function for `Money::PoWRewardV1`
+pub(crate) fn money_pow_reward_process_update_v1(
+    cid: ContractId,
+    update: MoneyPoWRewardUpdateV1,
+) -> ContractResult {
+    // Grab all db handles we want to work on
+    let info_db = db_lookup(cid, MONEY_CONTRACT_INFO_TREE)?;
+    let coins_db = db_lookup(cid, MONEY_CONTRACT_COINS_TREE)?;
+    let coin_roots_db = db_lookup(cid, MONEY_CONTRACT_COIN_ROOTS_TREE)?;
+
+    msg!("[PoWRewardV1] Adding new coin to the set");
+    db_set(coins_db, &serialize(&update.coin), &[])?;
+
+    msg!("[PoWRewardV1] Adding new coin to the Merkle tree");
+    let coins = vec![MerkleNode::from(update.coin.inner())];
+    merkle_add(
+        info_db,
+        coin_roots_db,
+        &serialize(&MONEY_CONTRACT_LATEST_COIN_ROOT),
+        &serialize(&MONEY_CONTRACT_COIN_MERKLE_TREE),
+        &coins,
+    )?;
+
+    Ok(())
+}

+ 32 - 0
src/contract/money/src/model.rs

@@ -158,6 +158,22 @@ pub struct MoneyTransferUpdateV1 {
     pub coins: Vec<Coin>,
 }
 
+/// Parameters for `Money::GenesisMint`
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub struct MoneyGenesisMintParamsV1 {
+    /// Clear input
+    pub input: ClearInput,
+    /// Anonymous output
+    pub output: Output,
+}
+
+/// State update for `Money::GenesisMint`
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub struct MoneyGenesisMintUpdateV1 {
+    /// The newly minted coin
+    pub coin: Coin,
+}
+
 /// Parameters for `Money::TokenMint`
 #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
 pub struct MoneyTokenMintParamsV1 {
@@ -190,6 +206,22 @@ pub struct MoneyTokenFreezeUpdateV1 {
     pub signature_public: PublicKey,
 }
 
+/// Parameters for `Money::PoWReward`
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub struct MoneyPoWRewardParamsV1 {
+    /// Clear input
+    pub input: ClearInput,
+    /// Anonymous output
+    pub output: Output,
+}
+
+/// State update for `Money::PoWReward`
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub struct MoneyPoWRewardUpdateV1 {
+    /// The newly minted coin
+    pub coin: Coin,
+}
+
 /// Parameters for `Money::Stake`
 #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
 // ANCHOR: MoneyStakeParams