Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vm: Add a transaction execution function #3186

Merged
merged 6 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 1 addition & 40 deletions contracts/stake/tests/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use std::sync::mpsc;

use dusk_core::abi::ContractError;
use dusk_core::transfer::data::TransactionData;
use dusk_core::transfer::phoenix::{
Note, NoteLeaf, NoteOpening, NoteTreeItem, PublicKey as PhoenixPublicKey,
Expand All @@ -15,7 +14,7 @@ use dusk_core::transfer::phoenix::{
};
use dusk_core::transfer::{Transaction, TRANSFER_CONTRACT};
use dusk_core::{BlsScalar, LUX};
use dusk_vm::{CallReceipt, Error as VMError, Session};
use dusk_vm::{Error as VMError, Session};
use rand::rngs::StdRng;
use rusk_prover::LocalProver;

Expand Down Expand Up @@ -98,44 +97,6 @@ pub fn filter_notes_owned_by<I: IntoIterator<Item = Note>>(
.collect()
}

/// Executes a transaction, returning the call receipt
pub fn execute(
session: &mut Session,
tx: impl Into<Transaction>,
) -> Result<CallReceipt<Result<Vec<u8>, ContractError>>, VMError> {
let tx = tx.into();

// Spend the inputs and execute the call. If this errors the transaction is
// unspendable.
let mut receipt = session.call::<_, Result<Vec<u8>, ContractError>>(
TRANSFER_CONTRACT,
"spend_and_execute",
&tx,
tx.gas_limit(),
)?;

// Ensure all gas is consumed if there's an error in the contract call
if receipt.data.is_err() {
receipt.gas_spent = receipt.gas_limit;
}

// Refund the appropriate amount to the transaction. This call is guaranteed
// to never error. If it does, then a programming error has occurred. As
// such, the call to `Result::expect` is warranted.
let refund_receipt = session
.call::<_, ()>(
TRANSFER_CONTRACT,
"refund",
&receipt.gas_spent,
u64::MAX,
)
.expect("Refunding must succeed");

receipt.events.extend(refund_receipt.events);

Ok(receipt)
}

/// Generate a TxCircuit given the sender secret-key, receiver public-key, the
/// input note positions in the transaction tree and the new output-notes.
pub fn create_transaction<const I: usize>(
Expand Down
29 changes: 14 additions & 15 deletions contracts/stake/tests/partial_stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use dusk_core::signatures::bls::{
use dusk_core::stake::{Reward, RewardReason, EPOCH, STAKE_CONTRACT};
use dusk_core::transfer::TRANSFER_CONTRACT;
use dusk_vm::{
new_genesis_session, new_session, ContractData, Error as VMError, Session,
VM,
execute, new_genesis_session, new_session, ContractData, Error as VMError,
Session, VM,
};
use rand::rngs::StdRng;
use rand::SeedableRng;
Expand All @@ -21,7 +21,6 @@ use wallet_core::transaction::{
};

pub mod common;

use crate::common::assert::*;
use crate::common::init::CHAIN_ID;
use crate::common::utils::*;
Expand Down Expand Up @@ -63,7 +62,7 @@ fn stake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 1st stake transaction
let gas_spent_1 = receipt.gas_spent;
Expand Down Expand Up @@ -91,7 +90,7 @@ fn stake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 2nd stake transaction
let gas_spent_2 = receipt.gas_spent;
Expand Down Expand Up @@ -125,7 +124,7 @@ fn stake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 3rd stake transaction
let gas_spent_3 = receipt.gas_spent;
Expand Down Expand Up @@ -160,7 +159,7 @@ fn stake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
assert!(execute(&mut session, tx,).is_err());
assert!(execute(&mut session, &tx, 0, 0, 0).is_err());

Ok(())
}
Expand Down Expand Up @@ -194,7 +193,7 @@ fn unstake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;
let mut moonlight_balance = GENESIS_VALUE - STAKE_VALUE - receipt.gas_spent;
assert_moonlight(&mut session, &moonlight_pk, moonlight_balance, nonce);

Expand All @@ -216,7 +215,7 @@ fn unstake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 1st unstake transaction
let gas_spent_1 = receipt.gas_spent;
Expand Down Expand Up @@ -246,7 +245,7 @@ fn unstake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;
total_stake = STAKE_VALUE;
let mut locked = unstake_1 / 10;
assert_stake(&mut session, &stake_pk, total_stake, locked, 0);
Expand All @@ -272,7 +271,7 @@ fn unstake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 2nd unstake transaction
let gas_spent_2 = receipt.gas_spent;
Expand Down Expand Up @@ -310,7 +309,7 @@ fn unstake() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 3rd unstake transaction
let gas_spent_3 = receipt.gas_spent;
Expand Down Expand Up @@ -353,7 +352,7 @@ fn withdraw_reward() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;
let mut moonlight_balance = GENESIS_VALUE - STAKE_VALUE - receipt.gas_spent;
assert_moonlight(&mut session, &moonlight_pk, moonlight_balance, nonce);
// add a reward to the staked key
Expand All @@ -378,7 +377,7 @@ fn withdraw_reward() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 1st reward withdrawal
let gas_spent_1 = receipt.gas_spent;
Expand Down Expand Up @@ -413,7 +412,7 @@ fn withdraw_reward() -> Result<(), VMError> {
CHAIN_ID,
)
.expect("tx creation should pass");
let receipt = execute(&mut session, tx)?;
let receipt = execute(&mut session, &tx, 0, 0, 0)?;

// verify 1st reward withdrawal
let gas_spent_2 = receipt.gas_spent;
Expand Down
17 changes: 8 additions & 9 deletions contracts/stake/tests/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

pub mod common;

use dusk_core::signatures::bls::{
PublicKey as BlsPublicKey, SecretKey as BlsSecretKey,
};
Expand All @@ -21,11 +19,12 @@ use dusk_core::transfer::withdraw::{
Withdraw, WithdrawReceiver, WithdrawReplayToken,
};
use dusk_core::{dusk, JubJubScalar};
use dusk_vm::{new_session, VM};
use dusk_vm::{execute, new_session, VM};
use ff::Field;
use rand::rngs::StdRng;
use rand::SeedableRng;

pub mod common;
use crate::common::assert::{
assert_reward_event, assert_stake, assert_stake_event,
};
Expand Down Expand Up @@ -86,8 +85,8 @@ fn stake_withdraw_unstake() {
contract_call,
);

let receipt =
execute(&mut session, tx).expect("Executing TX should succeed");
let receipt = execute(&mut session, &tx, 0, 0, 0)
.expect("Executing TX should succeed");

let gas_spent = receipt.gas_spent;
receipt.data.expect("Executed TX should not error");
Expand Down Expand Up @@ -181,8 +180,8 @@ fn stake_withdraw_unstake() {
let mut session = new_session(vm, base, CHAIN_ID, 2)
.expect("Instantiating new session should succeed");

let receipt =
execute(&mut session, tx).expect("Executing TX should succeed");
let receipt = execute(&mut session, &tx, 0, 0, 0)
.expect("Executing TX should succeed");

let gas_spent = receipt.gas_spent;
receipt.data.expect("Executed TX should not error");
Expand Down Expand Up @@ -277,8 +276,8 @@ fn stake_withdraw_unstake() {
let mut session = new_session(vm, base, CHAIN_ID, 3)
.expect("Instantiating new session should succeed");

let receipt =
execute(&mut session, tx).expect("Executing TX should succeed");
let receipt = execute(&mut session, &tx, 0, 0, 0)
.expect("Executing TX should succeed");
update_root(&mut session).expect("Updating the root should succeed");

let gas_spent = receipt.gas_spent;
Expand Down
40 changes: 3 additions & 37 deletions contracts/transfer/tests/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

use std::sync::mpsc;

use dusk_core::abi::{ContractError, ContractId};
use dusk_core::abi::ContractId;
use dusk_core::signatures::bls::PublicKey as AccountPublicKey;
use dusk_core::transfer::moonlight::AccountData;
use dusk_core::transfer::phoenix::{Note, NoteLeaf, ViewKey as PhoenixViewKey};
use dusk_core::transfer::{Transaction, TRANSFER_CONTRACT};
use dusk_core::transfer::TRANSFER_CONTRACT;
use dusk_core::BlsScalar;
use dusk_vm::{CallReceipt, Error as VMError, Session};
use dusk_vm::{Error as VMError, Session};

const GAS_LIMIT: u64 = 0x10_000_000;

Expand All @@ -31,40 +31,6 @@ pub fn chain_id(session: &mut Session) -> Result<u8, VMError> {
.map(|r| r.data)
}

/// Executes a transaction.
/// Returns result containing gas spent.
pub fn execute(
session: &mut Session,
tx: impl Into<Transaction>,
) -> Result<CallReceipt<Result<Vec<u8>, ContractError>>, VMError> {
let tx = tx.into();

let mut receipt = session.call::<_, Result<Vec<u8>, ContractError>>(
TRANSFER_CONTRACT,
"spend_and_execute",
&tx,
tx.gas_limit(),
)?;

// Ensure all gas is consumed if there's an error in the contract call
if receipt.data.is_err() {
receipt.gas_spent = receipt.gas_limit;
}

let refund_receipt = session
.call::<_, ()>(
TRANSFER_CONTRACT,
"refund",
&receipt.gas_spent,
u64::MAX,
)
.expect("Refunding must succeed");

receipt.events.extend(refund_receipt.events);

Ok(receipt)
}

// moonlight helper functions

pub fn account(
Expand Down
Loading
Loading