use casper_execution_engine::core::engine_state::ExecuteRequest;
use casper_types::{account::AccountHash, runtime_args, Key, RuntimeArgs, URef, U512};
use crate::{
DeployItemBuilder, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR,
DEFAULT_PAYMENT, PRODUCTION_RUN_GENESIS_REQUEST,
};
const CONTRACT_CREATE_ACCOUNTS: &str = "create_accounts.wasm";
const CONTRACT_CREATE_PURSES: &str = "create_purses.wasm";
const CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT: &str = "transfer_to_existing_account.wasm";
const CONTRACT_TRANSFER_TO_PURSE: &str = "transfer_to_purse.wasm";
pub const TRANSFER_BATCH_SIZE: u64 = 3;
pub const TARGET_ADDR: AccountHash = AccountHash::new([127; 32]);
const ARG_AMOUNT: &str = "amount";
const ARG_ID: &str = "id";
const ARG_ACCOUNTS: &str = "accounts";
const ARG_SEED_AMOUNT: &str = "seed_amount";
const ARG_TOTAL_PURSES: &str = "total_purses";
const ARG_TARGET: &str = "target";
const ARG_TARGET_PURSE: &str = "target_purse";
pub const BLOCK_TRANSFER_COUNT: usize = 2500;
fn make_deploy_hash(i: u64) -> [u8; 32] {
let mut result = [128; 32];
result[32 - 8..].copy_from_slice(&i.to_be_bytes());
result
}
pub fn create_initial_accounts_and_run_genesis(
builder: &mut LmdbWasmTestBuilder,
accounts: Vec<AccountHash>,
amount: U512,
) {
let exec_request = create_accounts_request(accounts, amount);
builder
.run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST)
.exec(exec_request)
.expect_success()
.commit();
}
pub fn create_accounts_request(source_accounts: Vec<AccountHash>, amount: U512) -> ExecuteRequest {
ExecuteRequestBuilder::standard(
*DEFAULT_ACCOUNT_ADDR,
CONTRACT_CREATE_ACCOUNTS,
runtime_args! { ARG_ACCOUNTS => source_accounts, ARG_SEED_AMOUNT => amount },
)
.build()
}
pub fn create_test_purses(
builder: &mut LmdbWasmTestBuilder,
source: AccountHash,
total_purses: u64,
purse_amount: U512,
) -> Vec<URef> {
let exec_request = ExecuteRequestBuilder::standard(
source,
CONTRACT_CREATE_PURSES,
runtime_args! {
ARG_AMOUNT => U512::from(total_purses) * purse_amount,
ARG_TOTAL_PURSES => total_purses,
ARG_SEED_AMOUNT => purse_amount
},
)
.build();
builder.exec(exec_request).expect_success().commit();
let query_result = builder
.query(None, Key::Account(source), &[])
.expect("should query target");
let account = query_result
.as_account()
.unwrap_or_else(|| panic!("result should be account but received {:?}", query_result));
(0..total_purses)
.map(|index| {
let purse_lookup_key = format!("purse:{}", index);
let purse_uref = account
.named_keys()
.get(&purse_lookup_key)
.and_then(Key::as_uref)
.unwrap_or_else(|| panic!("should get named key {} as uref", purse_lookup_key));
*purse_uref
})
.collect()
}
pub fn transfer_to_account_multiple_execs(
builder: &mut LmdbWasmTestBuilder,
account: AccountHash,
should_commit: bool,
) {
let amount = U512::one();
for _ in 0..TRANSFER_BATCH_SIZE {
let exec_request = ExecuteRequestBuilder::standard(
*DEFAULT_ACCOUNT_ADDR,
CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT,
runtime_args! {
ARG_TARGET => account,
ARG_AMOUNT => amount,
},
)
.build();
let builder = builder.exec(exec_request).expect_success();
if should_commit {
builder.commit();
}
}
}
pub fn transfer_to_account_multiple_deploys(
builder: &mut LmdbWasmTestBuilder,
account: AccountHash,
should_commit: bool,
) {
let mut exec_builder = ExecuteRequestBuilder::new();
for i in 0..TRANSFER_BATCH_SIZE {
let deploy = DeployItemBuilder::default()
.with_address(*DEFAULT_ACCOUNT_ADDR)
.with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT })
.with_session_code(
CONTRACT_TRANSFER_TO_EXISTING_ACCOUNT,
runtime_args! {
ARG_TARGET => account,
ARG_AMOUNT => U512::one(),
},
)
.with_authorization_keys(&[*DEFAULT_ACCOUNT_ADDR])
.with_deploy_hash(make_deploy_hash(i)) .build();
exec_builder = exec_builder.push_deploy(deploy);
}
let exec_request = exec_builder.build();
let builder = builder.exec(exec_request).expect_success();
if should_commit {
builder.commit();
}
}
pub fn transfer_to_purse_multiple_execs(
builder: &mut LmdbWasmTestBuilder,
purse: URef,
should_commit: bool,
) {
let amount = U512::one();
for _ in 0..TRANSFER_BATCH_SIZE {
let exec_request = ExecuteRequestBuilder::standard(
TARGET_ADDR,
CONTRACT_TRANSFER_TO_PURSE,
runtime_args! { ARG_TARGET_PURSE => purse, ARG_AMOUNT => amount },
)
.build();
let builder = builder.exec(exec_request).expect_success();
if should_commit {
builder.commit();
}
}
}
pub fn transfer_to_purse_multiple_deploys(
builder: &mut LmdbWasmTestBuilder,
purse: URef,
should_commit: bool,
) {
let mut exec_builder = ExecuteRequestBuilder::new();
for i in 0..TRANSFER_BATCH_SIZE {
let deploy = DeployItemBuilder::default()
.with_address(TARGET_ADDR)
.with_empty_payment_bytes(runtime_args! { ARG_AMOUNT => *DEFAULT_PAYMENT, })
.with_session_code(
CONTRACT_TRANSFER_TO_PURSE,
runtime_args! { ARG_TARGET_PURSE => purse, ARG_AMOUNT => U512::one() },
)
.with_authorization_keys(&[TARGET_ADDR])
.with_deploy_hash(make_deploy_hash(i)) .build();
exec_builder = exec_builder.push_deploy(deploy);
}
let exec_request = exec_builder.build();
let builder = builder.exec(exec_request).expect_success();
if should_commit {
builder.commit();
}
}
pub fn transfer_to_account_multiple_native_transfers(
builder: &mut LmdbWasmTestBuilder,
execute_requests: &[ExecuteRequest],
use_scratch: bool,
) {
for exec_request in execute_requests {
let request = ExecuteRequest::new(
exec_request.parent_state_hash,
exec_request.block_time,
exec_request.deploys.clone(),
exec_request.protocol_version,
exec_request.proposer.clone(),
);
if use_scratch {
builder.scratch_exec_and_commit(request).expect_success();
} else {
builder.exec(request).expect_success();
builder.commit();
}
}
if use_scratch {
builder.write_scratch_to_db();
}
builder.flush_environment();
builder.clear_results();
}
pub fn create_multiple_native_transfers_to_purses(
source_account: AccountHash,
transfer_count: usize,
purses: &[URef],
) -> Vec<ExecuteRequest> {
let mut purse_index = 0usize;
let mut exec_requests = Vec::with_capacity(transfer_count);
for _ in 0..transfer_count {
let account = {
let account = purses[purse_index];
if purse_index == purses.len() - 1 {
purse_index = 0;
} else {
purse_index += 1;
}
account
};
let mut exec_builder = ExecuteRequestBuilder::new();
let runtime_args = runtime_args! {
ARG_TARGET => account,
ARG_AMOUNT => U512::one(),
ARG_ID => <Option<u64>>::None
};
let native_transfer = DeployItemBuilder::new()
.with_address(source_account)
.with_empty_payment_bytes(runtime_args! {})
.with_transfer_args(runtime_args)
.with_authorization_keys(&[source_account])
.build();
exec_builder = exec_builder.push_deploy(native_transfer);
let exec_request = exec_builder.build();
exec_requests.push(exec_request);
}
exec_requests
}