Skip to content

Commit

Permalink
Merge #4455
Browse files Browse the repository at this point in the history
4455: Read only call args (coins/fee) r=modship a=modship

* [x] document all added functions
* [x] try in sandbox /simulation/labnet
  * [ ] if part of node-launch, checked using the `resync_check` flag
* [x] unit tests on the added/changed features
  * [x] make tests compile
  * [x] make tests pass 
* [ ] add logs allowing easy debugging in case the changes caused problems
* [x] if the API has changed, update the API specification

TODO 

- [x] GRPC (proto)
- [x] massa-client
- [x] JSONRpc api doc

Co-authored-by: modship <[email protected]>
  • Loading branch information
bors[bot] and modship authored Oct 18, 2023
2 parents cfdb112 + a01e96c commit aff5f4a
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 23 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ 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" = "b45cccca3fb09aa2bbee08aade080127521e39b8"}
massa-sc-runtime = {git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "4883fe075afca4dd4b7346ed7dff2d506323f9c7"}
peernet = { git = "https://github.com/massalabs/PeerNet", "rev" = "1d10f55ea883e685691ff527c2466f733ba3e1b2" }
massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "7a5674743033b803af6e022738e3aa0ab7e39e33" }
massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "24defd4e319bbba72b4a3cf47078ac8695976c38" }
peernet = { git = "https://github.com/massalabs/PeerNet", "branch" = "main" }

# Common dependencies
transition = { git = "https://github.com/massalabs/transition.git", "rev" = "93fa3bf82f9f5ff421c78536879b7fd1b948ca75" }
substruct = { git = "https://github.com/massalabs/substruct", "rev" = "2fb3ae0dc9d913a0566ce6415eaa7a7ca1690fe1"}
substruct = { git = "https://github.com/massalabs/substruct", "rev" = "2fb3ae0dc9d913a0566ce6415eaa7a7ca1690fe1" }
machine = { git = "https://github.com/massalabs/machine", "rev" = "1736a01400aac54f69a81002862f8555b08caa9b" }
aes-gcm = "0.10"
anyhow = "1.0"
Expand Down
8 changes: 7 additions & 1 deletion massa-api-exports/src/execution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022 MASSA LABS <[email protected]>

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

Expand Down Expand Up @@ -63,6 +63,8 @@ pub struct ReadOnlyBytecodeExecution {
pub address: Option<Address>,
/// Operation datastore, optional
pub operation_datastore: Option<Vec<u8>>,
/// fee
pub fee: Option<Amount>,
/// whether to start execution from final or active state. Default false
#[serde(default)]
pub is_final: bool,
Expand All @@ -81,6 +83,10 @@ pub struct ReadOnlyCall {
pub parameter: Vec<u8>,
/// caller's address, optional
pub caller_address: Option<Address>,
/// coins
pub coins: Option<Amount>,
/// fee
pub fee: Option<Amount>,
/// whether to start execution from final or active state. Default false
#[serde(default)]
pub is_final: bool,
Expand Down
10 changes: 9 additions & 1 deletion massa-api/src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use massa_execution_exports::{
};
use massa_models::{
address::Address,
amount::Amount,
block::{Block, BlockGraphStatus},
block_id::BlockId,
clique::Clique,
Expand Down Expand Up @@ -133,6 +134,7 @@ impl MassaRpcServer for API<Public> {
bytecode,
operation_datastore,
is_final,
fee,
} in reqs
{
let address = if let Some(addr) = address {
Expand Down Expand Up @@ -186,6 +188,8 @@ impl MassaRpcServer for API<Public> {
operation_datastore: op_datastore,
}],
is_final,
coins: None,
fee,
};

// run
Expand Down Expand Up @@ -231,6 +235,8 @@ impl MassaRpcServer for API<Public> {
parameter,
caller_address,
is_final,
coins,
fee,
} in reqs
{
let caller_address = if let Some(addr) = caller_address {
Expand Down Expand Up @@ -269,12 +275,14 @@ impl MassaRpcServer for API<Public> {
},
ExecutionStackElement {
address: target_address,
coins: Default::default(),
coins: coins.unwrap_or(Amount::default()),
owned_addresses: vec![target_address],
operation_datastore: None, // should always be None
},
],
is_final,
coins,
fee,
};

// run
Expand Down
13 changes: 9 additions & 4 deletions massa-api/src/tests/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,8 @@ async fn execute_read_only_bytecode() {
Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap()
),
operation_datastore: None,
is_final: false
is_final: false,
fee: None
}]];
let response: Result<Vec<ExecuteReadOnlyResponse>, Error> = client
.request("execute_read_only_bytecode", params.clone())
Expand All @@ -621,7 +622,8 @@ async fn execute_read_only_bytecode() {
bytecode: "hi".as_bytes().to_vec(),
address: None,
operation_datastore: None,
is_final: false
is_final: false,
fee: None,
}]];
let response: Result<Vec<ExecuteReadOnlyResponse>, Error> = client
.request("execute_read_only_bytecode", params.clone())
Expand All @@ -634,7 +636,8 @@ async fn execute_read_only_bytecode() {
bytecode: "hi".as_bytes().to_vec(),
address: None,
operation_datastore: Some("hi".as_bytes().to_vec()),
is_final: false
is_final: false,
fee: None
}]];
let response: Result<Vec<ExecuteReadOnlyResponse>, Error> = client
.request("execute_read_only_bytecode", params.clone())
Expand Down Expand Up @@ -695,7 +698,9 @@ async fn execute_read_only_call() {
target_function: "hello".to_string(),
parameter: vec![],
caller_address: None,
is_final: false
is_final: false,
fee: None,
coins: None,
}]];
let response: Vec<ExecuteReadOnlyResponse> = client
.request("execute_read_only_call", params.clone())
Expand Down
21 changes: 17 additions & 4 deletions massa-client/src/cmds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use std::fmt::Write as _;
use std::fmt::{Debug, Display};
use std::net::IpAddr;
use std::path::PathBuf;
use std::str::FromStr;
use strum::{EnumMessage, EnumProperty, IntoEnumIterator};
use strum_macros::{Display, EnumIter, EnumString};

Expand Down Expand Up @@ -280,20 +281,20 @@ pub enum Command {
#[strum(
ascii_case_insensitive,
props(
args = "PathToBytecode MaxGas Address IsFinal",
args = "PathToBytecode MaxGas Address IsFinal Fee",
pwd_not_needed = "true"
),
message = "execute byte code, address is optional, is_final is optional. Nothing is really executed on chain"
message = "execute byte code, address is optional, is_final is optional, fee is optional. Nothing is really executed on chain"
)]
read_only_execute_smart_contract,

#[strum(
ascii_case_insensitive,
props(
args = "TargetAddress TargetFunction Parameter MaxGas SenderAddress IsFinal",
args = "TargetAddress TargetFunction Parameter MaxGas SenderAddress IsFinal Coins Fee",
pwd_not_needed = "true"
),
message = "call a smart contract function, sender address is optional, is_final is optional. Nothing is really executed on chain"
message = "call a smart contract function, sender address, is_final, coins and fee are optional. Nothing is really executed on chain"
)]
read_only_call,

Expand Down Expand Up @@ -1142,6 +1143,10 @@ impl Command {
} else {
false
};
let fee = parameters
.get(7)
.map(|fee| Amount::from_str(fee))
.transpose()?;
let bytecode = get_file_as_byte_vec(&path).await?;
match client
.public
Expand All @@ -1151,6 +1156,7 @@ impl Command {
address,
operation_datastore: None, // TODO - #3072
is_final,
fee,
})
.await
{
Expand All @@ -1177,6 +1183,11 @@ impl Command {
} else {
false
};
let coins = parameters.get(6).map(|c| Amount::from_str(c)).transpose()?;
let fee = parameters
.get(7)
.map(|fee| Amount::from_str(fee))
.transpose()?;
match client
.public
.execute_read_only_call(ReadOnlyCall {
Expand All @@ -1186,6 +1197,8 @@ impl Command {
parameter,
max_gas,
is_final,
coins,
fee,
})
.await
{
Expand Down
4 changes: 4 additions & 0 deletions massa-execution-exports/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ pub struct ReadOnlyExecutionRequest {
pub call_stack: Vec<ExecutionStackElement>,
/// Target of the request
pub target: ReadOnlyExecutionTarget,
/// Coins transferred to the target address during the call
pub coins: Option<Amount>,
/// Fee
pub fee: Option<Amount>,
/// execution start state
///
/// Whether to start execution from final or active state
Expand Down
33 changes: 29 additions & 4 deletions massa-execution-worker/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1420,8 +1420,17 @@ impl ExecutionState {
// run the interpreter according to the target type
let exec_response = match req.target {
ReadOnlyExecutionTarget::BytecodeExecution(bytecode) => {
// set the execution context
*context_guard!(self) = execution_context;
{
let mut context = context_guard!(self);
*context = execution_context;

let call_stack_addr = context.get_call_stack();

// transfer fee
if let (Some(fee), Some(addr)) = (req.fee, call_stack_addr.get(0)) {
context.transfer_coins(Some(*addr), None, fee, false)?;
}
}

// load the tmp module
let module = self
Expand Down Expand Up @@ -1451,8 +1460,24 @@ impl ExecutionState {
.unwrap_or_default()
.0;

// set the execution context
*context_guard!(self) = execution_context;
{
let mut context = context_guard!(self);
*context = execution_context;

let call_stack_addr = context.get_call_stack();

// transfer fee
if let (Some(fee), Some(addr)) = (req.fee, call_stack_addr.get(0)) {
context.transfer_coins(Some(*addr), None, fee, false)?;
}

// transfer coins
if let (Some(coins), Some(from), Some(to)) =
(req.coins, call_stack_addr.get(0), call_stack_addr.get(1))
{
context.transfer_coins(Some(*from), Some(*to), coins, false)?;
}
}

// load and execute the compiled module
// IMPORTANT: do not keep a lock here as `run_function` uses the `get_module` interface
Expand Down
4 changes: 4 additions & 0 deletions massa-execution-worker/src/tests/scenarios_mandatories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ mod tests {
include_bytes!("./wasm/event_test.wasm").to_vec(),
),
is_final: true,
coins: None,
fee: None,
})
.expect("readonly execution failed");

Expand All @@ -195,6 +197,8 @@ mod tests {
include_bytes!("./wasm/event_test.wasm").to_vec(),
),
is_final: false,
coins: None,
fee: None,
})
.expect("readonly execution failed");

Expand Down
15 changes: 15 additions & 0 deletions massa-grpc/src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use massa_execution_exports::{
ExecutionQueryRequest, ExecutionStackElement, ReadOnlyExecutionRequest, ReadOnlyExecutionTarget,
};
use massa_models::address::Address;
use massa_models::amount::Amount;
use massa_models::block::{Block, BlockGraphStatus};
use massa_models::block_id::BlockId;
use massa_models::config::CompactConfig;
Expand Down Expand Up @@ -114,6 +115,20 @@ pub(crate) fn execute_read_only_call(
call_stack,
target,
is_final: call.is_final,
coins: call
.coins
.map(|native_amount| {
Amount::from_mantissa_scale(native_amount.mantissa, native_amount.scale)
.map_err(|_| GrpcError::InvalidArgument("invalid amount".to_string()))
})
.transpose()?,
fee: call
.fee
.map(|native_amount| {
Amount::from_mantissa_scale(native_amount.mantissa, native_amount.scale)
.map_err(|_| GrpcError::InvalidArgument("invalid amount".to_string()))
})
.transpose()?,
};

let output = grpc
Expand Down
2 changes: 2 additions & 0 deletions massa-grpc/src/tests/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@ async fn execute_read_only_call() {
target_function: "function".to_string(),
parameter: vec![],
})),
coins: None,
fee: None,
};

let call = public_client
Expand Down
20 changes: 18 additions & 2 deletions massa-node/base_config/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2576,7 +2576,7 @@
},
"op_exec_status": {
"description": "true if the operation execution succeeded, false if failed, None means unknown",
"type" : "boolean"
"type": "boolean"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -2772,6 +2772,14 @@
"is_final": {
"description": "Whether to start execution from final or active state",
"type": "boolean"
},
"coins": {
"description": "Amount in coins, optional",
"type": "number"
},
"fee": {
"description": "Fee, optional",
"type": "number"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -2806,6 +2814,14 @@
"caller_address": {
"description": "Caller's address, optional",
"type": "string"
},
"coins": {
"description": "Amount in coins, optional",
"type": "number"
},
"fee": {
"description": "Fee, optional",
"type": "number"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -3320,4 +3336,4 @@
}
}
}
}
}

0 comments on commit aff5f4a

Please sign in to comment.