Skip to content

Commit

Permalink
feat: new hardfork with ckb vm
Browse files Browse the repository at this point in the history
  • Loading branch information
driftluo committed Oct 26, 2023
1 parent eea7af5 commit 2c4730c
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 28 deletions.
2 changes: 2 additions & 0 deletions common/config-parser/src/types/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ pub enum HardforkName {
/// If this hardfork is activated, chain validators can modify the EVM
/// contract size limit.
Andromeda = 0b1,
/// Enable CKB hardfork 2023 with new VM
Antlia = 0b10,
}

impl HardforkName {
Expand Down
12 changes: 8 additions & 4 deletions core/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,10 +408,7 @@ impl AxonExecutor {
fn config(&self) -> Config {
let mut evm_config = Config::london();
let create_contract_limit = {
let latest_hardfork_info = &**HARDFORK_INFO.load();
let enable_contract_limit_flag =
H256::from_low_u64_be((HardforkName::Andromeda as u64).to_be());
if latest_hardfork_info & &enable_contract_limit_flag == enable_contract_limit_flag {
if enable_hardfork(HardforkName::Andromeda) {
let handle = MetadataHandle::new(CURRENT_METADATA_ROOT.with(|r| *r.borrow()));
let consensus_config = handle.get_consensus_config().unwrap();
Some(consensus_config.max_contract_limit as usize)
Expand Down Expand Up @@ -515,6 +512,13 @@ pub fn is_transaction_call(action: &TransactionAction, addr: &H160) -> bool {
action == &TransactionAction::Call(*addr)
}

pub fn enable_hardfork(name: HardforkName) -> bool {
let latest_hardfork_info = &**HARDFORK_INFO.load();
let enable_flag = H256::from_low_u64_be((name as u64).to_be());

latest_hardfork_info & &enable_flag == enable_flag
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
11 changes: 9 additions & 2 deletions core/executor/src/precompiles/call_ckb_vm.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use common_config_parser::types::spec::HardforkName;
use ethers::contract::{EthAbiCodec, EthAbiType};
use ethers::{abi::AbiDecode, core::types::Bytes as EthBytes};
use evm::executor::stack::{PrecompileFailure, PrecompileOutput};
use evm::{Context, ExitError, ExitSucceed};

use protocol::traits::Interoperation;
use protocol::types::{Bytes, H160};
use protocol::types::{Bytes, CKBVMVersion, H160};

use core_interoperation::{cycle_to_gas, gas_to_cycle, InteroperationImpl};

use crate::precompiles::{axon_precompile_address, PrecompileContract};
use crate::system_contract::{image_cell::image_cell_abi::OutPoint, DataProvider};
use crate::{err, CURRENT_HEADER_CELL_ROOT};
use crate::{enable_hardfork, err, CURRENT_HEADER_CELL_ROOT};

#[derive(Default, Clone)]
pub struct CallCkbVM;
Expand All @@ -27,12 +28,18 @@ impl PrecompileContract for CallCkbVM {
) -> Result<(PrecompileOutput, u64), PrecompileFailure> {
if let Some(gas) = gas_limit {
let (cell_dep, args) = parse_input(input)?;
let version = if enable_hardfork(HardforkName::Antlia) {
CKBVMVersion::V2023
} else {
CKBVMVersion::V2021
};
let res = <InteroperationImpl as Interoperation>::call_ckb_vm(
Default::default(),
&DataProvider::new(CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow())),
cell_dep.into(),
&args,
gas_to_cycle(gas),
version,
)
.map_err(|e| err!(_, e.to_string()))?;

Expand Down
11 changes: 9 additions & 2 deletions core/executor/src/precompiles/verify_by_ckb_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use evm::executor::stack::{PrecompileFailure, PrecompileOutput};
use evm::{Context, ExitError, ExitSucceed};

use protocol::traits::Interoperation;
use protocol::types::{SignatureR, SignatureS, H160, H256};
use protocol::types::{CKBVMVersion, SignatureR, SignatureS, H160, H256};

use common_config_parser::types::spec::HardforkName;
use core_interoperation::{cycle_to_gas, gas_to_cycle, InteroperationImpl};

use crate::precompiles::{axon_precompile_address, call_ckb_vm::CellDep, PrecompileContract};
use crate::system_contract::{image_cell::image_cell_abi::OutPoint, DataProvider};
use crate::{err, CURRENT_HEADER_CELL_ROOT};
use crate::{enable_hardfork, err, CURRENT_HEADER_CELL_ROOT};

#[derive(Default, Clone)]
pub struct CkbVM;
Expand All @@ -28,6 +29,11 @@ impl PrecompileContract for CkbVM {
let payload = parse_input(input)?;

if let Some(gas) = gas_limit {
let version = if enable_hardfork(HardforkName::Antlia) {
CKBVMVersion::V2023
} else {
CKBVMVersion::V2021
};
let res = InteroperationImpl::verify_by_ckb_vm(
Default::default(),
DataProvider::new(CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow())),
Expand All @@ -43,6 +49,7 @@ impl PrecompileContract for CkbVM {
),
None,
gas_to_cycle(gas),
version,
)
.map_err(|e| err!(_, e.to_string()))?;

Expand Down
50 changes: 34 additions & 16 deletions core/interoperation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ use ckb_script::{TransactionScriptsVerifier, TxVerifyEnv};
use ckb_traits::CellDataProvider;
use ckb_types::core::{Cycle, HeaderBuilder, TransactionView};
use ckb_types::{packed, prelude::Pack};
use ckb_vm::machine::{asm::AsmCoreMachine, DefaultMachineBuilder, SupportMachine, VERSION1};
use ckb_vm::{Error as VMError, ISA_B, ISA_IMC, ISA_MOP};
use ckb_vm::machine::{
asm::AsmCoreMachine, DefaultMachineBuilder, SupportMachine, VERSION1, VERSION2,
};
use ckb_vm::{Error as VMError, ISA_A, ISA_B, ISA_IMC, ISA_MOP};

use protocol::traits::{CkbDataProvider, Context, Interoperation};
use protocol::types::{Bytes, CellDep, CellWithData, OutPoint, VMResp};
use protocol::types::{Bytes, CKBVMVersion, CellDep, CellWithData, OutPoint, VMResp};
use protocol::{Display, ProtocolError, ProtocolErrorKind, ProtocolResult};

use crate::utils::resolve_transaction;

const ISA: u8 = ISA_IMC | ISA_B | ISA_MOP;
const ISA_2021: u8 = ISA_IMC | ISA_B | ISA_MOP;
const ISA_2023: u8 = ISA_IMC | ISA_B | ISA_MOP | ISA_A;
const GAS_TO_CYCLE_COEF: u64 = 6_000;

// The following information is from CKB block [10976708](https://explorer.nervos.org/block/10976708)
Expand Down Expand Up @@ -59,14 +62,18 @@ impl Interoperation for InteroperationImpl {
data_cell_dep: CellDep,
args: &[Bytes],
max_cycles: u64,
version: CKBVMVersion,
) -> ProtocolResult<VMResp> {
let data_cell_dep: packed::CellDep = (&data_cell_dep).into();
let program = data_loader
.get_cell_data(&data_cell_dep.out_point())
.ok_or_else(|| InteroperationError::GetProgram((&data_cell_dep.out_point()).into()))?;
let mut vm = ckb_vm::machine::asm::AsmMachine::new(
DefaultMachineBuilder::new(AsmCoreMachine::new(ISA, VERSION1, max_cycles)).build(),
);
let core = match version {
CKBVMVersion::V2021 => AsmCoreMachine::new(ISA_2021, VERSION1, max_cycles),
CKBVMVersion::V2023 => AsmCoreMachine::new(ISA_2023, VERSION2, max_cycles),
};
let mut vm =
ckb_vm::machine::asm::AsmMachine::new(DefaultMachineBuilder::new(core).build());
let _ = vm
.load_program(&program, args)
.map_err(InteroperationError::CkbVM)?;
Expand All @@ -85,6 +92,7 @@ impl Interoperation for InteroperationImpl {
mocked_tx: &TransactionView,
dummy_input: Option<CellWithData>,
max_cycles: u64,
version: CKBVMVersion,
) -> ProtocolResult<Cycle> {
let rtx = Arc::new(resolve_transaction(&data_loader, mocked_tx, dummy_input)?);
log::debug!("[mempool]: Verify by ckb vm tx {:?}", rtx);
Expand All @@ -93,15 +101,25 @@ impl Interoperation for InteroperationImpl {
// syscalls3 are enabled. Due to only the hardfork field in consensus and the
// epoch field in tx_env is used, the provided arguments only need to fill these
// fields correctly.
let (ckb_spec, ckb2023_disabled_env) = (
Arc::new(Consensus::default()),
Arc::new(TxVerifyEnv::new_commit(
&HeaderBuilder::default()
.number(CKB2023_DISABLED_NUMBER.pack())
.epoch(CKB2023_DISABLED_EPOCH.pack())
.build(),
)),
);
let (ckb_spec, ckb2023_disabled_env) = {
let env = match version {
CKBVMVersion::V2021 => TxVerifyEnv::new_commit(
&HeaderBuilder::default()
.number(CKB2023_DISABLED_NUMBER.pack())
.epoch(CKB2023_DISABLED_EPOCH.pack())
.build(),
),
// TODO: Determine 2023 activation time
CKBVMVersion::V2023 => TxVerifyEnv::new_commit(
&HeaderBuilder::default()
.number(CKB2023_DISABLED_NUMBER.pack())
.epoch(CKB2023_DISABLED_EPOCH.pack())
.build(),
),
};

(Arc::new(Consensus::default()), Arc::new(env))
};

TransactionScriptsVerifier::new(rtx, data_loader, ckb_spec, ckb2023_disabled_env)
.verify(max_cycles)
Expand Down
15 changes: 12 additions & 3 deletions core/mempool/src/adapter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ use protocol::traits::{
TrustFeedback,
};
use protocol::types::{
recover_intact_pub_key, Backend, BatchSignedTxs, CellDepWithPubKey, Hash, MerkleRoot,
SignatureR, SignatureS, SignedTransaction, H160, U256,
recover_intact_pub_key, Backend, BatchSignedTxs, CKBVMVersion, CellDepWithPubKey, Hash,
MerkleRoot, SignatureR, SignatureS, SignedTransaction, H160, U256,
};
use protocol::{
async_trait, codec::ProtocolCodec, tokio, trie, Display, ProtocolError, ProtocolErrorKind,
ProtocolResult,
};

use common_apm_derive::trace_span;
use common_config_parser::types::spec::HardforkName;
use common_crypto::{Crypto, Secp256k1Recoverable};
use core_executor::{
is_call_system_script, AxonExecutorReadOnlyAdapter, DataProvider, MetadataHandle,
enable_hardfork, is_call_system_script, AxonExecutorReadOnlyAdapter, DataProvider,
MetadataHandle,
};
use core_interoperation::InteroperationImpl;

Expand Down Expand Up @@ -288,6 +290,11 @@ where
}

let root = self.executor_backend(ctx).await?.get_image_cell_root();
let version = if enable_hardfork(HardforkName::Antlia) {
CKBVMVersion::V2023
} else {
CKBVMVersion::V2021
};

// Verify interoperation signature
match signature.r[0] {
Expand All @@ -302,6 +309,7 @@ where
r.cell_dep,
&[r.pub_key, signature.s],
u64::MAX,
version,
)
.map_err(|e| AdapterError::VerifySignature(e.to_string()))?;
}
Expand All @@ -327,6 +335,7 @@ where
),
r.dummy_input(),
MAX_VERIFY_CKB_VM_CYCLES,
version,
)
.map_err(|e| AdapterError::VerifySignature(e.to_string()))?;
}
Expand Down
4 changes: 3 additions & 1 deletion protocol/src/traits/interoperation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider};
use ckb_types::core::{cell::CellProvider, Cycle, TransactionView};
use ckb_types::{packed, prelude::*};

use crate::types::{Bytes, CellDep, CellWithData, SignatureR, SignatureS, VMResp};
use crate::types::{Bytes, CKBVMVersion, CellDep, CellWithData, SignatureR, SignatureS, VMResp};
use crate::{lazy::DUMMY_INPUT_OUT_POINT, traits::Context, ProtocolResult};

pub const BYTE_SHANNONS: u64 = 100_000_000;
Expand Down Expand Up @@ -36,6 +36,7 @@ pub trait Interoperation: Sync + Send {
data_cell_dep: CellDep,
args: &[Bytes],
max_cycles: u64,
vesion: CKBVMVersion,
) -> ProtocolResult<VMResp>;

fn verify_by_ckb_vm<DL: CkbDataProvider + Sync + Send + 'static>(
Expand All @@ -44,6 +45,7 @@ pub trait Interoperation: Sync + Send {
mocked_tx: &TransactionView,
dummy_input: Option<CellWithData>,
max_cycles: u64,
vesion: CKBVMVersion,
) -> ProtocolResult<Cycle>;

/// The function construct the `TransactionView` payload required by
Expand Down
5 changes: 5 additions & 0 deletions protocol/src/types/interoperation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ impl SignatureR {
}
}

pub enum CKBVMVersion {
V2021,
V2023,
}

#[derive(RlpEncodable, RlpDecodable, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct CKBTxMockByRef {
pub cell_deps: Vec<CellDep>,
Expand Down

0 comments on commit 2c4730c

Please sign in to comment.