Skip to content

Commit

Permalink
fix: handle VM InvalidCycles by generate a polyjuice system log
Browse files Browse the repository at this point in the history
  • Loading branch information
jjyr committed Jun 21, 2022
1 parent 74c3dc8 commit 4572d9e
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
39 changes: 36 additions & 3 deletions crates/generator/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use gw_common::{
},
H256,
};
use gw_config::BackendType;
use gw_store::{state::state_db::StateContext, transaction::StoreTransaction};
use gw_traits::{ChainView, CodeStore};
use gw_types::{
Expand All @@ -46,7 +47,7 @@ use ckb_vm::{DefaultMachineBuilder, SupportMachine};

#[cfg(not(has_asm))]
use ckb_vm::TraceMachine;
use gw_utils::script_log::GW_LOG_POLYJUICE_SYSTEM;
use gw_utils::script_log::{generate_polyjuice_system_log, GW_LOG_POLYJUICE_SYSTEM};
use tracing::instrument;

pub struct ApplyBlockArgs {
Expand Down Expand Up @@ -127,9 +128,12 @@ impl Generator {
max_cycles: u64,
backend: Backend,
) -> Result<RunResult, TransactionError> {
const INVALID_CYCLES_EXIT_CODE: i8 = -1;

let mut run_result = RunResult::default();
let used_cycles;
let exit_code;
let mut appended_log = None;

{
let t = Instant::now();
Expand Down Expand Up @@ -170,8 +174,34 @@ impl Generator {
let mut machine = TraceMachine::new(default_machine);

machine.load_program(&backend.generator, &[])?;
exit_code = machine.run()?;
used_cycles = machine.machine.cycles();
match machine.run() {
Ok(_exit_code) => {
exit_code = _exit_code;
used_cycles = machine.machine.cycles();
}
Err(ckb_vm::error::Error::InvalidCycles) => {
exit_code = INVALID_CYCLES_EXIT_CODE;
used_cycles = max_cycles;
if backend.backend_type == BackendType::Polyjuice {
// generate a system log for polyjuice tx
let polyjuice_tx =
crate::typed_transaction::types::PolyjuiceTx::new(raw_tx.to_owned());
let p = polyjuice_tx.parser().ok_or(TransactionError::NoCost)?;
let gas = p.gas();
appended_log = Some(generate_polyjuice_system_log(
raw_tx.to_id().unpack(),
gas,
gas,
Default::default(),
0,
));
}
}
Err(err) => {
// unexpected VM error
return Err(err.into());
}
}
log::debug!(
"[execute tx] VM machine_run time: {}ms, exit code: {} used_cycles: {}",
t.elapsed().as_millis(),
Expand All @@ -181,6 +211,9 @@ impl Generator {
}
run_result.used_cycles = used_cycles;
run_result.exit_code = exit_code;
if let Some(log) = appended_log {
run_result.write.logs.push(log);
}

Ok(run_result)
}
Expand Down
3 changes: 3 additions & 0 deletions crates/generator/src/typed_transaction/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ impl SimpleUDTTx {

pub struct PolyjuiceTx(RawL2Transaction);
impl PolyjuiceTx {
pub fn new(raw_tx: RawL2Transaction) -> Self {
Self(raw_tx)
}
pub fn parser(&self) -> Option<PolyjuiceParser> {
PolyjuiceParser::from_raw_l2_tx(&self.0)
}
Expand Down
20 changes: 20 additions & 0 deletions crates/utils/src/script_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,23 @@ pub fn parse_log(item: &LogItem) -> Result<GwLog> {
_ => Err(anyhow!("invalid log service flag: {}", service_flag)),
}
}

pub fn generate_polyjuice_system_log(
account_id: u32,
gas_used: u64,
cumulative_gas_used: u64,
created_address: [u8; 20],
status_code: u32,
) -> LogItem {
let service_flag: u8 = GW_LOG_POLYJUICE_SYSTEM;
let mut data = [0u8; 40];
data[0..8].copy_from_slice(&gas_used.to_le_bytes());
data[8..16].copy_from_slice(&cumulative_gas_used.to_le_bytes());
data[16..36].copy_from_slice(&created_address);
data[36..40].copy_from_slice(&status_code.to_le_bytes());
LogItem::new_builder()
.account_id(account_id.pack())
.service_flag(service_flag.into())
.data(data.pack())
.build()
}

0 comments on commit 4572d9e

Please sign in to comment.