Quellcode durchsuchen

validator: Implement contract deployment handling upon tx verification

parazyd vor 2 Jahren
Ursprung
Commit
55f72d0956
4 geänderte Dateien mit 68 neuen und 2 gelöschten Zeilen
  1. 3 1
      src/sdk/src/crypto/mod.rs
  2. 33 0
      src/validator/deploy.rs
  3. 3 0
      src/validator/mod.rs
  4. 29 1
      src/validator/verification.rs

+ 3 - 1
src/sdk/src/crypto/mod.rs

@@ -32,7 +32,9 @@ pub use keypair::{Keypair, PublicKey, SecretKey};
 
 /// Contract ID definitions and methods
 pub mod contract_id;
-pub use contract_id::{ContractId, CONSENSUS_CONTRACT_ID, DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
+pub use contract_id::{
+    ContractId, CONSENSUS_CONTRACT_ID, DAO_CONTRACT_ID, DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID,
+};
 
 /// Token ID definitions and methods
 pub mod token_id;

+ 33 - 0
src/validator/deploy.rs

@@ -0,0 +1,33 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2023 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use darkfi_sdk::crypto::PublicKey;
+use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
+
+/// Parameters for `Deploy::Deploy`
+///
+/// This is copied from `src/contract/deployooor.rs`
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub struct DeployParamsV1 {
+    /// Webassembly bincode of the smart contract
+    pub wasm_bincode: Vec<u8>,
+    /// Public key used to sign the transaction and derive the `ContractId`
+    pub public_key: PublicKey,
+    /// Serialized deployment payload instruction
+    pub ix: Vec<u8>,
+}

+ 3 - 0
src/validator/mod.rs

@@ -63,6 +63,9 @@ pub mod validation;
 pub mod utils;
 use utils::deploy_native_contracts;
 
+/// Contract deployment utilities
+pub mod deploy;
+
 /// Base 10 big float implementation for high precision arithmetics
 pub mod float_10;
 

+ 29 - 1
src/validator/verification.rs

@@ -20,7 +20,10 @@ use std::collections::HashMap;
 
 use darkfi_sdk::{
     blockchain::{block_version, expected_reward},
-    crypto::{schnorr::SchnorrPublic, PublicKey, CONSENSUS_CONTRACT_ID, MONEY_CONTRACT_ID},
+    crypto::{
+        schnorr::SchnorrPublic, ContractId, PublicKey, CONSENSUS_CONTRACT_ID,
+        DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID,
+    },
     dark_tree::dark_forest_leaf_vec_integrity_check,
     pasta::pallas,
 };
@@ -36,6 +39,7 @@ use crate::{
     util::time::TimeKeeper,
     validator::{
         consensus::{Consensus, Fork, Proposal, TXS_CAP},
+        deploy::DeployParamsV1,
         pow::PoWModule,
         validation::validate_block,
     },
@@ -459,6 +463,30 @@ pub async fn verify_transaction(
         runtime.apply(&state_update)?;
         debug!(target: "validator::verification::verify_transaction", "Successfully executed \"apply\" call");
 
+        // If this call is supposed to deploy a new contract, we have to instantiate
+        // a new `Runtime` and run its deploy function.
+        if call.data.contract_id == *DEPLOYOOOR_CONTRACT_ID && call.data.data[0] == 0x00
+        /* DeployV1 */
+        {
+            debug!(target: "validator::verification::verify_transaction", "Deploying new contract");
+            // Deserialize the deployment parameters
+            let deploy_params: DeployParamsV1 = deserialize_async(&call.data.data[1..]).await?;
+            let deploy_cid = ContractId::derive_public(deploy_params.public_key);
+
+            // Instantiate the new deployment runtime
+            let mut deploy_runtime = Runtime::new(
+                &deploy_params.wasm_bincode,
+                overlay.clone(),
+                deploy_cid,
+                time_keeper.clone(),
+            )?;
+
+            deploy_runtime.deploy(&deploy_params.ix)?;
+
+            // Append the used gas
+            gas_used += deploy_runtime.gas_used();
+        }
+
         // At this point we're done with the call and move on to the next one.
         // Accumulate the WASM gas used.
         gas_used += runtime.gas_used();