From 9c956e13472033ee4ad91d92b95fc54b5443dc1b Mon Sep 17 00:00:00 2001 From: green Date: Fri, 9 Dec 2022 00:54:39 +0000 Subject: [PATCH 1/3] Skip empty transaction --- src/interpreter/executors/debug.rs | 2 ++ src/interpreter/executors/main.rs | 17 +++++++++++-- src/state.rs | 2 ++ tests/flow.rs | 38 ++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/interpreter/executors/debug.rs b/src/interpreter/executors/debug.rs index b941b32a1f..98d6eca4eb 100644 --- a/src/interpreter/executors/debug.rs +++ b/src/interpreter/executors/debug.rs @@ -21,6 +21,8 @@ where ProgramState::Revert(w) => Ok(ProgramState::Revert(w)), + ProgramState::Skipped => Ok(ProgramState::Skipped), + ProgramState::RunProgram(_) => self.run_program(), ProgramState::VerifyPredicate(_) => unimplemented!(), diff --git a/src/interpreter/executors/main.rs b/src/interpreter/executors/main.rs index dfa26e0b9d..4323241a10 100644 --- a/src/interpreter/executors/main.rs +++ b/src/interpreter/executors/main.rs @@ -172,7 +172,7 @@ where let state = if let Some(create) = self.tx.as_create_mut() { Self::_deploy(create, &mut self.storage, self.initial_balances.clone(), &self.params)?; self.update_transaction_outputs()?; - ProgramState::Return(1) + ProgramState::Skipped } else { if self.transaction().inputs().iter().any(|input| { if let Input::Contract { contract_id, .. } = input { @@ -193,7 +193,20 @@ where // TODO set tree balance - let program = self.run_program(); + // `Interpreter` supports only `Create` and `Script` transactions. It is not `Create` -> + // it is `Script`. + let program = if !self + .transaction() + .as_script() + .expect("It should be `Script` transaction") + .script() + .is_empty() + { + self.run_program() + } else { + Ok(ProgramState::Skipped) + }; + let gas_used = self .transaction() .limit() diff --git a/src/state.rs b/src/state.rs index 7d29d53e56..677ecea188 100644 --- a/src/state.rs +++ b/src/state.rs @@ -74,6 +74,8 @@ pub enum ProgramState { ReturnData(Bytes32), /// The transaction execution resulted in a `RVRT` instruction. Revert(Word), + /// The transaction execution was skipped because of `Create` or empty `Script` transaction. + Skipped, #[cfg(feature = "debug")] /// A debug event was reached for the transaction. The VM is suspended. diff --git a/tests/flow.rs b/tests/flow.rs index 593c53819f..a7f82bacea 100644 --- a/tests/flow.rs +++ b/tests/flow.rs @@ -10,6 +10,44 @@ use rand::{rngs::StdRng, Rng, SeedableRng}; const SET_STATUS_REG: usize = 0x29; +#[test] +fn can_execute_empty_script_transaction() { + let mut client = MemoryClient::default(); + + let gas_price = 0; + let gas_limit = 1_000_000; + let maturity = 0; + let height = 0; + let params = ConsensusParameters::DEFAULT; + + let empty_script = vec![]; + + let tx = Transaction::script( + gas_price, + gas_limit, + maturity, + empty_script, + vec![], + vec![], + vec![], + vec![], + ) + .into_checked(height, ¶ms) + .expect("failed to generate a checked tx"); + + let receipts = client.transact(tx); + + // Expect the correct receipt + assert_eq!(receipts.len(), 1); + assert!(matches!( + receipts[0], + Receipt::ScriptResult { + result: ScriptExecutionResult::Success, + .. + } + )); +} + #[test] fn code_copy() { let rng = &mut StdRng::seed_from_u64(2322u64); From 382e05c657dcd143e59b2ea03ae5c647d08be4da Mon Sep 17 00:00:00 2001 From: green Date: Fri, 9 Dec 2022 01:06:57 +0000 Subject: [PATCH 2/3] Return `ProgramState::Return(1)` --- src/interpreter/executors/main.rs | 7 +++++-- tests/flow.rs | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/interpreter/executors/main.rs b/src/interpreter/executors/main.rs index 4323241a10..a669275029 100644 --- a/src/interpreter/executors/main.rs +++ b/src/interpreter/executors/main.rs @@ -172,7 +172,7 @@ where let state = if let Some(create) = self.tx.as_create_mut() { Self::_deploy(create, &mut self.storage, self.initial_balances.clone(), &self.params)?; self.update_transaction_outputs()?; - ProgramState::Skipped + ProgramState::Return(1) } else { if self.transaction().inputs().iter().any(|input| { if let Input::Contract { contract_id, .. } = input { @@ -204,7 +204,10 @@ where { self.run_program() } else { - Ok(ProgramState::Skipped) + // Return `1` as successful execution. + let return_val = 1; + self.ret(return_val)?; + Ok(ProgramState::Return(return_val)) }; let gas_used = self diff --git a/tests/flow.rs b/tests/flow.rs index a7f82bacea..2d2f6b2692 100644 --- a/tests/flow.rs +++ b/tests/flow.rs @@ -38,9 +38,10 @@ fn can_execute_empty_script_transaction() { let receipts = client.transact(tx); // Expect the correct receipt - assert_eq!(receipts.len(), 1); + assert_eq!(receipts.len(), 2); + assert!(matches!(receipts[0], Receipt::Return { val: 1, .. })); assert!(matches!( - receipts[0], + receipts[1], Receipt::ScriptResult { result: ScriptExecutionResult::Success, .. From 0c913ee1b6cf42e4d76c4f806b526161a8255c63 Mon Sep 17 00:00:00 2001 From: green Date: Fri, 9 Dec 2022 01:08:16 +0000 Subject: [PATCH 3/3] Remove `ProgramState::Skipped` --- src/interpreter/executors/debug.rs | 2 -- src/state.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/interpreter/executors/debug.rs b/src/interpreter/executors/debug.rs index 98d6eca4eb..b941b32a1f 100644 --- a/src/interpreter/executors/debug.rs +++ b/src/interpreter/executors/debug.rs @@ -21,8 +21,6 @@ where ProgramState::Revert(w) => Ok(ProgramState::Revert(w)), - ProgramState::Skipped => Ok(ProgramState::Skipped), - ProgramState::RunProgram(_) => self.run_program(), ProgramState::VerifyPredicate(_) => unimplemented!(), diff --git a/src/state.rs b/src/state.rs index 677ecea188..7d29d53e56 100644 --- a/src/state.rs +++ b/src/state.rs @@ -74,8 +74,6 @@ pub enum ProgramState { ReturnData(Bytes32), /// The transaction execution resulted in a `RVRT` instruction. Revert(Word), - /// The transaction execution was skipped because of `Create` or empty `Script` transaction. - Skipped, #[cfg(feature = "debug")] /// A debug event was reached for the transaction. The VM is suspended.