diff --git a/massa-deferred-calls/src/call.rs b/massa-deferred-calls/src/call.rs index 7080ea055f1..4feeef85fe1 100644 --- a/massa-deferred-calls/src/call.rs +++ b/massa-deferred-calls/src/call.rs @@ -78,7 +78,7 @@ pub struct DeferredCallSerializer { } impl DeferredCallSerializer { - /// Serializes an `AsyncCall` into a `Vec` + /// Serializes an `DeferredCall` into a `Vec` pub fn new() -> Self { Self { slot_serializer: SlotSerializer::new(), diff --git a/massa-deferred-calls/src/lib.rs b/massa-deferred-calls/src/lib.rs index 6165e89a48f..b259ef1a807 100644 --- a/massa-deferred-calls/src/lib.rs +++ b/massa-deferred-calls/src/lib.rs @@ -27,7 +27,7 @@ use massa_ledger_exports::{SetOrDelete, SetOrKeep}; use massa_models::{ amount::Amount, config::{DEFERRED_CALL_MAX_POOL_CHANGES, MAX_ASYNC_GAS, THREAD_COUNT}, - deferred_call_id::{DeferredCallId, DeferredCallIdDeserializer, DeferredCallIdSerializer}, + deferred_calls::{DeferredCallId, DeferredCallIdDeserializer, DeferredCallIdSerializer}, slot::Slot, }; use std::collections::{BTreeMap, HashSet}; @@ -49,7 +49,7 @@ impl DeferredCallRegistry { [DEFERRED_CALL_TOTAL_GAS] -> u64 // total currently booked gas [DEFERRED_CALLS_PREFIX][slot][SLOT_TOTAL_GAS] -> u64 // total gas booked for a slot (optional, default 0, deleted when set to 0) [DEFERRED_CALLS_PREFIX][slot][SLOT_BASE_FEE] -> u64 // deleted when set to 0 - [DEFERRED_CALLS_PREFIX][slot][CALLS_TAG][id][CALL_FIELD_X_TAG] -> AsyncCall.x // call data + [DEFERRED_CALLS_PREFIX][slot][CALLS_TAG][id][CALL_FIELD_X_TAG] -> DeferredCalls.x // call data */ // TODO pass args @@ -205,89 +205,105 @@ impl DeferredCallRegistry { let db = self.db.read(); - // sender address - let mut temp_buffer = Vec::new(); - self.call_serializer - .address_serializer - .serialize(&call.sender_address, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value( - batch, - sender_address_key!(buffer_id, slot_bytes), - &temp_buffer, - ); - temp_buffer.clear(); - - // target slot - self.call_serializer - .slot_serializer - .serialize(&call.target_slot, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value(batch, target_slot_key!(buffer_id, slot_bytes), &temp_buffer); - temp_buffer.clear(); + { + // sender address + let mut buffer = Vec::new(); + self.call_serializer + .address_serializer + .serialize(&call.sender_address, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value( + batch, + sender_address_key!(buffer_id, slot_bytes), + &buffer, + ); + } - // target address - self.call_serializer - .address_serializer - .serialize(&call.target_address, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value( - batch, - target_address_key!(buffer_id, slot_bytes), - &temp_buffer, - ); - temp_buffer.clear(); - - // target function - self.call_serializer - .string_serializer - .serialize(&call.target_function, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value( - batch, - target_function_key!(buffer_id, slot_bytes), - &temp_buffer, - ); - temp_buffer.clear(); - - // parameters - self.call_serializer - .vec_u8_serializer - .serialize(&call.parameters, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value(batch, parameters_key!(buffer_id, slot_bytes), &temp_buffer); - temp_buffer.clear(); + { + // target slot + let mut buffer = Vec::new(); + self.call_serializer + .slot_serializer + .serialize(&call.target_slot, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value(batch, target_slot_key!(buffer_id, slot_bytes), &buffer); + } - // coins - self.call_serializer - .amount_serializer - .serialize(&call.coins, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value(batch, coins_key!(buffer_id, slot_bytes), &temp_buffer); - temp_buffer.clear(); + { + // target address + let mut buffer = Vec::new(); + self.call_serializer + .address_serializer + .serialize(&call.target_address, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value( + batch, + target_address_key!(buffer_id, slot_bytes), + &buffer, + ); + } - // max gas - self.call_serializer - .u64_var_int_serializer - .serialize(&call.max_gas, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value(batch, max_gas_key!(buffer_id, slot_bytes), &temp_buffer); - temp_buffer.clear(); + { + // target function + let mut buffer = Vec::new(); + self.call_serializer + .string_serializer + .serialize(&call.target_function, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value( + batch, + target_function_key!(buffer_id, slot_bytes), + &buffer, + ); + } - // fee - self.call_serializer - .amount_serializer - .serialize(&call.fee, &mut temp_buffer) - .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value(batch, fee_key!(buffer_id, slot_bytes), &temp_buffer); - temp_buffer.clear(); + { + // parameters + let mut buffer = Vec::new(); + self.call_serializer + .vec_u8_serializer + .serialize(&call.parameters, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value(batch, parameters_key!(buffer_id, slot_bytes), &buffer); + } + + { + // coins + let mut buffer = Vec::new(); + self.call_serializer + .amount_serializer + .serialize(&call.coins, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value(batch, coins_key!(buffer_id, slot_bytes), &buffer); + } + + { + // max gas + let mut buffer = Vec::new(); + self.call_serializer + .u64_var_int_serializer + .serialize(&call.max_gas, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value(batch, max_gas_key!(buffer_id, slot_bytes), &buffer); + } + + { + // fee + let mut buffer = Vec::new(); + self.call_serializer + .amount_serializer + .serialize(&call.fee, &mut buffer) + .expect(DEFERRED_CALL_SER_ERROR); + db.put_or_update_entry_value(batch, fee_key!(buffer_id, slot_bytes), &buffer); + } // cancelled + let mut buffer = Vec::new(); self.call_serializer .bool_serializer - .serialize(&call.cancelled, &mut temp_buffer) + .serialize(&call.cancelled, &mut buffer) .expect(DEFERRED_CALL_SER_ERROR); - db.put_or_update_entry_value(batch, cancelled_key!(buffer_id, slot_bytes), &temp_buffer); + db.put_or_update_entry_value(batch, cancelled_key!(buffer_id, slot_bytes), &buffer); } fn delete_entry(&self, id: &DeferredCallId, slot: &Slot, batch: &mut DBBatch) { @@ -389,50 +405,11 @@ impl DeferredCallRegistry { } } -// #[derive(Debug, Clone, Serialize, Deserialize)] -// pub enum DeferredRegistryCallChange { -// Set(DeferredCall), -// Delete, -// } - // TODO put SetOrDelete dans models pub type DeferredRegistryCallChange = SetOrDelete; pub type DeferredRegistryGasChange = SetOrKeep; pub type DeferredRegistryBaseFeeChange = SetOrKeep; -// impl DeferredRegistryCallChange { -// pub fn merge(&mut self, other: DeferredRegistryCallChange) { -// *self = other; -// } - -// pub fn delete_call(&mut self) { -// *self = DeferredRegistryCallChange::Delete; -// } - -// pub fn set_call(&mut self, call: DeferredCall) { -// *self = DeferredRegistryCallChange::Set(call); -// } - -// pub fn get_call(&self) -> Option<&DeferredCall> { -// match self { -// DeferredRegistryCallChange::Set(v) => Some(v), -// DeferredRegistryCallChange::Delete => None, -// } -// } -// } - -// #[derive(Debug, Clone, Serialize, Deserialize)] -// pub enum DeferredRegistryGasChange { -// Set(V), -// Keep, -// } - -// impl Default for DeferredRegistryGasChange { -// fn default() -> Self { -// DeferredRegistryGasChange::Keep -// } -// } - /// A structure that lists slot calls for a given slot, /// as well as global gas usage statistics. #[derive(Debug, Clone)] diff --git a/massa-deferred-calls/src/macros.rs b/massa-deferred-calls/src/macros.rs index 9c45187d91f..f881e758f4a 100644 --- a/massa-deferred-calls/src/macros.rs +++ b/massa-deferred-calls/src/macros.rs @@ -143,7 +143,7 @@ macro_rules! cancelled_key { mod tests { use massa_db_exports::DEFERRED_CALLS_PREFIX; use massa_models::{ - deferred_call_id::{DeferredCallId, DeferredCallIdSerializer}, + deferred_calls::{DeferredCallId, DeferredCallIdSerializer}, slot::Slot, }; use massa_serialization::Serializer; diff --git a/massa-deferred-calls/src/registry_changes.rs b/massa-deferred-calls/src/registry_changes.rs index b18b35f79e0..703811bff58 100644 --- a/massa-deferred-calls/src/registry_changes.rs +++ b/massa-deferred-calls/src/registry_changes.rs @@ -3,7 +3,7 @@ use std::{collections::BTreeMap, ops::Bound}; use massa_ledger_exports::{SetOrKeepDeserializer, SetOrKeepSerializer}; use massa_models::{ amount::Amount, - deferred_call_id::DeferredCallId, + deferred_calls::DeferredCallId, slot::{Slot, SlotDeserializer, SlotSerializer}, }; use massa_serialization::{ @@ -208,7 +208,7 @@ impl Deserializer for DeferredRegistryChangesDeseri mod tests { use std::str::FromStr; - use massa_models::{address::Address, amount::Amount, deferred_call_id::DeferredCallId}; + use massa_models::{address::Address, amount::Amount, deferred_calls::DeferredCallId}; use massa_serialization::DeserializeError; use crate::{ diff --git a/massa-deferred-calls/src/slot_changes.rs b/massa-deferred-calls/src/slot_changes.rs index c2ac6d40f58..294b0762f54 100644 --- a/massa-deferred-calls/src/slot_changes.rs +++ b/massa-deferred-calls/src/slot_changes.rs @@ -11,7 +11,7 @@ use massa_ledger_exports::{ }; use massa_models::{ amount::{Amount, AmountDeserializer, AmountSerializer}, - deferred_call_id::{DeferredCallId, DeferredCallIdDeserializer, DeferredCallIdSerializer}, + deferred_calls::{DeferredCallId, DeferredCallIdDeserializer, DeferredCallIdSerializer}, }; use massa_serialization::{ Deserializer, SerializeError, Serializer, U64VarIntDeserializer, U64VarIntSerializer, @@ -213,7 +213,7 @@ mod tests { use std::str::FromStr; use massa_models::{ - address::Address, amount::Amount, deferred_call_id::DeferredCallId, slot::Slot, + address::Address, amount::Amount, deferred_calls::DeferredCallId, slot::Slot, }; use massa_serialization::{DeserializeError, Deserializer, Serializer}; diff --git a/massa-deferred-calls/src/tests/mod.rs b/massa-deferred-calls/src/tests/mod.rs index 9cc414d2951..d89ee1054c7 100644 --- a/massa-deferred-calls/src/tests/mod.rs +++ b/massa-deferred-calls/src/tests/mod.rs @@ -6,7 +6,7 @@ use massa_models::{ address::Address, amount::Amount, config::THREAD_COUNT, - deferred_call_id::{DeferredCallId, DeferredCallIdSerializer}, + deferred_calls::{DeferredCallId, DeferredCallIdSerializer}, slot::Slot, }; use parking_lot::RwLock; diff --git a/massa-execution-worker/src/context.rs b/massa-execution-worker/src/context.rs index 18da3cecf48..34efa720299 100644 --- a/massa-execution-worker/src/context.rs +++ b/massa-execution-worker/src/context.rs @@ -29,7 +29,7 @@ use massa_ledger_exports::{LedgerChanges, SetOrKeep}; use massa_models::address::ExecutionAddressCycleInfo; use massa_models::block_id::BlockIdSerializer; use massa_models::bytecode::Bytecode; -use massa_models::deferred_call_id::DeferredCallId; +use massa_models::deferred_calls::DeferredCallId; use massa_models::denunciation::DenunciationIndex; use massa_models::timeslots::get_block_slot_timestamp; use massa_models::{ @@ -1183,7 +1183,7 @@ impl ExecutionContext { /// Check if a deferred call exists /// If it exists, check if it has been cancelled /// If it has been cancelled, return false - pub fn deferred_call_exist(&self, call_id: &DeferredCallId) -> bool { + pub fn deferred_call_exists(&self, call_id: &DeferredCallId) -> bool { if let Some(call) = self.speculative_deferred_calls.get_call(call_id) { return call.cancelled; } @@ -1193,6 +1193,7 @@ impl ExecutionContext { /// when a deferred call execution fails we need to refund the coins to the caller pub fn deferred_call_fail_exec( &mut self, + id: &DeferredCallId, call: &DeferredCall, ) -> Option<(Address, Result)> { #[allow(unused_assignments, unused_mut)] @@ -1207,6 +1208,9 @@ impl ExecutionContext { ); } + let event = self.event_create(format!("DeferredCall execution fail call_id:{}", id), true); + self.event_emit(event); + #[cfg(feature = "execution-info")] if let Err(e) = transfer_result { result = Some((call.sender_address, Err(e.to_string()))) @@ -1217,11 +1221,7 @@ impl ExecutionContext { result } - /// not used for now - pub fn deferred_call_delete(&mut self, call_id: &DeferredCallId, slot: Slot) { - self.speculative_deferred_calls.delete_call(call_id, slot); - } - + /// when a deferred call is cancelled we need to refund the coins to the caller pub fn deferred_call_cancel( &mut self, call_id: &DeferredCallId, diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index cd8dd9f3517..d23ef84c0b4 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -30,6 +30,7 @@ use massa_models::bytecode::Bytecode; use massa_models::config::DEFERRED_CALL_MAX_FUTURE_SLOTS; use massa_models::datastore::get_prefix_bounds; +use massa_models::deferred_calls::DeferredCallId; use massa_models::denunciation::{Denunciation, DenunciationIndex}; use massa_models::execution::EventFilter; use massa_models::output_event::SCOutputEvent; @@ -1227,6 +1228,7 @@ impl ExecutionState { fn execute_deferred_call( &self, + id: &DeferredCallId, call: DeferredCall, ) -> Result { let mut result = DeferredCallExecutionResult::new(&call); @@ -1261,7 +1263,7 @@ impl ExecutionState { // Ensure that the target address exists if let Err(err) = context.check_target_sc_address(call.target_address) { context.reset_to_snapshot(snapshot, err.clone()); - context.deferred_call_fail_exec(&call); + context.deferred_call_fail_exec(id, &call); return Err(err); } @@ -1276,7 +1278,7 @@ impl ExecutionState { )); context.reset_to_snapshot(snapshot, err.clone()); - context.deferred_call_fail_exec(&call); + context.deferred_call_fail_exec(id, &call); return Err(err); } @@ -1336,7 +1338,7 @@ impl ExecutionState { }; let mut context = context_guard!(self); context.reset_to_snapshot(snapshot, err.clone()); - context.deferred_call_fail_exec(&call); + context.deferred_call_fail_exec(id, &call); Err(err) } } @@ -1388,12 +1390,6 @@ impl ExecutionState { self.config.thread_count, ); - // Get asynchronous messages to execute - let messages = execution_context.take_async_batch( - self.config.max_async_gas.saturating_sub(calls.slot_gas), - self.config.async_msg_cst_gas_cost, - ); - // Apply the created execution context for slot execution *context_guard!(self) = execution_context; @@ -1402,7 +1398,7 @@ impl ExecutionState { // Skip cancelled calls continue; } - match self.execute_deferred_call(call) { + match self.execute_deferred_call(&id, call) { Ok(_exec) => { info!("executed deferred call: {:?}", id); cfg_if::cfg_if! { @@ -1424,31 +1420,9 @@ impl ExecutionState { } } - // Try executing asynchronous messages. - // Effects are cancelled on failure and the sender is reimbursed. - for (opt_bytecode, message) in messages { - match self.execute_async_message(message, opt_bytecode) { - Ok(_message_return) => { - cfg_if::cfg_if! { - if #[cfg(feature = "execution-trace")] { - // Safe to unwrap - slot_trace.asc_call_stacks.push(_message_return.traces.unwrap().0); - } else if #[cfg(feature = "execution-info")] { - slot_trace.asc_call_stacks.push(_message_return.traces.clone().unwrap().0); - exec_info.async_messages.push(Ok(_message_return)); - } - } - } - Err(err) => { - let msg = format!("failed executing async message: {}", err); - #[cfg(feature = "execution-info")] - exec_info.async_messages.push(Err(msg.clone())); - debug!(msg); - } - } - } - let mut block_info: Option = None; + // Set block gas (max_gas_per_block - gas used by deferred calls) + let mut remaining_block_gas = self.config.max_gas_per_block; // Check if there is a block at this slot if let Some((block_id, block_metadata)) = exec_target { @@ -1500,9 +1474,6 @@ impl ExecutionState { .same_thread_parent_creator .expect("same thread parent creator missing"); - // Set remaining block gas - let mut remaining_block_gas = self.config.max_gas_per_block; - // Set block credits let mut block_credits = self.config.block_reward; @@ -1704,6 +1675,37 @@ impl ExecutionState { context_guard!(self).update_production_stats(&producer_addr, *slot, None); } + // Get asynchronous messages to execute + // The gas available for async messages is the remaining block gas + async remaining gas (max_async - gas used by deferred calls) + let async_msg_gas_available = + self.config.max_async_gas.saturating_sub(calls.slot_gas) + remaining_block_gas; + let messages = context_guard!(self) + .take_async_batch(async_msg_gas_available, self.config.async_msg_cst_gas_cost); + + // Try executing asynchronous messages. + // Effects are cancelled on failure and the sender is reimbursed. + for (opt_bytecode, message) in messages { + match self.execute_async_message(message, opt_bytecode) { + Ok(_message_return) => { + cfg_if::cfg_if! { + if #[cfg(feature = "execution-trace")] { + // Safe to unwrap + slot_trace.asc_call_stacks.push(_message_return.traces.unwrap().0); + } else if #[cfg(feature = "execution-info")] { + slot_trace.asc_call_stacks.push(_message_return.traces.clone().unwrap().0); + exec_info.async_messages.push(Ok(_message_return)); + } + } + } + Err(err) => { + let msg = format!("failed executing async message: {}", err); + #[cfg(feature = "execution-info")] + exec_info.async_messages.push(Err(msg.clone())); + debug!(msg); + } + } + } + #[cfg(feature = "execution-trace")] self.trace_history .write() diff --git a/massa-execution-worker/src/interface_impl.rs b/massa-execution-worker/src/interface_impl.rs index bfc1a947f3f..1bf5791628f 100644 --- a/massa-execution-worker/src/interface_impl.rs +++ b/massa-execution-worker/src/interface_impl.rs @@ -16,7 +16,7 @@ use massa_models::config::{ DEFERRED_CALL_GLOBAL_OVERBOOKING_PENALTY, DEFERRED_CALL_SLOT_OVERBOOKING_PENALTY, }; use massa_models::datastore::get_prefix_bounds; -use massa_models::deferred_call_id::DeferredCallId; +use massa_models::deferred_calls::DeferredCallId; use massa_models::{ address::{Address, SCAddress, UserAddress}, amount::Amount, @@ -1472,7 +1472,7 @@ impl Interface for InterfaceImpl { // write-lock context let call_id = DeferredCallId::from_bytes(id)?; let context = context_guard!(self); - Ok(context.deferred_call_exist(&call_id)) + Ok(context.deferred_call_exists(&call_id)) } /// Cancel a deferred call diff --git a/massa-execution-worker/src/speculative_deferred_calls.rs b/massa-execution-worker/src/speculative_deferred_calls.rs index b058cfe5319..e299965e1d6 100644 --- a/massa-execution-worker/src/speculative_deferred_calls.rs +++ b/massa-execution-worker/src/speculative_deferred_calls.rs @@ -13,7 +13,7 @@ use massa_models::{ DEFERRED_CALL_BASE_FEE_MAX_CHANGE_DENOMINATOR, DEFERRED_CALL_MAX_FUTURE_SLOTS, DEFERRED_CALL_MIN_GAS_COST, DEFERRED_CALL_MIN_GAS_INCREMENT, MAX_ASYNC_GAS, }, - deferred_call_id::DeferredCallId, + deferred_calls::DeferredCallId, slot::Slot, }; use parking_lot::RwLock; diff --git a/massa-execution-worker/src/tests/scenarios_mandatories.rs b/massa-execution-worker/src/tests/scenarios_mandatories.rs index f081f8fcc7b..f078d96ad8f 100644 --- a/massa-execution-worker/src/tests/scenarios_mandatories.rs +++ b/massa-execution-worker/src/tests/scenarios_mandatories.rs @@ -20,7 +20,7 @@ use massa_models::bytecode::Bytecode; use massa_models::config::{ CHAINID, ENDORSEMENT_COUNT, LEDGER_ENTRY_DATASTORE_BASE_SIZE, THREAD_COUNT, }; -use massa_models::deferred_call_id::DeferredCallId; +use massa_models::deferred_calls::DeferredCallId; use massa_models::prehash::PreHashMap; use massa_models::test_exports::gen_endorsements_for_denunciation; use massa_models::{address::Address, amount::Amount, slot::Slot}; diff --git a/massa-models/src/deferred_call_id.rs b/massa-models/src/deferred_calls.rs similarity index 100% rename from massa-models/src/deferred_call_id.rs rename to massa-models/src/deferred_calls.rs diff --git a/massa-models/src/lib.rs b/massa-models/src/lib.rs index 4aede396e25..5b3026725bc 100644 --- a/massa-models/src/lib.rs +++ b/massa-models/src/lib.rs @@ -29,7 +29,7 @@ pub mod config; /// datastore serialization / deserialization pub mod datastore; /// deferred call id -pub mod deferred_call_id; +pub mod deferred_calls; /// denunciation pub mod denunciation; /// endorsements