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

This commit is contained in:
zero
2024-04-01 17:46:27 +02:00
parent 69cf9c3a1a
commit 9074440105
8 changed files with 56 additions and 16 deletions

View File

@@ -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])?;

View File

@@ -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])?;

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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;

View File

@@ -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)?;

View File

@@ -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)?;