Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions binary_port/src/speculative_execution_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ impl SpeculativeExecutionResult {
}
}

pub fn error(&self) -> Option<&str> {
self.error.as_deref()
}

// This method is not intended to be used by third party crates.
#[doc(hidden)]
pub fn example() -> &'static Self {
Expand Down
4 changes: 4 additions & 0 deletions execution_engine/src/engine_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ impl ExecutionEngineV1 {
args,
authorization_keys,
phase,
is_speculative,
} = wasm_v1_request;
// NOTE to core engineers: it is intended for the EE to ONLY execute wasm targeting the
// casper v1 virtual machine. it should not handle native behavior, database / global state
Expand All @@ -94,6 +95,7 @@ impl ExecutionEngineV1 {
account_hash,
&authorization_keys,
&self.config().administrative_accounts,
is_speculative,
) {
Ok((runtime_footprint, entity_hash)) => (runtime_footprint, entity_hash),
Err(tce) => {
Expand Down Expand Up @@ -142,6 +144,7 @@ impl ExecutionEngineV1 {
args: RuntimeArgs,
authorization_keys: BTreeSet<AccountHash>,
phase: Phase,
is_speculative: bool,
) -> WasmV1Result
where
R: StateReader<Key, StoredValue, Error = GlobalStateError>,
Expand All @@ -161,6 +164,7 @@ impl ExecutionEngineV1 {
account_hash,
&authorization_keys,
&self.config().administrative_accounts,
is_speculative,
) {
Ok((addressable_entity, entity_hash)) => (addressable_entity, entity_hash),
Err(tce) => {
Expand Down
19 changes: 19 additions & 0 deletions execution_engine/src/engine_state/wasm_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ pub struct WasmV1Request {
pub authorization_keys: BTreeSet<AccountHash>,
/// Execution phase.
pub phase: Phase,
/// Is speculative execution
pub is_speculative: bool,
}

impl WasmV1Request {
Expand Down Expand Up @@ -414,6 +416,7 @@ impl WasmV1Request {
entry_point: executable_info.entry_point().clone(),
args: executable_info.args().clone(),
phase: executable_info.phase(),
is_speculative: false,
}
}

Expand All @@ -437,6 +440,22 @@ impl WasmV1Request {
))
}

/// Creates a new request from a transaction for use as the session code in speculative
/// execution flows.
pub fn new_session_speculative(
block_info: BlockInfo,
gas_limit: Gas,
session_input_data: &SessionInputData,
) -> Result<Self, InvalidRequest> {
match Self::new_session(block_info, gas_limit, session_input_data) {
Ok(mut request) => {
request.is_speculative = true;
Ok(request)
}
Err(err) => Err(err),
}
}

/// Creates a new request from a transaction for use as custom payment.
pub fn new_custom_payment(
block_info: BlockInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct ExecuteRequestBuilder {
session_entry_point: String,
session_args: RuntimeArgs,
authorization_keys: BTreeSet<AccountHash>,
is_speculative: bool,
}

const DEFAULT_GAS_LIMIT: u64 = 5_000_u64 * 10u64.pow(9);
Expand Down Expand Up @@ -130,6 +131,7 @@ impl ExecuteRequestBuilder {
session_entry_point: session.entry_point,
session_args: session.args,
authorization_keys,
is_speculative: false,
}
}

Expand Down Expand Up @@ -206,6 +208,7 @@ impl ExecuteRequestBuilder {
session_entry_point: session.entry_point,
session_args: session.args,
authorization_keys,
is_speculative: false,
}
}

Expand Down Expand Up @@ -476,6 +479,7 @@ impl ExecuteRequestBuilder {
session_entry_point,
session_args,
authorization_keys,
is_speculative,
} = self;

let block_info = BlockInfo::new(
Expand All @@ -495,6 +499,7 @@ impl ExecuteRequestBuilder {
args: payment_args,
authorization_keys: authorization_keys.clone(),
phase: Phase::Payment,
is_speculative,
});

let session = WasmV1Request {
Expand All @@ -507,6 +512,7 @@ impl ExecuteRequestBuilder {
args: session_args,
authorization_keys,
phase: Phase::Session,
is_speculative,
};

ExecuteRequest {
Expand Down
1 change: 1 addition & 0 deletions executor/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ impl ExecutorV2 {
args,
authorization_keys,
phase,
false,
)
};

Expand Down
12 changes: 2 additions & 10 deletions node/src/components/binary_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ where
match req {
Command::TryAcceptTransaction { transaction } => {
metrics.binary_port_try_accept_transaction_count.inc();
try_accept_transaction(effect_builder, transaction, false).await
try_accept_transaction(effect_builder, transaction).await
}
Command::TrySpeculativeExec { transaction } => {
metrics.binary_port_try_speculative_exec_count.inc();
Expand All @@ -220,10 +220,6 @@ where
);
return BinaryResponse::new_error(ErrorCode::FunctionDisabled);
}
let response = try_accept_transaction(effect_builder, transaction.clone(), true).await;
if !response.is_success() {
return response;
}
try_speculative_execution(effect_builder, transaction).await
}
Command::Get(get_req) => {
Expand Down Expand Up @@ -1343,13 +1339,12 @@ where
async fn try_accept_transaction<REv>(
effect_builder: EffectBuilder<REv>,
transaction: Transaction,
is_speculative: bool,
) -> BinaryResponse
where
REv: From<AcceptTransactionRequest>,
{
effect_builder
.try_accept_transaction(transaction, is_speculative)
.try_accept_transaction(transaction)
.await
.map_or_else(
|err| BinaryResponse::new_error(err.into()),
Expand Down Expand Up @@ -1384,9 +1379,6 @@ where
SpeculativeExecutionResult::WasmV1(spec_exec_result) => {
BinaryResponse::from_value(spec_exec_result)
}
SpeculativeExecutionResult::ReceivedV1Transaction => {
BinaryResponse::new_error(ErrorCode::ReceivedV1Transaction)
}
}
}

Expand Down
48 changes: 39 additions & 9 deletions node/src/components/contract_runtime/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use casper_types::{
system::handle_payment::ARG_AMOUNT,
BlockHash, BlockHeader, BlockTime, BlockV2, CLValue, Chainspec, ChecksumRegistry, Digest,
EntityAddr, EraEndV2, EraId, FeeHandling, Gas, InvalidTransaction, InvalidTransactionV1, Key,
ProtocolVersion, PublicKey, RefundHandling, Transaction, TransactionEntryPoint,
ProtocolVersion, PublicKey, RefundHandling, TimeDiff, Transaction, TransactionEntryPoint,
AUCTION_LANE_ID, MINT_LANE_ID, U512,
};

Expand Down Expand Up @@ -1353,6 +1353,11 @@ where
return SpeculativeExecutionResult::invalid_transaction(error);
}
let transaction = maybe_transaction.unwrap();
if let Err(error) =
transaction.is_config_compliant(chainspec, TimeDiff::ZERO, transaction.timestamp())
{
return SpeculativeExecutionResult::invalid_transaction(error);
}
let state_root_hash = block_header.state_root_hash();
let parent_block_hash = block_header.block_hash();
let block_height = block_header.height();
Expand Down Expand Up @@ -1406,20 +1411,45 @@ where
execution_engine_v1.config().protocol_version(),
);
let session_input_data = transaction.to_session_input_data();
let wasm_v1_result =
match WasmV1Request::new_session(block_info, gas_limit, &session_input_data) {
Ok(wasm_v1_request) => {
execution_engine_v1.execute(state_provider, wasm_v1_request)
}
Err(error) => WasmV1Result::invalid_executable_item(gas_limit, error),
};
let wasm_v1_result = match WasmV1Request::new_session_speculative(
block_info,
gas_limit,
&session_input_data,
) {
Ok(wasm_v1_request) => execution_engine_v1.execute(state_provider, wasm_v1_request),
Err(error) => WasmV1Result::invalid_executable_item(gas_limit, error),
};
SpeculativeExecutionResult::WasmV1(Box::new(utils::spec_exec_from_wasm_v1_result(
wasm_v1_result,
block_header.block_hash(),
)))
}
} else if transaction.is_wasm() {
let block_info = BlockInfo::new(
*state_root_hash,
block_time.into(),
parent_block_hash,
block_height,
execution_engine_v1.config().protocol_version(),
);
let session_input_data = transaction.to_session_input_data();
let wasm_v1_result = match WasmV1Request::new_session_speculative(
block_info,
gas_limit,
&session_input_data,
) {
Ok(wasm_v1_request) => execution_engine_v1.execute(state_provider, wasm_v1_request),
Err(error) => WasmV1Result::invalid_executable_item(gas_limit, error),
};
SpeculativeExecutionResult::WasmV1(Box::new(utils::spec_exec_from_wasm_v1_result(
wasm_v1_result,
block_header.block_hash(),
)))
} else {
SpeculativeExecutionResult::ReceivedV1Transaction
// TODO: placeholder error
SpeculativeExecutionResult::InvalidTransaction(InvalidTransaction::V1(
InvalidTransactionV1::CannotCalculateFieldsHash,
))
}
}

Expand Down
1 change: 0 additions & 1 deletion node/src/components/contract_runtime/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,6 @@ pub struct BlockAndExecutionArtifacts {
pub enum SpeculativeExecutionResult {
InvalidTransaction(InvalidTransaction),
WasmV1(Box<casper_binary_port::SpeculativeExecutionResult>),
ReceivedV1Transaction,
}

impl SpeculativeExecutionResult {
Expand Down
2 changes: 1 addition & 1 deletion node/src/components/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ where
Source::PeerGossiped(peer) | Source::Peer(peer) => {
self.got_from_peer(effect_builder, peer, item)
}
Source::Client | Source::SpeculativeExec | Source::Ourself => Effects::new(),
Source::Client | Source::Ourself => Effects::new(),
},
Event::GotInvalidRemotely { .. } => Effects::new(),
Event::AbsentRemotely { id, peer } => {
Expand Down
6 changes: 1 addition & 5 deletions node/src/components/fetcher/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,8 @@ impl ReactorTrait for Reactor {
}
Event::AcceptTransactionRequest(AcceptTransactionRequest {
transaction,
is_speculative,
responder,
}) => {
assert!(!is_speculative);
let event = transaction_acceptor::Event::Accept {
transaction,
source: Source::Client,
Expand Down Expand Up @@ -383,9 +381,7 @@ impl NetworkedReactor for Reactor {
fn announce_transaction_received(
txn: Transaction,
) -> impl FnOnce(EffectBuilder<Event>) -> Effects<Event> {
|effect_builder: EffectBuilder<Event>| {
effect_builder.try_accept_transaction(txn, false).ignore()
}
|effect_builder: EffectBuilder<Event>| effect_builder.try_accept_transaction(txn).ignore()
}

type FetchedTransactionResult = Arc<Mutex<(bool, Option<FetchResult<Transaction>>)>>;
Expand Down
6 changes: 1 addition & 5 deletions node/src/components/gossiper/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,8 @@ impl reactor::Reactor for Reactor {
),
Event::AcceptTransactionRequest(AcceptTransactionRequest {
transaction,
is_speculative,
responder,
}) => {
assert!(!is_speculative);
let event = transaction_acceptor::Event::Accept {
transaction,
source: Source::Client,
Expand Down Expand Up @@ -336,9 +334,7 @@ fn announce_transaction_received(
transaction: &Transaction,
) -> impl FnOnce(EffectBuilder<Event>) -> Effects<Event> {
let txn = transaction.clone();
|effect_builder: EffectBuilder<Event>| {
effect_builder.try_accept_transaction(txn, false).ignore()
}
|effect_builder: EffectBuilder<Event>| effect_builder.try_accept_transaction(txn).ignore()
}

async fn run_gossip(rng: &mut TestRng, network_size: usize, txn_count: usize) {
Expand Down
10 changes: 0 additions & 10 deletions node/src/components/transaction_acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,16 +856,6 @@ impl TransactionAcceptor {
return self.reject_transaction(effect_builder, *event_metadata, error);
}

// If this has been received from the speculative exec server, we just want to call the
// responder and finish. Otherwise store the transaction and announce it if required.
if let Source::SpeculativeExec = event_metadata.source {
if let Some(responder) = event_metadata.maybe_responder {
return responder.respond(Ok(())).ignore();
}
error!("speculative exec source should always have a responder");
return Effects::new();
}

effect_builder
.put_transaction_to_storage(event_metadata.transaction.clone())
.event(move |is_new| Event::PutToStorageResult {
Expand Down
2 changes: 0 additions & 2 deletions node/src/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,15 +857,13 @@ impl<REv> EffectBuilder<REv> {
pub(crate) async fn try_accept_transaction(
self,
transaction: Transaction,
is_speculative: bool,
) -> Result<(), transaction_acceptor::Error>
where
REv: From<AcceptTransactionRequest>,
{
self.make_request(
|responder| AcceptTransactionRequest {
transaction,
is_speculative,
responder,
},
QueueKind::Api,
Expand Down
8 changes: 1 addition & 7 deletions node/src/effect/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1229,17 +1229,11 @@ impl Display for SetNodeStopRequest {
#[derive(DataSize, Debug, Serialize)]
pub(crate) struct AcceptTransactionRequest {
pub(crate) transaction: Transaction,
pub(crate) is_speculative: bool,
pub(crate) responder: Responder<Result<(), transaction_acceptor::Error>>,
}

impl Display for AcceptTransactionRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"accept transaction {} is_speculative: {}",
self.transaction.hash(),
self.is_speculative
)
write!(f, "accept transaction {}", self.transaction.hash(),)
}
}
Loading