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

Update wasm lanes and opcode costs #5022

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
33 changes: 23 additions & 10 deletions execution_engine/src/bin/run_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@ struct RunWasmInfo {

fn run_wasm(
module_bytes: Vec<u8>,
cli_args: &Args,
chainspec: &ChainspecConfig,
func_name: &str,
args: &[String],
) -> (
Result<Option<RuntimeValue>, casper_wasmi::Error>,
RunWasmInfo,
) {
println!("Invoke export {:?} with args {:?}", func_name, args);
println!(
"Invoke export {:?} with args {:?}",
func_name, cli_args.args
);

let instance = prepare_instance(&module_bytes, chainspec);

Expand All @@ -51,9 +54,13 @@ fn run_wasm(
};

let args = {
assert_eq!(args.len(), params.len(), "Not enough arguments supplied");
assert_eq!(
cli_args.args.len(),
params.len(),
"Not enough arguments supplied"
);
let mut vec = Vec::new();
for (input_arg, func_arg) in args.iter().zip(params.into_iter()) {
for (input_arg, func_arg) in cli_args.args.iter().zip(params.into_iter()) {
let value = match func_arg {
casper_wasmi::ValueType::I32 => {
casper_wasmi::RuntimeValue::I32(input_arg.parse().unwrap())
Expand All @@ -71,7 +78,11 @@ fn run_wasm(

let start = Instant::now();

let mut externals = MinimalWasmiExternals::new(0, chainspec.transaction_config.block_gas_limit);
let gas_limit = cli_args
.gas_limit
.unwrap_or(chainspec.transaction_config.block_gas_limit);

let mut externals = MinimalWasmiExternals::new(0, gas_limit);
let result: Result<Option<RuntimeValue>, casper_wasmi::Error> =
instance
.clone()
Expand All @@ -87,11 +98,13 @@ fn run_wasm(
use clap::Parser;
use serde::Deserialize;

#[derive(Parser, Debug)]
#[derive(Parser, Clone, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(value_name = "MODULE")]
wasm_file: PathBuf,
#[arg(long = "gas_limit")]
gas_limit: Option<u64>,
#[arg(long = "invoke", value_name = "FUNCTION")]
invoke: Option<String>,
/// Arguments given to the Wasm module or the invoked function.
Expand Down Expand Up @@ -130,16 +143,16 @@ struct ChainspecConfig {
fn main() {
let args = Args::parse();

let chainspec_file = args.chainspec_file.expect("chainspec file");
let chainspec_file = args.clone().chainspec_file.expect("chainspec file");
println!("Using chainspec file {:?}", chainspec_file.display());
let chainspec_data = fs::read_to_string(chainspec_file.as_path()).expect("valid file");
let chainspec_config: ChainspecConfig =
toml::from_str(&chainspec_data).expect("valid chainspec");

let wasm_bytes = load_wasm_file(args.wasm_file);
let wasm_bytes = load_wasm_file(&args.wasm_file);

if let Some(func_name) = args.invoke {
let (result, info) = run_wasm(wasm_bytes, &chainspec_config, &func_name, &args.args);
if let Some(ref func_name) = args.invoke {
let (result, info) = run_wasm(wasm_bytes, &args, &chainspec_config, func_name);

println!("result: {:?}", result);
println!("elapsed: {:?}", info.elapsed);
Expand Down
8 changes: 4 additions & 4 deletions execution_engine_testing/tests/src/test/explorer/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,13 +663,13 @@ fn faucet_costs() {
// This test will fail if execution costs vary. The expected costs should not be updated
// without understanding why the cost has changed. If the costs do change, it should be
// reflected in the "Costs by Entry Point" section of the faucet crate's README.md.
const EXPECTED_FAUCET_INSTALL_COST: u64 = 144_782_774_054;
const EXPECTED_FAUCET_INSTALL_COST: u64 = 145_436_440_703;

const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 70_836_755;
const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 79_611_645;

const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_645_108_193;
const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_652_664_693;

const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_545_778_741;
const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_558_340_671;

let installer_account = AccountHash::new([1u8; 32]);
let user_account: AccountHash = AccountHash::new([2u8; 32]);
Expand Down
41 changes: 23 additions & 18 deletions node/src/components/block_validator/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ impl BlockValidationState {
.transaction_v1_config
.get_max_transaction_count(supported_lane);
if lane_count_limit < transactions as u64 {
warn!("too many transactions in lane: {lane_count_limit}");
warn!(
supported_lane,
lane_count_limit, transactions, "too many transactions in lane"
);
return Err(());
}
}
Expand Down Expand Up @@ -674,11 +677,12 @@ mod tests {
}

// Please note: values in the following test cases must match the production chainspec.
const MAX_LARGE_COUNT: u64 = 3;
const MAX_LARGE_COUNT: u64 = 1;
const MAX_AUCTION_COUNT: u64 = 145;
const MAX_INSTALL_UPGRADE_COUNT: u64 = 1;
const MAX_MINT_COUNT: u64 = 650;

#[derive(Debug)]
struct TestCase {
mint_count: u64,
auction_count: u64,
Expand Down Expand Up @@ -760,13 +764,13 @@ mod tests {
},
};

const LESS_THAN_MAX_STANDARD: TestCase = TestCase {
standard_count: FULL_STANDARD.standard_count - 1,
state_validator: |(state, responder)| {
responder.is_none() && matches!(state, BlockValidationState::InProgress { .. })
},
..FULL_STANDARD
};
// const LESS_THAN_MAX_STANDARD: TestCase = TestCase {
// standard_count: FULL_STANDARD.standard_count - 1,
// state_validator: |(state, responder)| {
// responder.is_none() && matches!(state, BlockValidationState::InProgress { .. })
// },
// ..FULL_STANDARD
// };

const TOO_MANY_STANDARD: TestCase = TestCase {
standard_count: FULL_STANDARD.standard_count + 1,
Expand Down Expand Up @@ -850,7 +854,8 @@ mod tests {
let mut rng = TestRng::new();
run_test_case(TOO_MANY_STANDARD, &mut rng);
run_test_case(FULL_STANDARD, &mut rng);
run_test_case(LESS_THAN_MAX_STANDARD, &mut rng);
// NOTE: current prod chainspec has a limit of 1 large transaction, so one less is 0 which
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use the prod chainspec in tests? I thought we use local? Could we have different limitations in local env? That would allow this test to be still valid?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Historically we were always keeping local and prod chainspec consistent

// makes the test invalid run_test_case(LESS_THAN_MAX_STANDARD, &mut rng);
}

#[test]
Expand Down Expand Up @@ -943,7 +948,7 @@ mod tests {
fn should_add_responder_if_in_progress() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
assert!(matches!(state, BlockValidationState::InProgress { .. }));
assert_eq!(state.responder_count(), 1);

Expand Down Expand Up @@ -984,7 +989,7 @@ mod tests {
fn should_add_new_holder_if_in_progress() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
assert!(matches!(state, BlockValidationState::InProgress { .. }));
assert_eq!(state.holders_mut().unwrap().len(), 1);

Expand All @@ -1001,7 +1006,7 @@ mod tests {
fn should_not_change_holder_state() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
assert!(matches!(state, BlockValidationState::InProgress { .. }));
let (holder, holder_state) = state
.holders_mut()
Expand All @@ -1024,7 +1029,7 @@ mod tests {
fn should_start_fetching() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
assert!(matches!(state, BlockValidationState::InProgress { .. }));
let (holder, holder_state) = state
.holders_mut()
Expand Down Expand Up @@ -1052,7 +1057,7 @@ mod tests {
..
} => {
assert_eq!(holder, original_holder);
assert_eq!(missing_transactions.len(), 7);
assert_eq!(missing_transactions.len(), 6);
}
_ => panic!("unexpected return value"),
}
Expand All @@ -1066,7 +1071,7 @@ mod tests {
fn start_fetching_should_return_ongoing_if_any_holder_in_asked_state() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
assert!(matches!(state, BlockValidationState::InProgress { .. }));

// Change the current (only) holder's state to `Asked`.
Expand Down Expand Up @@ -1111,7 +1116,7 @@ mod tests {
fn start_fetching_should_return_unable_if_all_holders_in_failed_state() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
assert!(matches!(state, BlockValidationState::InProgress { .. }));

// Set the original holder's state to `Failed` and add some more failed.
Expand Down Expand Up @@ -1192,7 +1197,7 @@ mod tests {
fn unrelated_transaction_added_should_not_change_state() {
let mut rng = TestRng::new();
let mut fixture = Fixture::new(&mut rng);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 2);
let (mut state, _maybe_responder) = fixture.new_state(2, 2, 1, 1);
let (appendable_block_before, missing_transactions_before, holders_before) = match &state {
BlockValidationState::InProgress {
appendable_block,
Expand Down
11 changes: 4 additions & 7 deletions node/src/components/block_validator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ async fn transfer_transaction_mixup_and_replay() {
let transfer_v1 = new_v1_transfer(&mut rng, timestamp, ttl);

// First we make sure that our transfers and transactions would normally be valid.
let transactions = vec![deploy.clone(), transaction_v1.clone()];
let transactions = vec![transaction_v1.clone()];
let transfers = vec![transfer_orig.clone(), transfer_v1.clone()];
let mut context = ValidationContext::new()
.with_num_validators(&mut rng, 1)
Expand Down Expand Up @@ -1146,15 +1146,14 @@ async fn should_validate_block_with_signatures() {
let mut rng = TestRng::new();
let ttl = TimeDiff::from_millis(200);
let timestamp = Timestamp::from(1000);
let deploy = new_deploy(&mut rng, timestamp, ttl);
let transaction_v1 = new_v1_standard(&mut rng, timestamp, ttl);
let transfer = new_transfer(&mut rng, timestamp, ttl);
let transfer_v1 = new_v1_transfer(&mut rng, timestamp, ttl);

let context = ValidationContext::new()
.with_num_validators(&mut rng, 3)
.with_past_blocks(&mut rng, 0, 5, 0.into())
.with_transactions(vec![deploy, transaction_v1])
.with_transactions(vec![transaction_v1])
.with_transfers(vec![transfer, transfer_v1])
.include_all_transactions()
.include_all_transfers();
Expand All @@ -1173,15 +1172,14 @@ async fn should_fetch_missing_signature() {
let mut rng = TestRng::new();
let ttl = TimeDiff::from_millis(200);
let timestamp = Timestamp::from(1000);
let deploy = new_deploy(&mut rng, timestamp, ttl);
let transaction_v1 = new_v1_standard(&mut rng, timestamp, ttl);
let transfer = new_transfer(&mut rng, timestamp, ttl);
let transfer_v1 = new_v1_transfer(&mut rng, timestamp, ttl);

let context = ValidationContext::new()
.with_num_validators(&mut rng, 3)
.with_past_blocks(&mut rng, 0, 5, 0.into())
.with_transactions(vec![deploy, transaction_v1])
.with_transactions(vec![transaction_v1])
.with_transfers(vec![transfer, transfer_v1])
.include_all_transactions()
.include_all_transfers();
Expand Down Expand Up @@ -1253,7 +1251,6 @@ async fn should_validate_with_delayed_block() {
let mut rng = TestRng::new();
let ttl = TimeDiff::from_millis(200);
let timestamp = Timestamp::from(1000);
let deploy = new_deploy(&mut rng, timestamp, ttl);
let transaction_v1 = new_v1_standard(&mut rng, timestamp, ttl);
let transfer = new_transfer(&mut rng, timestamp, ttl);
let transfer_v1 = new_v1_transfer(&mut rng, timestamp, ttl);
Expand All @@ -1262,7 +1259,7 @@ async fn should_validate_with_delayed_block() {
.with_num_validators(&mut rng, 3)
.with_past_blocks(&mut rng, 0, 4, 0.into())
.with_delayed_blocks(&mut rng, 5, 5, 0.into())
.with_transactions(vec![deploy, transaction_v1])
.with_transactions(vec![transaction_v1])
.with_transfers(vec![transfer, transfer_v1])
.include_all_transactions()
.include_all_transfers();
Expand Down
67 changes: 35 additions & 32 deletions resources/local/chainspec.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ block_max_approval_count = 2600
# Maximum block size in bytes including transactions contained by the block. 0 means unlimited.
max_block_size = 5_242_880
# The upper limit of total gas of all transactions in a block.
block_gas_limit = 200_000_000_000
block_gas_limit = 1_625_000_000_000
# The minimum amount in motes for a valid native transfer.
native_transfer_minimum_motes = 2_500_000_000
# The maximum value to which `transaction_acceptor.timestamp_leeway` can be set in the config.toml file.
Expand Down Expand Up @@ -206,7 +206,10 @@ vm_casper_v2 = false
native_mint_lane = [0, 2048, 1024, 2_500_000_000, 650]
native_auction_lane = [1, 3096, 2048, 2_500_000_000, 145]
install_upgrade_lane = [2, 1_048_576, 2048, 100_000_000_000, 1]
wasm_lanes = [[3, 344_064, 1024, 100_000_000_000, 3], [4, 172_032, 1024, 50_000_000_000, 7], [5, 12_288, 512, 2_500_000_000, 25]]
wasm_lanes = [
[3, 344_064, 1024, 100_000_000_000, 1],
[4, 172_032, 1024, 50_000_000_000, 2],
[5, 12_288, 512, 2_500_000_000, 80]]

[transactions.deploy]
# The maximum number of Motes allowed to be spent during payment. 0 means unlimited.
Expand All @@ -228,56 +231,56 @@ gas_per_byte = 1_117_587

[wasm.v1.opcode_costs]
# Bit operations multiplier.
bit = 35
bit = 105
# Arithmetic add operations multiplier.
add = 35
add = 105
# Mul operations multiplier.
mul = 35
mul = 105
# Div operations multiplier.
div = 35
div = 105
# Memory load operation multiplier.
load = 35
load = 105
# Memory store operation multiplier.
store = 35
store = 105
# Const store operation multiplier.
const = 35
const = 105
# Local operations multiplier.
local = 35
local = 105
# Global operations multiplier.
global = 35
global = 105
# Integer operations multiplier.
integer_comparison = 35
integer_comparison = 105
# Conversion operations multiplier.
conversion = 35
conversion = 105
# Unreachable operation multiplier.
unreachable = 35
unreachable = 105
# Nop operation multiplier.
nop = 35
nop = 105
# Get current memory operation multiplier.
current_memory = 35
# Grow memory cost, per page (64kb).
grow_memory = 300
current_memory = 105
# Grow memory cost, per page (192kb).
grow_memory = 900
# Sign extension operations cost
sign = 35
sign = 105

# Control flow operations multiplier.
[wasm.v1.opcode_costs.control_flow]
block = 85
loop = 85
if = 35
else = 35
end = 35
br = 555
br_if = 170
return = 35
select = 35
call = 75
call_indirect = 90
drop = 35
block = 255
loop = 255
if = 105
else = 105
end = 105
br = 1665
br_if = 510
return = 105
select = 105
call = 225
call_indirect = 270
drop = 105

[wasm.v1.opcode_costs.control_flow.br_table]
# Fixed cost per `br_table` opcode
cost = 50
cost = 150
# Size of target labels in the `br_table` opcode will be multiplied by `size_multiplier`
size_multiplier = 100

Expand Down
Loading
Loading