Selaa lähdekoodia

runtime: remove call_idx from the payload, and add it as a Runtime param

zero 2 vuotta sitten
vanhempi
sitoutus
9074440105

+ 5 - 3
src/contract/dao/src/entrypoint/mod.rs

@@ -23,7 +23,7 @@ use darkfi_sdk::{
     dark_tree::DarkLeaf,
     db::{db_get, db_init, db_lookup, db_set, zkas_db_set},
     error::ContractResult,
-    util::set_return_data,
+    util::{get_call_index, set_return_data},
     ContractCall,
 };
 use darkfi_serial::{deserialize, serialize, Decodable, Encodable, WriteExt};
@@ -141,7 +141,8 @@ fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
 /// for verifying signatures and ZK proofs. The payload given here are all the
 /// contract calls in the transaction.
 fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
-    let (call_idx, calls): (u32, Vec<DarkLeaf<ContractCall>>) = deserialize(ix)?;
+    let call_idx = get_call_index();
+    let calls: Vec<DarkLeaf<ContractCall>> = deserialize(ix)?;
     let self_ = &calls[call_idx as usize].data;
     let func = DaoFunction::try_from(self_.data[0])?;
 
@@ -159,7 +160,8 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
 /// This function verifies a state transition and produces a state update
 /// if everything is successful.
 fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
-    let (call_idx, calls): (u32, Vec<DarkLeaf<ContractCall>>) = deserialize(ix)?;
+    let call_idx = get_call_index();
+    let calls: Vec<DarkLeaf<ContractCall>> = deserialize(ix)?;
     let self_ = &calls[call_idx as usize].data;
     let func = DaoFunction::try_from(self_.data[0])?;
 

+ 6 - 3
src/contract/money/src/entrypoint.rs

@@ -21,8 +21,9 @@ use darkfi_sdk::{
     dark_tree::DarkLeaf,
     db::{db_init, db_lookup, db_set, zkas_db_set},
     error::ContractResult,
+    msg,
     pasta::pallas,
-    util::set_return_data,
+    util::{get_call_index, set_return_data},
     ContractCall,
 };
 use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
@@ -206,7 +207,8 @@ fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
 /// for verifying signatures and zk proofs. The payload given here are all the
 /// contract calls in the transaction.
 fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
-    let (call_idx, calls): (u32, Vec<DarkLeaf<ContractCall>>) = deserialize(ix)?;
+    let call_idx = get_call_index();
+    let calls: Vec<DarkLeaf<ContractCall>> = deserialize(ix)?;
     let self_ = &calls[call_idx as usize].data;
     let func = MoneyFunction::try_from(self_.data[0])?;
 
@@ -236,7 +238,8 @@ fn get_metadata(cid: ContractId, ix: &[u8]) -> ContractResult {
 /// if everything is successful. This step should happen **after** the host
 /// has successfully verified the metadata from `get_metadata()`.
 fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
-    let (call_idx, calls): (u32, Vec<DarkLeaf<ContractCall>>) = deserialize(ix)?;
+    let call_idx = get_call_index();
+    let calls: Vec<DarkLeaf<ContractCall>> = deserialize(ix)?;
     let self_ = &calls[call_idx as usize].data;
     let func = MoneyFunction::try_from(self_.data[0])?;
 

+ 5 - 3
src/contract/test-harness/src/lib.rs

@@ -41,7 +41,7 @@ use darkfi_sdk::{
     },
     pasta::pallas,
 };
-use darkfi_serial::{Encodable, WriteExt};
+use darkfi_serial::Encodable;
 use log::debug;
 use num_bigint::BigUint;
 
@@ -305,11 +305,13 @@ fn benchmark_wasm_calls(
             call.data.contract_id,
             block_height,
             tx.hash().clone(),
+            idx as u32,
         )
         .expect("runtime");
+
+        // Write call data
         let mut payload = vec![];
-        payload.write_u32(idx as u32).unwrap(); // Call index
-        tx.calls.encode(&mut payload).unwrap(); // Actual call data
+        tx.calls.encode(&mut payload).unwrap();
 
         let mut times = [0; 3];
         let now = std::time::Instant::now();

+ 11 - 0
src/runtime/import/util.rs

@@ -254,6 +254,17 @@ pub(crate) fn get_tx_hash(mut ctx: FunctionEnvMut<Env>) -> i64 {
     (objects.len() - 1) as i64
 }
 
+/// Will return current runtime configured verifying block height number
+pub(crate) fn get_call_index(mut ctx: FunctionEnvMut<Env>) -> u32 {
+    let (env, mut store) = ctx.data_and_store_mut();
+
+    // Subtract used gas. Here we count the size of the object.
+    // u32 is 4 bytes.
+    env.subtract_gas(&mut store, 4);
+
+    env.call_idx
+}
+
 /// Will return current blockchain timestamp,
 /// defined as the last block's timestamp.
 pub(crate) fn get_blockchain_time(mut ctx: FunctionEnvMut<Env>) -> i64 {

+ 10 - 0
src/runtime/vm_runtime.rs

@@ -99,6 +99,8 @@ pub struct Env {
     pub verifying_block_height: u64,
     /// The hash for this transaction the runtime is being run against.
     pub tx_hash: TransactionHash,
+    /// The index for this call in the transaction
+    pub call_idx: u32,
     /// Parent `Instance`
     pub instance: Option<Arc<Instance>>,
 }
@@ -155,6 +157,7 @@ impl Runtime {
         contract_id: ContractId,
         verifying_block_height: u64,
         tx_hash: TransactionHash,
+        call_idx: u32,
     ) -> Result<Self> {
         info!(target: "runtime::vm_runtime", "[WASM] Instantiating a new runtime");
         // This function will be called for each `Operator` encountered during
@@ -197,6 +200,7 @@ impl Runtime {
                 objects: RefCell::new(vec![]),
                 verifying_block_height,
                 tx_hash,
+                call_idx,
                 instance: None,
             },
         );
@@ -299,6 +303,12 @@ impl Runtime {
                     import::util::get_tx_hash,
                 ),
 
+                "get_call_index_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::util::get_call_index,
+                ),
+
                 "get_blockchain_time_" => Function::new_typed_with_env(
                     &mut store,
                     &ctx,

+ 11 - 0
src/sdk/src/util.rs

@@ -113,6 +113,16 @@ pub fn get_tx_hash() -> GenericResult<TransactionHash> {
     Ok(TransactionHash(tx_hash_data))
 }
 
+/// Only deploy(), metadata() and exec() can call this. Will return runtime configured
+/// verifying block height.
+///
+/// ```
+/// call_idx = get_call_index();
+/// ```
+pub fn get_call_index() -> u32 {
+    unsafe { get_call_index_() }
+}
+
 /// Everyone can call this. Will return current blockchain timestamp.
 ///
 /// ```
@@ -156,6 +166,7 @@ extern "C" {
 
     fn get_verifying_block_height_() -> u64;
     fn get_tx_hash_() -> i64;
+    fn get_call_index_() -> u32;
     fn get_blockchain_time_() -> i64;
     fn get_last_block_height_() -> i64;
     fn get_tx_(ptr: *const u8) -> i64;

+ 2 - 1
src/validator/utils.rs

@@ -81,7 +81,7 @@ pub async fn deploy_native_contracts(overlay: &BlockchainOverlayPtr) -> Result<(
         Err(_) => 0,
     };
 
-    for nc in native_contracts {
+    for (call_idx, nc) in native_contracts.into_iter().enumerate() {
         info!(target: "validator::utils::deploy_native_contracts", "Deploying {} with ContractID {}", nc.0, nc.1);
 
         let mut runtime = Runtime::new(
@@ -90,6 +90,7 @@ pub async fn deploy_native_contracts(overlay: &BlockchainOverlayPtr) -> Result<(
             nc.1,
             verifying_block_height,
             TransactionHash::none(),
+            call_idx as u32,
         )?;
 
         runtime.deploy(&nc.3)?;

+ 6 - 6
src/validator/verification.rs

@@ -28,9 +28,7 @@ use darkfi_sdk::{
     deploy::DeployParamsV1,
     pasta::pallas,
 };
-use darkfi_serial::{
-    deserialize_async, serialize_async, AsyncDecodable, AsyncEncodable, AsyncWriteExt, WriteExt,
-};
+use darkfi_serial::{deserialize_async, serialize_async, AsyncDecodable, AsyncEncodable};
 use log::{debug, error, warn};
 use num_bigint::BigUint;
 use smol::io::Cursor;
@@ -276,7 +274,6 @@ pub async fn verify_producer_transaction(
 
     // Write the actual payload data
     let mut payload = vec![];
-    payload.write_u32_async(0).await?; // Call index
     tx.calls.encode_async(&mut payload).await?; // Actual call data
 
     debug!(target: "validator::verification::verify_producer_transaction", "Instantiating WASM runtime");
@@ -288,6 +285,8 @@ pub async fn verify_producer_transaction(
         call.data.contract_id,
         verifying_block_height,
         tx_hash.clone(),
+        // Call index in producer tx is 0
+        0,
     )?;
 
     debug!(target: "validator::verification::verify_producer_transaction", "Executing \"metadata\" call");
@@ -443,8 +442,7 @@ pub async fn verify_transaction(
 
         // Write the actual payload data
         let mut payload = vec![];
-        payload.write_u32(idx as u32)?; // Call index
-        tx.calls.encode_async(&mut payload).await?; // Actual call data
+        tx.calls.encode_async(&mut payload).await?;
 
         debug!(target: "validator::verification::verify_transaction", "Instantiating WASM runtime");
         let wasm = overlay.lock().unwrap().contracts.get(call.data.contract_id)?;
@@ -455,6 +453,7 @@ pub async fn verify_transaction(
             call.data.contract_id,
             verifying_block_height,
             tx_hash.clone(),
+            idx as u32,
         )?;
 
         debug!(target: "validator::verification::verify_transaction", "Executing \"metadata\" call");
@@ -529,6 +528,7 @@ pub async fn verify_transaction(
                 deploy_cid,
                 verifying_block_height,
                 tx_hash.clone(),
+                idx as u32,
             )?;
 
             deploy_runtime.deploy(&deploy_params.ix)?;