Skip to content

Commit

Permalink
Merge branch 'feat-2.0' into make_prepayment_naming_consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
Maciej Wójcik committed Dec 9, 2024
2 parents 1a9deaa + 9ac4510 commit e218f0a
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 65 deletions.
9 changes: 5 additions & 4 deletions execution_engine/src/runtime/auction_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,16 +394,17 @@ where
amount: U512,
id: Option<u64>,
) -> Result<Result<(), mint::Error>, Error> {
if !(self
let is_main_purse_transfer = self
.context
.runtime_footprint()
.borrow()
.main_purse()
.expect("didnt have purse")
.addr()
== source.addr()
|| self.context.get_initiator() == PublicKey::System.to_account_hash())
{
== source.addr();
let has_perms = is_main_purse_transfer
|| (source.is_writeable() && self.context.validate_uref(&source).is_ok());
if !(has_perms || self.context.get_initiator() == PublicKey::System.to_account_hash()) {
return Err(Error::InvalidCaller);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,157 @@ fn should_support_contract_staking() {
"unbonded amount should be available to contract staking purse"
);
}

#[ignore]
#[test]
fn should_not_enforce_max_spending_when_main_purse_not_in_use() {
const ARG_ACTION: &str = "action";
let timestamp_millis = DEFAULT_GENESIS_TIMESTAMP_MILLIS;
let purse_name = "staking_purse".to_string();
let contract_name = "staking".to_string();
let entry_point_name = "run".to_string();
let stake_all = "STAKE_ALL".to_string();
let account = *DEFAULT_ACCOUNT_ADDR;
let seed_amount = U512::from(10_000_000_000_000_000_u64);
let validator_pk = &*DEFAULT_PROPOSER_PUBLIC_KEY;
let other_validator_pk = {
let secret_key = SecretKey::ed25519_from_bytes([199; SecretKey::ED25519_LENGTH]).unwrap();
PublicKey::from(&secret_key)
};

let mut builder = LmdbWasmTestBuilder::default();
let mut genesis_request = LOCAL_GENESIS_REQUEST.clone();
genesis_request.set_enable_entity(false);

genesis_request.push_genesis_validator(
validator_pk,
GenesisValidator::new(
Motes::new(10_000_000_000_000_000_u64),
DelegationRate::zero(),
),
);
genesis_request.push_genesis_account(GenesisAccount::Account {
public_key: other_validator_pk.clone(),
validator: Some(GenesisValidator::new(
Motes::new(1_000_000_000_000_000_u64),
DelegationRate::zero(),
)),
balance: Motes::new(10_000_000_000_000_000_u64),
});
builder.run_genesis(genesis_request);

let auction_delay = builder.get_unbonding_delay();

for _ in 0..=auction_delay {
// crank era
builder.run_auction(timestamp_millis, vec![]);
}

let account_main_purse = builder
.get_entity_with_named_keys_by_account_hash(account)
.expect("should have account")
.main_purse();
let starting_account_balance = builder.get_purse_balance(account_main_purse);

builder
.exec(
ExecuteRequestBuilder::standard(
account,
STORED_STAKING_CONTRACT_NAME,
runtime_args! {
ARG_AMOUNT => seed_amount
},
)
.build(),
)
.commit()
.expect_success();

let default_account = builder.get_account(account).expect("should have account");
let named_keys = default_account.named_keys();

let contract_key = named_keys
.get(&contract_name)
.expect("contract_name key should exist");

let stored_contract = builder
.query(None, *contract_key, &[])
.expect("should have stored value at contract key");

let contract = stored_contract
.as_contract()
.expect("stored value should be contract");

let contract_named_keys = contract.named_keys();

let contract_purse = contract_named_keys
.get(&purse_name)
.expect("purse_name key should exist")
.into_uref()
.expect("should be a uref");

let post_install_account_balance = builder.get_purse_balance(account_main_purse);
assert_eq!(
post_install_account_balance,
starting_account_balance.saturating_sub(seed_amount),
"post install should be reduced due to seeding contract purse"
);

let pre_delegation_balance = builder.get_purse_balance(contract_purse);
assert_eq!(pre_delegation_balance, seed_amount);

// stake from contract
builder
.exec(
ExecuteRequestBuilder::contract_call_by_name(
account,
&contract_name,
&entry_point_name,
runtime_args! {
ARG_ACTION => stake_all,
ARG_VALIDATOR => validator_pk.clone(),
},
)
.build(),
)
.commit()
.expect_success();

let post_delegation_balance = builder.get_purse_balance(contract_purse);
assert_eq!(
post_delegation_balance,
U512::zero(),
"contract purse balance should be reduced by staked amount"
);

let delegation_key = Key::BidAddr(BidAddr::DelegatedPurse {
validator: validator_pk.to_account_hash(),
delegator: contract_purse.addr(),
});

let stored_value = builder
.query(None, delegation_key, &[])
.expect("should have delegation bid");

assert!(
matches!(stored_value, StoredValue::BidKind(BidKind::Delegator(_))),
"expected delegator bid"
);

if let StoredValue::BidKind(BidKind::Delegator(delegator)) = stored_value {
assert_eq!(
delegator.staked_amount(),
pre_delegation_balance,
"staked amount should match delegation amount"
);
}

for _ in 0..=auction_delay {
// crank era
builder.run_auction(timestamp_millis, vec![]);
}

builder
.query(None, delegation_key, &[])
.expect("should have delegation bid");
}
21 changes: 14 additions & 7 deletions node/src/components/transaction_acceptor/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ use casper_types::{
global_state::TrieMerkleProof,
testing::TestRng,
Block, BlockV2, CLValue, Chainspec, ChainspecRawBytes, Contract, Deploy, EraId, HashAddr,
InvalidDeploy, InvalidTransaction, InvalidTransactionV1, Package, PricingMode, ProtocolVersion,
PublicKey, SecretKey, StoredValue, TestBlockBuilder, TimeDiff, Timestamp, Transaction,
TransactionConfig, TransactionRuntime, TransactionV1, URef, U512,
InvalidDeploy, InvalidTransaction, InvalidTransactionV1, Package, PricingHandling, PricingMode,
ProtocolVersion, PublicKey, SecretKey, StoredValue, TestBlockBuilder, TimeDiff, Timestamp,
Transaction, TransactionConfig, TransactionRuntime, TransactionV1, URef, U512,
};

use super::*;
Expand Down Expand Up @@ -595,10 +595,9 @@ impl TestScenario {
}
TestScenario::InvalidPricingModeForTransactionV1 => {
let classic_mode_transaction = TransactionV1Builder::new_random(rng)
.with_pricing_mode(PricingMode::PaymentLimited {
payment_amount: 10000u64,
gas_price_tolerance: 1u8,
standard_payment: true,
.with_pricing_mode(PricingMode::Fixed {
gas_price_tolerance: 5,
additional_computation_factor: 0,
})
.with_chain_name("casper-example")
.build()
Expand Down Expand Up @@ -1152,6 +1151,14 @@ async fn run_transaction_acceptor_without_timeout(
let admin = SecretKey::random(rng);
let (mut chainspec, chainspec_raw_bytes) =
<(Chainspec, ChainspecRawBytes)>::from_resources("local");
let mut chainspec = if let TestScenario::TooLowGasPriceToleranceForTransactionV1 = test_scenario
{
chainspec.with_pricing_handling(PricingHandling::Fixed);
chainspec
} else {
chainspec
};

chainspec.core_config.administrators = iter::once(PublicKey::from(&admin)).collect();

let chainspec = Arc::new(chainspec);
Expand Down
67 changes: 33 additions & 34 deletions node/src/reactor/main_reactor/tests/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static CHARLIE_SECRET_KEY: Lazy<Arc<SecretKey>> = Lazy::new(|| {
static CHARLIE_PUBLIC_KEY: Lazy<PublicKey> =
Lazy::new(|| PublicKey::from(&*CHARLIE_SECRET_KEY.clone()));

const MIN_GAS_PRICE: u8 = 5;
const MIN_GAS_PRICE: u8 = 1;
const CHAIN_NAME: &str = "single-transaction-test-net";

async fn transfer_to_account<A: Into<U512>>(
Expand Down Expand Up @@ -1023,8 +1023,6 @@ impl SingleTransactionTestCase {
ConfigsOverride::default()
.with_minimum_era_height(5) // make the era longer so that the transaction doesn't land in the switch block.
.with_balance_hold_interval(TimeDiff::from_seconds(5))
.with_min_gas_price(MIN_GAS_PRICE)
.with_max_gas_price(MIN_GAS_PRICE)
.with_chain_name("single-transaction-test-net".to_string())
}

Expand Down Expand Up @@ -3045,25 +3043,27 @@ async fn insufficient_funds_transfer_from_account() {

let transfer_amount = U512::max_value();

let mut txn = Transaction::from(
let txn_v1 =
TransactionV1Builder::new_transfer(transfer_amount, None, ALICE_PUBLIC_KEY.clone(), None)
.unwrap()
.with_chain_name(CHAIN_NAME)
.with_initiator_addr(PublicKey::from(&**BOB_SECRET_KEY))
.build()
.unwrap(),
);
.unwrap();
let price = txn_v1
.payment_amount()
.expect("must have payment amount as txns are using classic");
let mut txn = Transaction::from(txn_v1);
txn.sign(&BOB_SECRET_KEY);

let (_txn_hash, _block_height, exec_result) = test.send_transaction(txn).await;
let ExecutionResult::V2(result) = exec_result else {
panic!("Expected ExecutionResult::V2 but got {:?}", exec_result);
};
let transfer_cost: U512 =
U512::from(test.chainspec().system_costs_config.mint_costs().transfer) * MIN_GAS_PRICE;
let expected_cost: U512 = U512::from(price) * MIN_GAS_PRICE;

assert_eq!(result.error_message.as_deref(), Some("Insufficient funds"));
assert_eq!(result.cost, transfer_cost);
assert_eq!(result.cost, expected_cost);
}

#[tokio::test]
Expand All @@ -3089,22 +3089,22 @@ async fn insufficient_funds_add_bid() {
let (_, bob_initial_balance, _) = test.get_balances(None);
let bid_amount = bob_initial_balance.total;

let mut txn = Transaction::from(
let txn =
TransactionV1Builder::new_add_bid(BOB_PUBLIC_KEY.clone(), 0, bid_amount, None, None, None)
.unwrap()
.with_chain_name(CHAIN_NAME)
.with_initiator_addr(PublicKey::from(&**BOB_SECRET_KEY))
.build()
.unwrap(),
);
.unwrap();
let price = txn.payment_amount().expect("must get payment amount");
let mut txn = Transaction::from(txn);
txn.sign(&BOB_SECRET_KEY);

let (_txn_hash, _block_height, exec_result) = test.send_transaction(txn).await;
let ExecutionResult::V2(result) = exec_result else {
panic!("Expected ExecutionResult::V2 but got {:?}", exec_result);
};
let bid_cost: U512 =
U512::from(test.chainspec().system_costs_config.auction_costs().add_bid) * MIN_GAS_PRICE;
let bid_cost: U512 = U512::from(price) * MIN_GAS_PRICE;

assert_eq!(
result.error_message.as_deref(),
Expand Down Expand Up @@ -3175,27 +3175,26 @@ async fn insufficient_funds_transfer_from_purse() {

// now we try to transfer from the purse we just created
let transfer_amount = U512::max_value();
let mut txn = Transaction::from(
TransactionV1Builder::new_transfer(
transfer_amount,
Some(uref),
ALICE_PUBLIC_KEY.clone(),
None,
)
.unwrap()
.with_chain_name(CHAIN_NAME)
.with_initiator_addr(PublicKey::from(&**BOB_SECRET_KEY))
.build()
.unwrap(),
);
let txn = TransactionV1Builder::new_transfer(
transfer_amount,
Some(uref),
ALICE_PUBLIC_KEY.clone(),
None,
)
.unwrap()
.with_chain_name(CHAIN_NAME)
.with_initiator_addr(PublicKey::from(&**BOB_SECRET_KEY))
.build()
.unwrap();
let price = txn.payment_amount().expect("must get payment amount");
let mut txn = Transaction::from(txn);
txn.sign(&BOB_SECRET_KEY);

let (_txn_hash, _block_height, exec_result) = test.send_transaction(txn).await;
let ExecutionResult::V2(result) = exec_result else {
panic!("Expected ExecutionResult::V2 but got {:?}", exec_result);
};
let transfer_cost: U512 =
U512::from(test.chainspec().system_costs_config.mint_costs().transfer) * MIN_GAS_PRICE;
let transfer_cost: U512 = U512::from(price) * MIN_GAS_PRICE;

assert_eq!(result.error_message.as_deref(), Some("Insufficient funds"));
assert_eq!(result.cost, transfer_cost);
Expand Down Expand Up @@ -3223,22 +3222,22 @@ async fn insufficient_funds_when_caller_lacks_minimum_balance() {

let (_, bob_initial_balance, _) = test.get_balances(None);
let transfer_amount = bob_initial_balance.total - U512::one();
let mut txn = Transaction::from(
let txn =
TransactionV1Builder::new_transfer(transfer_amount, None, ALICE_PUBLIC_KEY.clone(), None)
.unwrap()
.with_chain_name(CHAIN_NAME)
.with_initiator_addr(PublicKey::from(&**BOB_SECRET_KEY))
.build()
.unwrap(),
);
.unwrap();
let price = txn.payment_amount().expect("must get payment amount");
let mut txn = Transaction::from(txn);
txn.sign(&BOB_SECRET_KEY);

let (_txn_hash, _block_height, exec_result) = test.send_transaction(txn).await;
let ExecutionResult::V2(result) = exec_result else {
panic!("Expected ExecutionResult::V2 but got {:?}", exec_result);
};
let transfer_cost: U512 =
U512::from(test.chainspec().system_costs_config.mint_costs().transfer) * MIN_GAS_PRICE;
let transfer_cost: U512 = U512::from(price) * MIN_GAS_PRICE;

assert_eq!(result.error_message.as_deref(), Some("Insufficient funds"));
assert_eq!(result.cost, transfer_cost);
Expand Down
Loading

0 comments on commit e218f0a

Please sign in to comment.