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

Add initial code for recursion limit #4729

Merged
merged 24 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
04ed29c
Asc message execution - requery message bytecode after each message e…
Leo-Besancon Jun 18, 2024
52814d4
fix call stack inconsistency (#4709)
Leo-Besancon Jun 21, 2024
b64e360
Improve async message checks (#4706)
Leo-Besancon Jun 25, 2024
86e1d02
Fix ledger change to take into account cancelled message balance chan…
Leo-Besancon Jul 2, 2024
880eec7
Fix async msg same slot (#4718)
Leo-Besancon Jul 2, 2024
e25f021
Add initial code for recursion limit
Leo-Besancon Jul 16, 2024
9c13a14
Latest runtime
Leo-Besancon Jul 16, 2024
c0f3a0a
Run CI on PRs based on mainnet_2_3
Leo-Besancon Jul 16, 2024
57bf59d
fmt
Leo-Besancon Jul 16, 2024
ad071b5
Fix config and add UTs
Leo-Besancon Jul 16, 2024
fb20aec
Update scenarios_mandatories.rs
Leo-Besancon Jul 16, 2024
7c7c32f
Review comments (CI for all branches starting with "mainnet_" + comment)
Leo-Besancon Jul 17, 2024
2cc4a17
Update ci.yml
Leo-Besancon Jul 17, 2024
766f044
Remove manual increment / decrement in interface implementation
Leo-Besancon Aug 5, 2024
aa77944
Merge branch 'mainnet_2_3' into add_recursion_counter
Leo-Besancon Oct 15, 2024
3f37c1d
fmt + update sc_runtime + fix warning
Leo-Besancon Oct 15, 2024
e12ee3c
Merge branch 'mainnet_2_3' into add_recursion_counter
Leo-Besancon Oct 15, 2024
8504ced
Update test
Leo-Besancon Oct 15, 2024
e36e31d
Update constants.rs
Leo-Besancon Oct 15, 2024
869c46a
Updated execution config for tests
Leo-Besancon Oct 16, 2024
0069fd5
Updated usize -> u16 for recursion counter and limits
Leo-Besancon Oct 16, 2024
8c5ff99
Update test comments
Leo-Besancon Oct 16, 2024
d351f76
Add comments regarding the needs of this limits
Leo-Besancon Oct 16, 2024
b3cf306
Update sc-runtime branch
Leo-Besancon Oct 16, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main, staging, trying]
pull_request:
branches: [main, 'testnet_*']
branches: [main, 'testnet_*', 'mainnet_2_3']
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
types:
- opened
- reopened
Expand Down
39 changes: 5 additions & 34 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ massa_wallet = { path = "./massa-wallet" }

# Massa projects dependencies
massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "38950875a7aa406fedc4f0b8336864e5ff290f2c" }
massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "80352eb9f2a6b90a441cd64433d8874c33fb384f" }
massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "branch" = "add_recursion_counter" }
peernet = { git = "https://github.com/massalabs/PeerNet", "rev" = "04b05ddd320fbe76cc858115af7b5fc28bdb8310" }

# Common dependencies
Expand Down
2 changes: 2 additions & 0 deletions massa-execution-exports/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,6 @@ pub struct ExecutionConfig {
pub max_execution_traces_slot_limit: usize,
/// Where to dump blocks
pub block_dump_folder_path: PathBuf,
/// Max recursive calls depth
pub max_recursive_calls_depth: usize,
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions massa-execution-exports/src/test_exports/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ impl Default for ExecutionConfig {
broadcast_slot_execution_traces_channel_capacity: 5000,
max_execution_traces_slot_limit: 320,
block_dump_folder_path,
max_recursive_calls_depth: 50,
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
29 changes: 17 additions & 12 deletions massa-execution-worker/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ pub struct ExecutionContextSnapshot {
/// The gas remaining before the last subexecution.
/// so *excluding* the gas used by the last sc call.
pub gas_remaining_before_subexecution: Option<u64>,

/// recursion counter, incremented for each new nested call
pub recursion_counter: usize,
}

/// An execution context that needs to be initialized before executing bytecode,
Expand Down Expand Up @@ -179,6 +182,9 @@ pub struct ExecutionContext {
/// The gas remaining before the last subexecution.
/// so *excluding* the gas used by the last sc call.
pub gas_remaining_before_subexecution: Option<u64>,

/// recursion counter, incremented for each new nested call
pub recursion_counter: usize,
}

impl ExecutionContext {
Expand Down Expand Up @@ -243,6 +249,7 @@ impl ExecutionContext {
address_factory: AddressFactory { mip_store },
execution_trail_hash,
gas_remaining_before_subexecution: None,
recursion_counter: 0,
}
}

Expand All @@ -264,6 +271,7 @@ impl ExecutionContext {
event_count: self.events.0.len(),
unsafe_rng: self.unsafe_rng.clone(),
gas_remaining_before_subexecution: self.gas_remaining_before_subexecution,
recursion_counter: self.recursion_counter,
}
}

Expand Down Expand Up @@ -364,12 +372,12 @@ impl ExecutionContext {
&mut self,
max_gas: u64,
async_msg_cst_gas_cost: u64,
) -> Vec<(Option<Bytecode>, AsyncMessage)> {
self.speculative_async_pool
.take_batch_to_execute(self.slot, max_gas, async_msg_cst_gas_cost)
.into_iter()
.map(|(_id, msg)| (self.get_bytecode(&msg.destination), msg))
.collect()
) -> Vec<(AsyncMessageId, AsyncMessage)> {
self.speculative_async_pool.take_batch_to_execute(
self.slot,
max_gas,
async_msg_cst_gas_cost,
)
}

/// Create a new `ExecutionContext` for executing an active slot.
Expand Down Expand Up @@ -893,13 +901,10 @@ impl ExecutionContext {
// execute the deferred credits coming from roll sells
let deferred_credits_transfers = self.execute_deferred_credits(&slot);

// take the ledger changes first as they are needed for async messages and cache
let ledger_changes = self.speculative_ledger.take();

// settle emitted async messages and reimburse the senders of deleted messages
let deleted_messages = self
.speculative_async_pool
.settle_slot(&slot, &ledger_changes);
.settle_slot(&slot, &self.speculative_ledger.added_changes);

let mut cancel_async_message_transfers = vec![];
for (_msg_id, msg) in deleted_messages {
Expand All @@ -909,7 +914,7 @@ impl ExecutionContext {
}

// update module cache
let bc_updates = ledger_changes.get_bytecode_updates();
let bc_updates = self.speculative_ledger.added_changes.get_bytecode_updates();
{
let mut cache_write_lock = self.module_cache.write();
for bytecode in bc_updates {
Expand All @@ -935,7 +940,7 @@ impl ExecutionContext {

// generate the execution output
let state_changes = StateChanges {
ledger_changes,
ledger_changes: self.speculative_ledger.take(),
async_pool_changes: self.speculative_async_pool.take(),
pos_changes: self.speculative_roll_state.take(),
executed_ops_changes: self.speculative_executed_ops.take(),
Expand Down
19 changes: 15 additions & 4 deletions massa-execution-worker/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ impl ExecutionState {
context.stack = vec![
ExecutionStackElement {
address: message.sender,
coins: message.coins,
coins: Default::default(),
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
owned_addresses: vec![message.sender],
operation_datastore: None,
},
Expand Down Expand Up @@ -1175,10 +1175,19 @@ impl ExecutionState {

// load and execute the compiled module
// IMPORTANT: do not keep a lock here as `run_function` uses the `get_module` interface
let module = self
let Ok(module) = self
.module_cache
.write()
.load_module(&bytecode, message.max_gas)?;
.load_module(&bytecode, message.max_gas)
else {
let err =
ExecutionError::RuntimeError("could not load module for async execution".into());
let mut context = context_guard!(self);
context.reset_to_snapshot(context_snapshot, err.clone());
context.cancel_async_message(&message);
return Err(err);
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
};

let response = massa_sc_runtime::run_function(
&*self.execution_interface,
module,
Expand Down Expand Up @@ -1271,7 +1280,9 @@ impl ExecutionState {

// Try executing asynchronous messages.
// Effects are cancelled on failure and the sender is reimbursed.
for (opt_bytecode, message) in messages {
for (_message_id, message) in messages {
let opt_bytecode = context_guard!(self).get_bytecode(&message.destination);

match self.execute_async_message(message, opt_bytecode) {
Ok(_message_return) => {
cfg_if::cfg_if! {
Expand Down
43 changes: 43 additions & 0 deletions massa-execution-worker/src/interface_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,29 @@ impl Interface for InterfaceImpl {
Ok(())
}

fn increment_recursion_counter(&self) -> Result<()> {
let mut context = context_guard!(self);

context.recursion_counter += 1;

if context.recursion_counter > self.config.max_recursive_calls_depth {
bail!("recursion depth limit reached");
}

Ok(())
}

fn decrement_recursion_counter(&self) -> Result<()> {
let mut context = context_guard!(self);

match context.recursion_counter.checked_sub(1) {
Some(value) => context.recursion_counter = value,
None => bail!("recursion counter underflow"),
}

Ok(())
}

/// Initialize the call when bytecode calls a function from another bytecode
/// This function transfers the coins passed as parameter,
/// prepares the current execution context by pushing a new element on the top of the call stack,
Expand Down Expand Up @@ -282,6 +305,8 @@ impl Interface for InterfaceImpl {
operation_datastore: None,
});

context.recursion_counter += 1;
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved

// return the target bytecode
Ok(bytecode.0)
}
Expand All @@ -295,6 +320,8 @@ impl Interface for InterfaceImpl {
bail!("call stack out of bounds")
}

context.recursion_counter -= 1;
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved

Ok(())
}

Expand Down Expand Up @@ -1183,6 +1210,11 @@ impl Interface for InterfaceImpl {
if validity_end.1 >= self.config.thread_count {
bail!("validity end thread exceeds the configuration thread count")
}

if max_gas < self.config.gas_costs.max_instance_cost {
bail!("max gas is lower than the minimum instance cost")
}

let target_addr = Address::from_str(target_address)?;

// check that the target address is an SC address
Expand All @@ -1200,6 +1232,15 @@ impl Interface for InterfaceImpl {

let mut execution_context = context_guard!(self);
let emission_slot = execution_context.slot;

if Slot::new(validity_end.0, validity_end.1) < Slot::new(validity_start.0, validity_start.1)
{
bail!("validity end is earlier than the validity start")
}
if Slot::new(validity_end.0, validity_end.1) < emission_slot {
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
bail!("validity end is earlier than the current slot")
}

let emission_index = execution_context.created_message_index;
let sender = execution_context.get_current_address()?;
let coins = Amount::from_raw(raw_coins);
Expand Down Expand Up @@ -1378,6 +1419,8 @@ impl Interface for InterfaceImpl {
operation_datastore: None,
});

context.recursion_counter += 1;

// return the target bytecode
Ok(bytecode.0)
}
Expand Down
7 changes: 6 additions & 1 deletion massa-execution-worker/src/speculative_async_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,14 @@ impl SpeculativeAsyncPool {
}

// Query eliminated messages
let eliminated_msg =
let mut eliminated_msg =
self.fetch_msgs(eliminated_infos.iter().map(|(id, _)| id).collect(), true);

eliminated_msg.extend(eliminated_new_messages.iter().filter_map(|(k, v)| match v {
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
SetUpdateOrDelete::Set(v) => Some((*k, v.clone())),
SetUpdateOrDelete::Update(_v) => None,
SetUpdateOrDelete::Delete => None,
}));
eliminated_msg
}

Expand Down
13 changes: 0 additions & 13 deletions massa-execution-worker/src/speculative_ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,6 @@ pub(crate) struct SpeculativeLedger {
active_history: Arc<RwLock<ActiveHistory>>,

/// list of ledger changes that were applied to this `SpeculativeLedger` since its creation
#[cfg(all(
not(feature = "gas_calibration"),
not(feature = "benchmarking"),
not(feature = "test-exports"),
not(test)
))]
added_changes: LedgerChanges,
#[cfg(any(
feature = "gas_calibration",
feature = "benchmarking",
feature = "test-exports",
test
))]
pub added_changes: LedgerChanges,

/// max datastore key length
Expand Down
Loading
Loading