Skip to content

Commit

Permalink
fix nonce and divide api between submit now and later
Browse files Browse the repository at this point in the history
  • Loading branch information
lemunozm committed Oct 13, 2023
1 parent 084d148 commit 380b817
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 83 deletions.
87 changes: 40 additions & 47 deletions runtime/integration-tests/src/generic/cases/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ fn transfer_balance<T: Runtime>() {
);

// Call an extrinsic that would be processed immediately
env.submit(
Keyring::Alice,
pallet_balances::Call::transfer {
dest: Keyring::Bob.into(),
value: TRANSFER,
},
)
.unwrap();
let fee = env
.submit_now(
Keyring::Alice,
pallet_balances::Call::transfer {
dest: Keyring::Bob.into(),
value: TRANSFER,
},
)
.unwrap();

// Check for an even occurred in this block
env.check_event(pallet_balances::Event::Transfer {
Expand All @@ -50,16 +51,20 @@ fn transfer_balance<T: Runtime>() {
})
.unwrap();

// Pass blocks to evolve the system
env.pass(Blocks::ByNumber(1));

// Check the state
env.state(|| {
assert_eq!(
pallet_balances::Pallet::<T>::free_balance(Keyring::Alice.to_account_id()),
T::ExistentialDeposit::get() + FOR_FEES - fee,
);
assert_eq!(
pallet_balances::Pallet::<T>::free_balance(Keyring::Bob.to_account_id()),
TRANSFER
);
});

// Pass blocks to evolve the system
env.pass(Blocks::ByNumber(1));
}

// Identical to `transfer_balance()` test but using fudge.
Expand All @@ -78,7 +83,7 @@ fn fudge_transfer_balance<T: Runtime + FudgeSupport>() {
.storage(),
);

env.submit(
env.submit_later(
Keyring::Alice,
pallet_balances::Call::transfer {
dest: Keyring::Bob.into(),
Expand All @@ -87,23 +92,38 @@ fn fudge_transfer_balance<T: Runtime + FudgeSupport>() {
)
.unwrap();

// submit-later will only take effect if a block has passed
env.pass(Blocks::ByNumber(1));

// Check the state
env.state(|| {
assert_eq!(
pallet_balances::Pallet::<T>::free_balance(Keyring::Bob.to_account_id()),
TRANSFER
);
});

// Check for an even occurred in this block
env.check_event(pallet_balances::Event::Transfer {
from: Keyring::Alice.to_account_id(),
to: Keyring::Bob.to_account_id(),
amount: TRANSFER,
})
.unwrap();

// Look for the fee for the last transaction
let fee = env
.find_event(|e| match e {
pallet_transaction_payment::Event::TransactionFeePaid { actual_fee, .. } => {
Some(actual_fee)
}
_ => None,
})
.unwrap();

// Check the state
env.state(|| {
assert_eq!(
pallet_balances::Pallet::<T>::free_balance(Keyring::Alice.to_account_id()),
T::ExistentialDeposit::get() + FOR_FEES - fee,
);
assert_eq!(
pallet_balances::Pallet::<T>::free_balance(Keyring::Bob.to_account_id()),
TRANSFER
);
});
}

fn call_api<T: Runtime>() {
Expand Down Expand Up @@ -133,34 +153,7 @@ fn fudge_call_api<T: Runtime + FudgeSupport>() {
})
}

fn check_fee<T: Runtime>() {
let mut env = RuntimeEnv::<T>::from_storage(
Genesis::default()
.add(pallet_balances::GenesisConfig::<T> {
balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)],
})
.storage(),
);

env.submit(
Keyring::Alice,
frame_system::Call::remark { remark: vec![] },
)
.unwrap();

// Get the fee of the last submitted extrinsic
let fee = env.last_fee();

env.state(|| {
assert_eq!(
pallet_balances::Pallet::<T>::free_balance(Keyring::Alice.to_account_id()),
1 * CFG - fee
);
});
}

crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance);
crate::test_for_runtimes!(all, call_api);
crate::test_for_runtimes!(all, check_fee);
crate::test_for_runtimes!(all, fudge_transfer_balance);
crate::test_for_runtimes!(all, fudge_call_api);
29 changes: 13 additions & 16 deletions runtime/integration-tests/src/generic/environment.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use cfg_primitives::{Address, Balance, BlockNumber, Moment};
use cfg_primitives::{Address, Balance, BlockNumber, Index, Moment};
use codec::Encode;
use sp_runtime::{
generic::{Era, SignedPayload},
traits::{Block, Extrinsic},
DispatchResult, MultiSignature, Storage,
DispatchError, DispatchResult, MultiSignature, Storage,
};

use crate::{generic::runtime::Runtime, utils::accounts::Keyring};
Expand Down Expand Up @@ -37,10 +37,10 @@ pub trait Env<T: Runtime> {
&self,
who: Keyring,
call: impl Into<T::RuntimeCall>,
nonce: Index,
) -> <T::Block as Block>::Extrinsic {
self.state(|| {
let runtime_call = call.into();
let nonce = frame_system::Pallet::<T>::account(who.to_account_id()).nonce;
let signed_extra = (
frame_system::CheckNonZeroSender::<T>::new(),
frame_system::CheckSpecVersion::<T>::new(),
Expand All @@ -63,8 +63,16 @@ pub trait Env<T: Runtime> {
})
}

/// Submit an extrinsic mutating the state
fn submit(&mut self, who: Keyring, call: impl Into<T::RuntimeCall>) -> DispatchResult;
/// Submit an extrinsic mutating the state instantly and returning the
/// consumed fee
fn submit_now(
&mut self,
who: Keyring,
call: impl Into<T::RuntimeCall>,
) -> Result<Balance, DispatchError>;

/// Submit an extrinsic mutating the state when the block is finalized
fn submit_later(&mut self, who: Keyring, call: impl Into<T::RuntimeCall>) -> DispatchResult;

/// Pass any number of blocks
fn pass(&mut self, blocks: Blocks<T>) {
Expand Down Expand Up @@ -137,16 +145,5 @@ pub trait Env<T: Runtime> {
})
}

/// Retrieve the fees used in the last submit call
fn last_fee(&self) -> Balance {
self.find_event(|e| match e {
pallet_transaction_payment::Event::TransactionFeePaid { actual_fee, .. } => {
Some(actual_fee)
}
_ => None,
})
.expect("Expected transaction")
}

fn __priv_build_block(&mut self, i: BlockNumber);
}
70 changes: 65 additions & 5 deletions runtime/integration-tests/src/generic/envs/fudge_env.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub mod handle;

use cfg_primitives::BlockNumber;
use std::collections::HashMap;

use cfg_primitives::{Balance, BlockNumber, Index};
use fudge::primitives::Chain;
use handle::{FudgeHandle, ParachainClient};
use sc_client_api::HeaderBackend;
Expand All @@ -21,6 +23,7 @@ pub trait FudgeSupport: Runtime {
/// Evironment that uses fudge to interact with the runtime
pub struct FudgeEnv<T: Runtime + FudgeSupport> {
handle: T::FudgeHandle,
nonce_storage: HashMap<Keyring, Index>,
}

impl<T: Runtime + FudgeSupport> Env<T> for FudgeEnv<T> {
Expand All @@ -29,11 +32,25 @@ impl<T: Runtime + FudgeSupport> Env<T> for FudgeEnv<T> {

handle.evolve();

Self { handle }
Self {
handle,
nonce_storage: HashMap::default(),
}
}

fn submit_now(
&mut self,
_who: Keyring,
_call: impl Into<T::RuntimeCall>,
) -> Result<Balance, DispatchError> {
unimplemented!("FudgeEnv does not support submit_now() try submit_later()")
}

fn submit(&mut self, who: Keyring, call: impl Into<T::RuntimeCall>) -> DispatchResult {
let extrinsic = self.create_extrinsic(who, call);
/// Submit an extrinsic mutating the state when the block is finalized
fn submit_later(&mut self, who: Keyring, call: impl Into<T::RuntimeCall>) -> DispatchResult {
let nonce = *self.nonce_storage.entry(who).or_default();

let extrinsic = self.create_extrinsic(who, call, nonce);

self.handle
.parachain_mut()
Expand All @@ -42,7 +59,11 @@ impl<T: Runtime + FudgeSupport> Env<T> for FudgeEnv<T> {
.map_err(|_| {
DispatchError::Other("Specific kind of DispatchError not supported by fudge now")
// More information, issue: https://github.com/centrifuge/fudge/issues/67
})
})?;

self.nonce_storage.insert(who, nonce + 1);

Ok(())
}

fn state_mut<R>(&mut self, f: impl FnOnce() -> R) -> R {
Expand Down Expand Up @@ -88,3 +109,42 @@ impl<T: Runtime + FudgeSupport> FudgeEnv<T> {
exec(api, best_hash);
}
}

mod tests {
use cfg_primitives::CFG;

use super::*;
use crate::generic::{environment::Blocks, utils::genesis::Genesis};

fn correct_nonce_for_submit_later<T: Runtime + FudgeSupport>() {
let mut env = FudgeEnv::<T>::from_storage(
Genesis::default()
.add(pallet_balances::GenesisConfig::<T> {
balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)],
})
.storage(),
);

env.submit_later(
Keyring::Alice,
frame_system::Call::remark { remark: vec![] },
)
.unwrap();

env.submit_later(
Keyring::Alice,
frame_system::Call::remark { remark: vec![] },
)
.unwrap();

env.pass(Blocks::ByNumber(1));

env.submit_later(
Keyring::Alice,
frame_system::Call::remark { remark: vec![] },
)
.unwrap();
}

crate::test_for_runtimes!(all, correct_nonce_for_submit_later);
}
Loading

0 comments on commit 380b817

Please sign in to comment.