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

Remove fixed fee #1125

Merged
merged 3 commits into from
Dec 5, 2023
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
18 changes: 14 additions & 4 deletions contracts/stake/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,31 @@ static mut STATE: StakeState = StakeState::new();
#[no_mangle]
unsafe fn stake(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |arg| {
assert_external_caller();
assert_transfer_caller();
STATE.stake(arg)
})
}

#[no_mangle]
unsafe fn unstake(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |arg| {
assert_external_caller();
assert_transfer_caller();
STATE.unstake(arg)
})
}

#[no_mangle]
unsafe fn withdraw(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |arg| {
assert_external_caller();
assert_transfer_caller();
STATE.withdraw(arg)
})
}

#[no_mangle]
unsafe fn allow(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |arg| {
assert_external_caller();
assert_transfer_caller();
STATE.allow(arg)
})
}
Expand Down Expand Up @@ -125,6 +125,16 @@ unsafe fn add_owner(arg_len: u32) -> u32 {
})
}

/// Asserts the call is made via the transfer contract.
///
/// # Panics
/// When the `caller` is not [`rusk_abi::TRANSFER_CONTRACT`].
fn assert_transfer_caller() {
if rusk_abi::caller() != rusk_abi::TRANSFER_CONTRACT {
panic!("Can only be called from the transfer contract");
}
}

/// Asserts the call is made "from the outside", meaning that it's not an
/// inter-contract call.
///
Expand Down
30 changes: 9 additions & 21 deletions contracts/stake/tests/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use poseidon_merkle::Opening as PoseidonOpening;
use rand::rngs::StdRng;
use rand::{CryptoRng, RngCore, SeedableRng};
use rusk_abi::dusk::{dusk, LUX};
use rusk_abi::{ContractData, Error, Session, VM};
use rusk_abi::{ContractId, STAKE_CONTRACT, TRANSFER_CONTRACT};
use rusk_abi::{ContractData, ContractError, Error, RawResult, Session, VM};
use rusk_abi::{STAKE_CONTRACT, TRANSFER_CONTRACT};
use transfer_circuits::{
CircuitInput, CircuitInputSignature, ExecuteCircuitOneTwo,
ExecuteCircuitThreeTwo, ExecuteCircuitTwoTwo,
Expand All @@ -29,7 +29,6 @@ use transfer_circuits::{

const GENESIS_VALUE: u64 = dusk(1_000_000.0);
const POINT_LIMIT: u64 = 0x100000000;
const GAS_PER_TX: u64 = 10_000;

type Result<T, E = Error> = core::result::Result<T, E>;

Expand Down Expand Up @@ -165,25 +164,14 @@ fn filter_notes_owned_by<I: IntoIterator<Item = Note>>(

/// Executes a transaction, returning the gas spent.
fn execute(session: &mut Session, tx: Transaction) -> Result<u64> {
session.call::<_, ()>(TRANSFER_CONTRACT, "spend", &tx, u64::MAX)?;

let mut gas_spent = GAS_PER_TX;
if let Some((contract_id, fn_name, fn_data)) = &tx.call {
let gas_limit = tx.fee.gas_limit - GAS_PER_TX;

let contract_id = ContractId::from_bytes(*contract_id);
println!("Calling '{fn_name}' of {contract_id} with {gas_limit} gas");

let r = session.call_raw(
contract_id,
fn_name,
fn_data.clone(),
gas_limit,
)?;
println!("{r:?}");
let receipt = session.call::<_, Result<RawResult, ContractError>>(
TRANSFER_CONTRACT,
"spend_and_execute",
&tx,
tx.fee.gas_limit,
)?;

gas_spent += r.points_spent;
}
let gas_spent = receipt.points_spent;

session
.call::<_, ()>(
Expand Down
4 changes: 2 additions & 2 deletions contracts/transfer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ unsafe fn leaves_from_pos(arg_len: u32) -> u32 {
// "Management" transactions

#[no_mangle]
unsafe fn spend(arg_len: u32) -> u32 {
unsafe fn spend_and_execute(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |tx| {
assert_external_caller();
STATE.spend(tx)
STATE.spend_and_execute(tx)
})
}

Expand Down
36 changes: 28 additions & 8 deletions contracts/transfer/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ use dusk_pki::{Ownable, PublicKey, StealthAddress};
use phoenix_core::transaction::*;
use phoenix_core::{Crossover, Fee, Message, Note};
use poseidon_merkle::Opening as PoseidonOpening;
use rusk_abi::{ContractId, PaymentInfo, PublicInput, STAKE_CONTRACT};
use rusk_abi::{
ContractError, ContractId, PaymentInfo, PublicInput, RawCall, RawResult,
STAKE_CONTRACT,
};

/// Arity of the transfer tree.
pub const A: usize = 4;
Expand Down Expand Up @@ -269,21 +272,27 @@ impl TransferState {
true
}

/// Spend the inputs and process the outputs, together with the crossover.
/// It performs all checks necessary to ensure the transaction is valid -
/// hash matches, anchor has been a root of the tree, proof checks out,
/// etc...
/// Spends the inputs and creates the given UTXO, and executes the contract
/// call if present. It performs all checks necessary to ensure the
/// transaction is valid - hash matches, anchor has been a root of the
/// tree, proof checks out, etc...
///
/// This will emplace the crossover in the state, if it exists, and expect
/// [`refund`] to be called if it succeeds.
/// This will emplace the crossover in the state, if it exists - making it
/// available for any contracts called.
///
/// [`refund`] **must** be called if this function succeeds, otherwise we
/// will have an inconsistent state.
///
/// # Panics
/// Any failure in the checks performed in processing the transaction will
/// result in a panic. The contract expects the environment to roll back any
/// change in state.
///
/// [`refund`]: [`TransferState::refund`]
pub fn spend(&mut self, tx: Transaction) {
pub fn spend_and_execute(
&mut self,
tx: Transaction,
) -> Result<RawResult, ContractError> {
// 1. α ∈ R
if !self.root_exists(&tx.anchor) {
panic!("Anchor not found in the state!");
Expand Down Expand Up @@ -316,6 +325,17 @@ impl TransferState {
// 11. if ∣k∣≠0 then call(k)
self.var_crossover = tx.crossover;
self.var_crossover_addr.replace(*tx.fee.stealth_address());

let mut result = Ok(RawResult::new(&[]));

if let Some((contract_id, fn_name, fn_args)) = tx.call {
result = rusk_abi::call_raw(
ContractId::from_bytes(contract_id),
&RawCall::from_parts(&fn_name, fn_args),
);
}

result
}

/// Refund the previously performed transaction, taking into account the
Expand Down
31 changes: 11 additions & 20 deletions contracts/transfer/tests/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ use poseidon_merkle::Opening as PoseidonOpening;
use rand::rngs::StdRng;
use rand::{CryptoRng, RngCore, SeedableRng};
use rusk_abi::dusk::{dusk, LUX};
use rusk_abi::{ContractData, Error, Session, VM};
use rusk_abi::{ContractId, TRANSFER_CONTRACT};
use rusk_abi::{
ContractData, ContractError, ContractId, Error, RawResult, Session,
TRANSFER_CONTRACT, VM,
};
use transfer_circuits::{
CircuitInput, CircuitInputSignature, DeriveKey, ExecuteCircuitOneTwo,
ExecuteCircuitTwoTwo, SendToContractObfuscatedCircuit,
Expand All @@ -29,7 +31,6 @@ use transfer_circuits::{

const GENESIS_VALUE: u64 = dusk(1_000.0);
const POINT_LIMIT: u64 = 0x10000000;
const GAS_PER_TX: u64 = 10_000;

const ALICE_ID: ContractId = {
let mut bytes = [0u8; 32];
Expand Down Expand Up @@ -210,24 +211,14 @@ fn filter_notes_owned_by<I: IntoIterator<Item = Note>>(

/// Executes a transaction, returning the gas spent.
fn execute(session: &mut Session, tx: Transaction) -> Result<u64> {
session.call::<_, ()>(TRANSFER_CONTRACT, "spend", &tx, u64::MAX)?;

let mut gas_spent = GAS_PER_TX;
if let Some((contract_id, fn_name, fn_data)) = &tx.call {
let gas_limit = tx.fee.gas_limit - GAS_PER_TX;

let contract_id = ContractId::from_bytes(*contract_id);
println!("Calling '{fn_name}' of {contract_id} with {gas_limit} gas");

let r = session.call_raw(
contract_id,
fn_name,
fn_data.clone(),
gas_limit,
)?;
let receipt = session.call::<_, Result<RawResult, ContractError>>(
TRANSFER_CONTRACT,
"spend_and_execute",
&tx,
u64::MAX,
)?;

gas_spent += r.points_spent;
}
let gas_spent = receipt.points_spent;

session
.call::<_, ()>(
Expand Down
Loading