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

Refactor execution state reads #4152

Merged
merged 26 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from 21 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.idea
.vscode
.fleet
*.zst*
*.swp*
**/Cargo.lock
**/target
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions massa-execution-exports/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ massa_models = { path = "../massa-models" }
massa_time = { path = "../massa-time" }
massa_storage = { path = "../massa-storage" }
massa_final_state = { path = "../massa-final-state" }
massa_pos_exports = { path = "../massa-pos-exports" }
massa_ledger_exports = { path = "../massa-ledger-exports", optional = true }
massa_module_cache = { path = "../massa-module-cache" }
massa_versioning = { path = "../massa-versioning" }
Expand Down
11 changes: 9 additions & 2 deletions massa-execution-exports/src/controller_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

//! This module exports generic traits representing interfaces for interacting with the Execution worker

use crate::types::ReadOnlyExecutionRequest;
use crate::types::{ExecutionQueryRequest, ExecutionQueryResponse, ReadOnlyExecutionRequest};
use crate::ExecutionError;
use crate::{ExecutionAddressInfo, ReadOnlyExecutionOutput};
use massa_models::address::Address;
Expand Down Expand Up @@ -35,6 +35,9 @@ pub trait ExecutionController: Send + Sync {
block_storage: PreHashMap<BlockId, Storage>,
);

/// Atomically query the execution state with multiple requests
fn query_state(&self, req: ExecutionQueryRequest) -> ExecutionQueryResponse;

/// Get execution events optionally filtered by:
/// * start slot
/// * end slot
Expand Down Expand Up @@ -91,7 +94,11 @@ pub trait ExecutionController: Send + Sync {
) -> Result<ReadOnlyExecutionOutput, ExecutionError>;

/// Check if a denunciation has been executed given a `DenunciationIndex`
fn is_denunciation_executed(&self, denunciation_index: &DenunciationIndex) -> bool;
/// (speculative, final)
fn get_denunciation_execution_status(
&self,
denunciation_index: &DenunciationIndex,
) -> (bool, bool);

/// Gets information about a batch of addresses
fn get_addresses_infos(&self, addresses: &[Address]) -> Vec<ExecutionAddressInfo>;
Expand Down
7 changes: 7 additions & 0 deletions massa-execution-exports/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,10 @@ pub enum ExecutionError {
/// Factory error: {0}
FactoryError(#[from] FactoryError),
}

/// Execution query errors
#[derive(Clone, Display, Error, Debug)]
pub enum ExecutionQueryError {
/// Not found: {0}
NotFound(String),
}
10 changes: 6 additions & 4 deletions massa-execution-exports/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ pub use channels::ExecutionChannels;
#[cfg(any(test, feature = "testing"))]
pub use controller_traits::MockExecutionController;
pub use controller_traits::{ExecutionController, ExecutionManager};
pub use error::ExecutionError;
pub use error::{ExecutionError, ExecutionQueryError};
pub use event_store::EventStore;
pub use massa_sc_runtime::GasCosts;
pub use settings::{ExecutionConfig, StorageCostsConstants};
pub use types::{
ExecutionAddressInfo, ExecutionOutput, ExecutionStackElement, ReadOnlyCallRequest,
ReadOnlyExecutionOutput, ReadOnlyExecutionRequest, ReadOnlyExecutionTarget,
SlotExecutionOutput,
ExecutionAddressInfo, ExecutionOutput, ExecutionQueryCycleInfos, ExecutionQueryExecutionStatus,
ExecutionQueryRequest, ExecutionQueryRequestItem, ExecutionQueryResponse,
ExecutionQueryResponseItem, ExecutionQueryStakerInfo, ExecutionStackElement,
ReadOnlyCallRequest, ReadOnlyExecutionOutput, ReadOnlyExecutionRequest,
ReadOnlyExecutionTarget, SlotExecutionOutput,
};

#[cfg(any(feature = "testing", feature = "gas_calibration"))]
Expand Down
15 changes: 12 additions & 3 deletions massa-execution-exports/src/test_exports/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

//! This file defines utilities to mock the crate for testing purposes

use crate::types::{ExecutionQueryRequest, ExecutionQueryResponse};
use crate::{
ExecutionAddressInfo, ExecutionController, ExecutionError, ReadOnlyExecutionOutput,
ReadOnlyExecutionRequest,
Expand Down Expand Up @@ -81,8 +82,8 @@ pub enum MockExecutionControllerMessage {
IsDenunciationExecuted {
/// denunciation index
de_idx: DenunciationIndex,
/// response channel
response_tx: mpsc::Sender<bool>,
/// response channel: (speculative, final)
response_tx: mpsc::Sender<(bool, bool)>,
},
/// Get final and candidate balances by addresses
GetFinalAndCandidateBalance {
Expand Down Expand Up @@ -149,6 +150,11 @@ impl ExecutionController for MockExecutionController {
.unwrap();
}

fn query_state(&self, _req: ExecutionQueryRequest) -> ExecutionQueryResponse {
unimplemented!("mocked execution controller does not support query_state for now");
//TODO
}

fn get_filtered_sc_output_event(&self, filter: EventFilter) -> Vec<SCOutputEvent> {
let (response_tx, response_rx) = mpsc::channel();
self.0
Expand Down Expand Up @@ -206,7 +212,10 @@ impl ExecutionController for MockExecutionController {
response_rx.recv().unwrap()
}

fn is_denunciation_executed(&self, denunciation_index: &DenunciationIndex) -> bool {
fn get_denunciation_execution_status(
&self,
denunciation_index: &DenunciationIndex,
) -> (bool, bool) {
let (response_tx, response_rx) = mpsc::channel();
if let Err(err) =
self.0
Expand Down
152 changes: 152 additions & 0 deletions massa-execution-exports/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,167 @@

//! This file exports useful types used to interact with the execution worker

use crate::error::ExecutionQueryError;
use crate::event_store::EventStore;
use massa_final_state::StateChanges;
use massa_models::bytecode::Bytecode;
use massa_models::datastore::Datastore;
use massa_models::denunciation::DenunciationIndex;
use massa_models::execution::EventFilter;
use massa_models::operation::OperationId;
use massa_models::output_event::SCOutputEvent;
use massa_models::prehash::PreHashSet;
use massa_models::{
address::Address, address::ExecutionAddressCycleInfo, amount::Amount, block_id::BlockId,
slot::Slot,
};
use massa_pos_exports::ProductionStats;
use std::collections::{BTreeMap, BTreeSet};

/// Request to atomically execute a batch of execution state queries
pub struct ExecutionQueryRequest {
/// List of requests
pub requests: Vec<ExecutionQueryRequestItem>,
}

/// Response to a list of execution queries
pub struct ExecutionQueryResponse {
/// List of responses
pub responses: Vec<Result<ExecutionQueryResponseItem, ExecutionQueryError>>,
/// Last executed final slot
pub final_cursor: Slot,
/// Last executed candidate slot
pub candidate_cursor: Slot,
}

/// Execution state query item
pub enum ExecutionQueryRequestItem {
/// checks if address exists (candidate) returns ExecutionQueryResponseItem::Boolean(true) if it does
AddressExistsCandidate(Address),
/// checks if address exists (finak) returns ExecutionQueryResponseItem::Boolean(true) if it does
AddressExistsFinal(Address),
/// gets the balance (candidate) of an address, returns ExecutionQueryResponseItem::Amount(balance) or an error if the address is not found
AddressBalanceCandidate(Address),
/// gets the balance (final) of an address, returns ExecutionQueryResponseItem::Amount(balance) or an error if the address is not found
AddressBalanceFinal(Address),
/// gets the bytecode (candidate) of an address, returns ExecutionQueryResponseItem::Bytecode(bytecode) or an error if the address is not found
AddressBytecodeCandidate(Address),
/// gets the bytecode (final) of an address, returns ExecutionQueryResponseItem::Bytecode(bytecode) or an error if the address is not found
AddressBytecodeFinal(Address),
/// gets the datastore keys (candidate) of an address, returns ExecutionQueryResponseItem::KeyList(keys) or an error if the address is not found
AddressDatastoreKeysCandidate {
/// Address for which to query the datastore
addr: Address,
/// Filter only entries whose key starts with a prefix
prefix: Vec<u8>,
},
/// gets the datastore keys (final) of an address, returns ExecutionQueryResponseItem::KeyList(keys) or an error if the address is not found
AddressDatastoreKeysFinal {
/// Address for which to query the datastore
addr: Address,
/// Filter only entries whose key starts with a prefix
prefix: Vec<u8>,
},
/// gets a datastore value (candidate) for an address, returns ExecutionQueryResponseItem::DatastoreValue(keys) or an error if the address or key is not found
AddressDatastoreValueCandidate {
/// Address for which to query the datastore
addr: Address,
/// Key of the entry
key: Vec<u8>,
},
/// gets a datastore value (final) for an address, returns ExecutionQueryResponseItem::DatastoreValue(keys) or an error if the address or key is not found
AddressDatastoreValueFinal {
/// Address for which to query the datastore
addr: Address,
/// Key of the entry
key: Vec<u8>,
},

/// gets the execution status (candidate) for an operation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
OpExecutionStatusCandidate(OperationId),
/// gets the execution status (final) for an operation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
OpExecutionStatusFinal(OperationId),
/// gets the execution status (candidate) for an denunciation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
DenunciationExecutionStatusCandidate(DenunciationIndex),
/// gets the execution status (final) for an denunciation, returns ExecutionQueryResponseItem::ExecutionStatus(status)
DenunciationExecutionStatusFinal(DenunciationIndex),

/// gets the roll count (candidate) of an address, returns ExecutionQueryResponseItem::RollCount(rolls) or an error if the address is not found
AddressRollsCandidate(Address),
/// gets the roll count (final) of an address, returns ExecutionQueryResponseItem::RollCount(rolls) or an error if the address is not found
AddressRollsFinal(Address),
/// gets the deferred credits (candidate) of an address, returns ExecutionQueryResponseItem::DeferredCredits(deferred_credits) or an error if the address is not found
AddressDeferredCreditsCandidate(Address),
/// gets the deferred credits (final) of an address, returns ExecutionQueryResponseItem::DeferredCredits(deferred_credits) or an error if the address is not found
AddressDeferredCreditsFinal(Address),

/// get all information for a given cycle, returns ExecutionQueryResponseItem::CycleInfos(cycle_infos) or an error if the cycle is not found
CycleInfos {
/// cycle to query
cycle: u64,
/// optionally restrict the query to a set of addresses. If None, the info for all addresses will be returned.
restrict_to_addresses: Option<PreHashSet<Address>>,
},

/// get filtered events. Returns ExecutionQueryResponseItem::Events
Events(EventFilter),
}

/// Execution state query response item
pub enum ExecutionQueryResponseItem {
/// boolean value
Boolean(bool),
/// roll counts value
RollCount(u64),
/// amount value
Amount(Amount),
/// bytecode
Bytecode(Bytecode),
/// datastore value
DatastoreValue(Vec<u8>),
/// list of keys
KeyList(BTreeSet<Vec<u8>>),
/// deferred credits value
DeferredCredits(BTreeMap<Slot, Amount>),
/// execution status value
ExecutionStatus(ExecutionQueryExecutionStatus),
/// cycle infos value
CycleInfos(ExecutionQueryCycleInfos),
/// Events
Events(Vec<SCOutputEvent>),
}

/// Execution status of an operation or denunciation
pub enum ExecutionQueryExecutionStatus {
/// The operation or denunciation was executed recently with success
Leo-Besancon marked this conversation as resolved.
Show resolved Hide resolved
AlreadyExecutedWithSuccess,
/// The operation or denunciation was executed recently with failure
AlreadyExecutedWithFailure,
/// The operation or denunciation was not executed recently,
/// but might have been executed a longer time ago and forgotten.
/// Technically it means that the operation or denunciation
/// can still be executed unless it has expired.
ExecutableOrExpired,
}

/// Information about cycles
pub struct ExecutionQueryCycleInfos {
/// cycle number
pub cycle: u64,
/// whether the cycle is final
pub is_final: bool,
/// infos for each PoS-participating address among the ones that were asked
pub staker_infos: BTreeMap<Address, ExecutionQueryStakerInfo>,
}

/// Staker information for a given cycle
pub struct ExecutionQueryStakerInfo {
/// active roll count
pub active_rolls: u64,
/// production stats
pub production_stats: ProductionStats,
}

/// Execution info about an address
#[derive(Clone, Debug)]
pub struct ExecutionAddressInfo {
Expand Down
4 changes: 2 additions & 2 deletions massa-execution-worker/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,8 @@ impl ExecutionContext {
}

/// gets the datastore keys of an address if it exists in the speculative ledger, or returns None
pub fn get_keys(&self, address: &Address) -> Option<BTreeSet<Vec<u8>>> {
self.speculative_ledger.get_keys(address)
pub fn get_keys(&self, address: &Address, prefix: &[u8]) -> Option<BTreeSet<Vec<u8>>> {
self.speculative_ledger.get_keys(address, prefix)
}

/// gets the data from a datastore entry of an address if it exists in the speculative ledger, or returns None
Expand Down
Loading