Skip to content

Commit

Permalink
Add gathering of transfers in the node + prep work for ABIs (#4646)
Browse files Browse the repository at this point in the history
* Add 2 RPC endpoint with fake data

* Add stream grpc

* Add initial impl of execution traces for abi calls

* Link job on getting info with API.

* Add draft gather infos

* Cleanup execution trace

* Cargo clippy pass

* Update grpc public & stream api for execution traces

* Execution trace parameters & return value are now ser in json format

* Cargo clippy pass

* Fix execution trace unit tests

* Add serde_json as an optional dep

* Update proto files

* Fix finality filter and add placeholder for slot transfers endpoints

* Format and add a start of logic for compiling results

* Fix compil errors for basic feature

* Fix clippy issues

* Add JSON-RPC structure endpoint

* Flatten code for new abi get_slot_transfers

* Fix tu

* Fix logic in the stream and add it in the gRPC endpoint and Json-RPC

* Format and update massa-runtime

* Revert config change on the client

* Revert changes on initial rolls file

* Fix final broadcast by default on API.

* Fix initial rolls

* Add transfer when calling an SC

---------

Co-authored-by: sydhds <[email protected]>
  • Loading branch information
AurelienFT and sydhds authored Feb 22, 2024
1 parent f88b1c6 commit b75577f
Show file tree
Hide file tree
Showing 40 changed files with 1,602 additions and 57 deletions.
19 changes: 11 additions & 8 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ massa_versioning = { path = "./massa-versioning" }
massa_wallet = { path = "./massa-wallet" }

# Massa projects dependencies
massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "84678fb77cf6d06d85d55e2c20502908ff292e61" }
massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "845dc733a2f66b1b219a75d71f30c8e2a7e8a310" }
massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "25638b3b7d387afbca81afcb02bae1af03697f18" }
massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "32102813c05559c17d8ac1e1ee673802c2ba2ea8" }
peernet = { git = "https://github.com/massalabs/PeerNet", "rev" = "04b05ddd320fbe76cc858115af7b5fc28bdb8310" }

# Common dependencies
Expand Down
30 changes: 29 additions & 1 deletion massa-api-exports/src/execution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Copyright (c) 2022 MASSA LABS <[email protected]>

use massa_final_state::StateChanges;
use massa_models::{address::Address, amount::Amount, output_event::SCOutputEvent, slot::Slot};
use massa_models::{
address::Address, amount::Amount, operation::OperationId, output_event::SCOutputEvent,
slot::Slot,
};
use serde::{Deserialize, Serialize};
use std::{collections::VecDeque, fmt::Display};

Expand Down Expand Up @@ -85,3 +88,28 @@ pub struct ReadOnlyCall {
/// fee
pub fee: Option<Amount>,
}

/// Context of the transfer
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum TransferContext {
#[serde(rename = "operation_id")]
/// Transfer made in an operation
Operation(OperationId),
#[serde(rename = "asc_index")]
/// Transfer made in an asynchronous call
ASC(u64),
}

/// Structure defining a transfer
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Transfer {
/// The sender of the transfer
pub from: Address,
/// The receiver of the transfer
pub to: Address,
/// The amount of the transfer
pub amount: Amount,
/// Context
pub context: TransferContext,
}
1 change: 1 addition & 0 deletions massa-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[features]
test-exports = ["dep:massa_channel", "dep:massa_grpc", "massa_grpc/test-exports"]
execution-trace = ["massa_execution_exports/execution-trace"]

[dependencies]
massa_api_exports = { workspace = true }
Expand Down
5 changes: 5 additions & 0 deletions massa-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use jsonrpsee::proc_macros::rpc;
use jsonrpsee::server::middleware::HostFilterLayer;
use jsonrpsee::server::{BatchRequestConfig, ServerBuilder, ServerHandle};
use jsonrpsee::RpcModule;
use massa_api_exports::execution::Transfer;
use massa_api_exports::{
address::{AddressFilter, AddressInfo},
block::{BlockInfo, BlockSummary},
Expand Down Expand Up @@ -373,6 +374,10 @@ pub trait MassaRpc {
#[method(name = "get_addresses_bytecode")]
async fn get_addresses_bytecode(&self, args: Vec<AddressFilter>) -> RpcResult<Vec<Vec<u8>>>;

/// Get all the transfers for a slot
#[method(name = "get_slots_transfers")]
async fn get_slots_transfers(&self, arg: Vec<Slot>) -> RpcResult<Vec<Vec<Transfer>>>;

/// Adds operations to pool. Returns operations that were ok and sent to pool.
#[method(name = "send_operations")]
async fn send_operations(&self, arg: Vec<OperationInput>) -> RpcResult<Vec<OperationId>>;
Expand Down
6 changes: 5 additions & 1 deletion massa-api/src/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use massa_api_exports::{
datastore::{DatastoreEntryInput, DatastoreEntryOutput},
endorsement::EndorsementInfo,
error::ApiError,
execution::{ExecuteReadOnlyResponse, ReadOnlyBytecodeExecution, ReadOnlyCall},
execution::{ExecuteReadOnlyResponse, ReadOnlyBytecodeExecution, ReadOnlyCall, Transfer},
node::NodeStatus,
operation::{OperationInfo, OperationInput},
page::{PageRequest, PagedVec},
Expand Down Expand Up @@ -195,6 +195,10 @@ impl MassaRpcServer for API<Private> {
);
}

async fn get_slots_transfers(&self, _: Vec<Slot>) -> RpcResult<Vec<Vec<Transfer>>> {
crate::wrong_api::<Vec<Vec<Transfer>>>()
}

async fn get_status(&self) -> RpcResult<NodeStatus> {
crate::wrong_api::<NodeStatus>()
}
Expand Down
79 changes: 78 additions & 1 deletion massa-api/src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use massa_api_exports::{
datastore::{DatastoreEntryInput, DatastoreEntryOutput},
endorsement::EndorsementInfo,
error::ApiError,
execution::{ExecuteReadOnlyResponse, ReadOnlyBytecodeExecution, ReadOnlyCall, ReadOnlyResult},
execution::{
ExecuteReadOnlyResponse, ReadOnlyBytecodeExecution, ReadOnlyCall, ReadOnlyResult, Transfer,
},
node::NodeStatus,
operation::{OperationInfo, OperationInput},
page::{PageRequest, PagedVec},
Expand Down Expand Up @@ -121,6 +123,81 @@ impl MassaRpcServer for API<Public> {
crate::wrong_api::<()>()
}

#[cfg(feature = "execution-trace")]
async fn get_slots_transfers(&self, slots: Vec<Slot>) -> RpcResult<Vec<Vec<Transfer>>> {
use massa_api_exports::execution::TransferContext;
use std::str::FromStr;

let mut res: Vec<Vec<Transfer>> = Vec::with_capacity(slots.len());
for slot in slots {
let mut transfers = Vec::new();
let abi_calls = self
.0
.execution_controller
.get_slot_abi_call_stack(slot.clone().into());
if let Some(abi_calls) = abi_calls {
// flatten & filter transfer trace in asc_call_stacks

let abi_transfer_1 = "assembly_script_transfer_coins".to_string();
let abi_transfer_2 = "assembly_script_transfer_coins_for".to_string();
let abi_transfer_3 = "abi_transfer_coins".to_string();
let transfer_abi_names = vec![abi_transfer_1, abi_transfer_2, abi_transfer_3];
for (i, asc_call_stack) in abi_calls.asc_call_stacks.iter().enumerate() {
for abi_trace in asc_call_stack {
let only_transfer = abi_trace.flatten_filter(&transfer_abi_names);
for transfer in only_transfer {
let (t_from, t_to, t_amount) = transfer.parse_transfer();
transfers.push(Transfer {
from: Address::from_str(&t_from).unwrap(),
to: Address::from_str(&t_to).unwrap(),
amount: Amount::from_raw(t_amount),
context: TransferContext::ASC(i as u64),
});
}
}
}

for op_call_stack in abi_calls.operation_call_stacks {
let op_id = op_call_stack.0;
let op_call_stack = op_call_stack.1;
for abi_trace in op_call_stack {
let only_transfer = abi_trace.flatten_filter(&transfer_abi_names);
for transfer in only_transfer {
let (t_from, t_to, t_amount) = transfer.parse_transfer();
transfers.push(Transfer {
from: Address::from_str(&t_from).unwrap(),
to: Address::from_str(&t_to).unwrap(),
amount: Amount::from_raw(t_amount),
context: TransferContext::Operation(op_id),
});
}
}
}
}
let transfers_op: Vec<Transfer> = self
.0
.execution_controller
.get_transfers_for_slot(slot)
.unwrap_or_default()
.iter()
.map(|t| Transfer {
from: t.from,
to: t.to,
amount: t.amount,
context: TransferContext::Operation(t.op_id),
})
.collect();
transfers.extend(transfers_op);
res.push(transfers);
}
Ok(res)
}

#[cfg(not(feature = "execution-trace"))]
async fn get_slots_transfers(&self, _: Vec<Slot>) -> RpcResult<Vec<Vec<Transfer>>> {
RpcResult::Err(ApiError::BadRequest("feature execution-trace is not enabled".into()).into())
}

async fn execute_read_only_bytecode(
&self,
reqs: Vec<ReadOnlyBytecodeExecution>,
Expand Down
1 change: 1 addition & 0 deletions massa-execution-exports/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
[features]
gas_calibration = ["tempfile"]
test-exports = ["massa_models/test-exports", "tempfile", "mockall"]
execution-trace = ["massa-sc-runtime/execution-trace"]

[dependencies]
displaydoc = {workspace = true}
Expand Down
6 changes: 6 additions & 0 deletions massa-execution-exports/src/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

use crate::types::SlotExecutionOutput;

#[cfg(feature = "execution-trace")]
use crate::types::SlotAbiCallStack;

/// channels used by the execution worker
#[derive(Clone)]
pub struct ExecutionChannels {
/// Broadcast channel for new slot execution outputs
pub slot_execution_output_sender: tokio::sync::broadcast::Sender<SlotExecutionOutput>,
#[cfg(feature = "execution-trace")]
/// Broadcast channel for execution traces (abi call stacks, boolean true if the slot is finalized, false otherwise)
pub slot_execution_traces_sender: tokio::sync::broadcast::Sender<(SlotAbiCallStack, bool)>,
}
16 changes: 16 additions & 0 deletions massa-execution-exports/src/controller_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use crate::types::{
ExecutionBlockMetadata, ExecutionQueryRequest, ExecutionQueryResponse, ReadOnlyExecutionRequest,
};

use crate::ExecutionError;
use crate::{ExecutionAddressInfo, ReadOnlyExecutionOutput};
use massa_models::address::Address;
Expand All @@ -20,6 +21,9 @@ use massa_models::stats::ExecutionStats;
use std::collections::BTreeMap;
use std::collections::HashMap;

#[cfg(feature = "execution-trace")]
use crate::types::{AbiTrace, SlotAbiCallStack, Transfer};

#[cfg_attr(feature = "test-exports", mockall::automock)]
/// interface that communicates with the execution worker thread
pub trait ExecutionController: Send + Sync {
Expand Down Expand Up @@ -111,6 +115,18 @@ pub trait ExecutionController: Send + Sync {
/// Get execution statistics
fn get_stats(&self) -> ExecutionStats;

#[cfg(feature = "execution-trace")]
/// Get the abi call stack for a given operation id
fn get_operation_abi_call_stack(&self, operation_id: OperationId) -> Option<Vec<AbiTrace>>;

#[cfg(feature = "execution-trace")]
/// Get the abi call stack for a given slot
fn get_slot_abi_call_stack(&self, slot: Slot) -> Option<SlotAbiCallStack>;

#[cfg(feature = "execution-trace")]
/// Get the all transfers of MAS for a given slot
fn get_transfers_for_slot(&self, slot: Slot) -> Option<Vec<Transfer>>;

/// Returns a boxed clone of self.
/// Useful to allow cloning `Box<dyn ExecutionController>`.
fn clone_box(&self) -> Box<dyn ExecutionController>;
Expand Down
5 changes: 5 additions & 0 deletions massa-execution-exports/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,8 @@ pub use types::{

#[cfg(any(feature = "test-exports", feature = "gas_calibration"))]
pub mod test_exports;

#[cfg(feature = "execution-trace")]
pub use types::{
AbiTrace, SCRuntimeAbiTraceType, SCRuntimeAbiTraceValue, SlotAbiCallStack, Transfer,
};
6 changes: 6 additions & 0 deletions massa-execution-exports/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,10 @@ pub struct ExecutionConfig {
pub max_event_size: usize,
/// chain id
pub chain_id: u64,
/// whether slot execution traces broadcast is enabled
pub broadcast_traces_enabled: bool,
/// slot execution traces channel capacity
pub broadcast_slot_execution_traces_channel_capacity: usize,
/// Max execution traces slot to keep in trace history cache
pub max_execution_traces_slot_limit: usize,
}
3 changes: 3 additions & 0 deletions massa-execution-exports/src/test_exports/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ impl Default for ExecutionConfig {
max_function_length: 1000,
max_parameter_length: 1000,
chain_id: *CHAINID,
broadcast_traces_enabled: true,
broadcast_slot_execution_traces_channel_capacity: 5000,
max_execution_traces_slot_limit: 5000,
}
}
}
Loading

0 comments on commit b75577f

Please sign in to comment.