diff --git a/core/executor/src/precompiles/mod.rs b/core/executor/src/precompiles/mod.rs index c593ca7d8..3e6fa09c3 100644 --- a/core/executor/src/precompiles/mod.rs +++ b/core/executor/src/precompiles/mod.rs @@ -16,7 +16,6 @@ mod sha256; #[cfg(test)] mod tests; -mod verify_by_ckb_vm; use std::collections::BTreeMap; diff --git a/core/executor/src/precompiles/verify_by_ckb_vm.rs b/core/executor/src/precompiles/verify_by_ckb_vm.rs deleted file mode 100644 index d2ccc31ca..000000000 --- a/core/executor/src/precompiles/verify_by_ckb_vm.rs +++ /dev/null @@ -1,140 +0,0 @@ -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::{SignatureR, SignatureS, H160, H256}; - -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}; - -#[derive(Default, Clone)] -pub struct CkbVM; - -impl PrecompileContract for CkbVM { - const ADDRESS: H160 = axon_precompile_address(0x05); - const MIN_GAS: u64 = 500; - - fn exec_fn( - input: &[u8], - gas_limit: Option, - _context: &Context, - _is_static: bool, - ) -> Result<(PrecompileOutput, u64), PrecompileFailure> { - let payload = parse_input(input)?; - - if let Some(gas) = gas_limit { - let res = InteroperationImpl::verify_by_ckb_vm( - Default::default(), - DataProvider::new(CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow())), - &InteroperationImpl::dummy_transaction( - SignatureR::new_by_ref( - payload.cell_deps(), - payload.header_deps(), - payload.inputs(), - Default::default(), - ), - SignatureS::new(payload.witnesses()), - None, - ), - None, - gas_to_cycle(gas), - ) - .map_err(|e| err!(_, e.to_string()))?; - - return Ok(( - PrecompileOutput { - exit_status: ExitSucceed::Returned, - output: res.to_le_bytes().to_vec(), - }, - cycle_to_gas(res).max(Self::MIN_GAS), - )); - } - - err!() - } - - fn gas_cost(_input: &[u8]) -> u64 { - unreachable!() - } -} - -fn parse_input(input: &[u8]) -> Result { - ::decode(input).map_err(|_| err!(_, "decode input")) -} - -#[derive(EthAbiType, EthAbiCodec, Clone, Default, Debug, PartialEq, Eq)] -pub struct VerifyByCkbPayload { - pub cell_deps: Vec, - pub header_deps: Vec<[u8; 32]>, - pub inputs: Vec, - pub witnesses: Vec, -} - -impl VerifyByCkbPayload { - pub fn cell_deps(&self) -> Vec { - self.cell_deps - .iter() - .map(|c| protocol::types::CellDep { - tx_hash: c.out_point.tx_hash.into(), - index: c.out_point.index, - dep_type: c.dep_type, - }) - .collect() - } - - pub fn header_deps(&self) -> Vec { - self.header_deps.iter().map(Into::into).collect() - } - - pub fn inputs(&self) -> Vec { - self.inputs - .iter() - .map(|i| protocol::types::OutPoint { - tx_hash: i.tx_hash.into(), - index: i.index, - }) - .collect() - } - - pub fn witnesses(&self) -> Vec { - self.witnesses.clone().into_iter().map(Into::into).collect() - } -} - -#[derive(EthAbiType, EthAbiCodec, Clone, Default, Debug, PartialEq, Eq)] -pub struct WitnessArgs { - pub lock: EthBytes, - pub input_type: EthBytes, - pub output_type: EthBytes, -} - -impl From for protocol::types::Witness { - fn from(w: WitnessArgs) -> Self { - let lock = if w.lock.is_empty() { - None - } else { - Some(w.lock.0) - }; - let input_type = if w.input_type.is_empty() { - None - } else { - Some(w.input_type.0) - }; - let output_type = if w.output_type.is_empty() { - None - } else { - Some(w.output_type.0) - }; - - protocol::types::Witness { - lock, - input_type, - output_type, - } - } -} diff --git a/core/interoperation/src/lib.rs b/core/interoperation/src/lib.rs index fe3256327..826726821 100644 --- a/core/interoperation/src/lib.rs +++ b/core/interoperation/src/lib.rs @@ -1,29 +1,17 @@ -pub mod utils; +use std::error::Error; -use std::{error::Error, sync::Arc}; - -use ckb_chain_spec::consensus::Consensus; -use ckb_script::{TransactionScriptsVerifier, TxVerifyEnv}; use ckb_traits::CellDataProvider; -use ckb_types::core::{Cycle, HeaderBuilder, TransactionView}; -use ckb_types::{packed, prelude::Pack}; +use ckb_types::packed; use ckb_vm::machine::{asm::AsmCoreMachine, DefaultMachineBuilder, SupportMachine, VERSION1}; use ckb_vm::{Error as VMError, ISA_B, ISA_IMC, ISA_MOP}; -use protocol::traits::{CkbDataProvider, Context, Interoperation}; -use protocol::types::{Bytes, CellDep, CellWithData, OutPoint, VMResp}; +use protocol::traits::{Context, Interoperation}; +use protocol::types::{Bytes, CellDep, OutPoint, VMResp}; use protocol::{Display, ProtocolError, ProtocolErrorKind, ProtocolResult}; -use crate::utils::resolve_transaction; - const ISA: u8 = ISA_IMC | ISA_B | ISA_MOP; const GAS_TO_CYCLE_COEF: u64 = 6_000; -// The following information is from CKB block [10976708](https://explorer.nervos.org/block/10976708) -// which is CKB2023 disabled. -const CKB2023_DISABLED_NUMBER: u64 = 10_976_708; -const CKB2023_DISABLED_EPOCH: u64 = 0x53c007f0020c8; - pub const fn gas_to_cycle(gas: u64) -> u64 { gas * GAS_TO_CYCLE_COEF } @@ -76,37 +64,6 @@ impl Interoperation for InteroperationImpl { cycles: vm.machine.cycles(), }) } - - /// Todo: After CKB2023 is enabled, a hardfork is needed to support the new - /// VM version and syscalls. - fn verify_by_ckb_vm( - _ctx: Context, - data_loader: DL, - mocked_tx: &TransactionView, - dummy_input: Option, - max_cycles: u64, - ) -> ProtocolResult { - let rtx = Arc::new(resolve_transaction(&data_loader, mocked_tx, dummy_input)?); - log::debug!("[mempool]: Verify by ckb vm tx {:?}", rtx); - - // The consensus and tx_env arguments are used for judge if the VM version2 and - // 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(), - )), - ); - - TransactionScriptsVerifier::new(rtx, data_loader, ckb_spec, ckb2023_disabled_env) - .verify(max_cycles) - .map_err(|e| InteroperationError::Ckb(e).into()) - } } #[derive(Debug, Display)] diff --git a/core/interoperation/src/utils.rs b/core/interoperation/src/utils.rs deleted file mode 100644 index 557f3c3a3..000000000 --- a/core/interoperation/src/utils.rs +++ /dev/null @@ -1,82 +0,0 @@ -use ckb_types::core::cell::{CellMeta, CellProvider, CellStatus, ResolvedTransaction}; -use ckb_types::core::{DepType, TransactionView}; -use ckb_types::{packed, prelude::*}; - -use protocol::{lazy::DUMMY_INPUT_OUT_POINT, types::CellWithData, ProtocolResult}; - -use crate::InteroperationError; - -pub fn resolve_transaction( - cell_loader: &CL, - tx: &TransactionView, - dummy_input: Option, -) -> ProtocolResult { - let resolve_cell = |out_point: &packed::OutPoint| -> ProtocolResult { - match cell_loader.cell(out_point, true) { - CellStatus::Live(meta) => Ok(meta), - _ => Err(InteroperationError::GetUnknownCell(out_point.into()).into()), - } - }; - - let (mut resolved_inputs, mut resolved_cell_deps, mut resolved_dep_groups) = ( - Vec::with_capacity(tx.inputs().len()), - Vec::with_capacity(tx.cell_deps().len()), - Vec::with_capacity(tx.cell_deps().len()), - ); - - for outpoint in tx.input_pts_iter() { - if is_dummy_out_point(&outpoint) { - if let Some(ref cell) = dummy_input { - resolved_inputs.push(cell.into()); - } else { - return Err(InteroperationError::InvalidDummyInput.into()); - } - } else { - resolved_inputs.push(resolve_cell(&outpoint)?); - } - } - - for cell_dep in tx.cell_deps_iter() { - if cell_dep.dep_type() == DepType::DepGroup.into() { - let dep_group = resolve_cell(&cell_dep.out_point())?; - let data = dep_group.mem_cell_data.as_ref().unwrap(); - let sub_out_points = - parse_dep_group_data(data).map_err(InteroperationError::InvalidDepGroup)?; - - for sub_out_point in sub_out_points.into_iter() { - resolved_cell_deps.push(resolve_cell(&sub_out_point)?); - } - resolved_dep_groups.push(dep_group); - } else { - resolved_cell_deps.push(resolve_cell(&cell_dep.out_point())?); - } - } - - Ok(ResolvedTransaction { - transaction: tx.clone(), - resolved_cell_deps, - resolved_inputs, - resolved_dep_groups, - }) -} - -pub fn parse_dep_group_data(slice: &[u8]) -> Result { - if slice.is_empty() { - Err("data is empty".to_owned()) - } else { - match packed::OutPointVec::from_slice(slice) { - Ok(v) => { - if v.is_empty() { - Err("dep group is empty".to_owned()) - } else { - Ok(v) - } - } - Err(err) => Err(err.to_string()), - } - } -} - -pub fn is_dummy_out_point(out_point: &packed::OutPoint) -> bool { - *out_point == *DUMMY_INPUT_OUT_POINT -} diff --git a/core/mempool/src/adapter/mod.rs b/core/mempool/src/adapter/mod.rs index f701e7466..26c871815 100644 --- a/core/mempool/src/adapter/mod.rs +++ b/core/mempool/src/adapter/mod.rs @@ -17,7 +17,7 @@ use protocol::traits::{ }; use protocol::types::{ recover_intact_pub_key, Backend, BatchSignedTxs, CellDepWithPubKey, Hash, MerkleRoot, - SignatureR, SignatureS, SignedTransaction, H160, U256, + SignedTransaction, H160, U256, }; use protocol::{ async_trait, codec::ProtocolCodec, tokio, trie, Display, ProtocolError, ProtocolErrorKind, @@ -35,8 +35,6 @@ use crate::adapter::message::{MsgPullTxs, END_GOSSIP_NEW_TXS, RPC_PULL_TXS}; use crate::context::TxContext; use crate::MemPoolError; -const MAX_VERIFY_CKB_VM_CYCLES: u64 = 50_000_000; - struct IntervalTxsBroadcaster; impl IntervalTxsBroadcaster { @@ -289,48 +287,17 @@ where let root = self.executor_backend(ctx).await?.get_image_cell_root(); - // Verify interoperation signature - match signature.r[0] { - 0u8 => { - // Call CKB-VM mode - let r = rlp::decode::(&signature.r[1..]) - .map_err(AdapterError::Rlp)?; - - InteroperationImpl::call_ckb_vm( - Default::default(), - &DataProvider::new(root), - r.cell_dep, - &[r.pub_key, signature.s], - u64::MAX, - ) - .map_err(|e| AdapterError::VerifySignature(e.to_string()))?; - } - _ => { - // Verify by mock transaction mode - let r = SignatureR::decode(&signature.r)?; - let s = SignatureS::decode(&signature.s)?; - - if r.inputs_len() != s.witnesses.len() { - return Err(AdapterError::VerifySignature( - "signature item mismatch".to_string(), - ) - .into()); - } + // Verify interoperation signature call CKB-VM mode + let r = rlp::decode::(&signature.r[1..]).map_err(AdapterError::Rlp)?; + InteroperationImpl::call_ckb_vm( + Default::default(), + &DataProvider::new(root), + r.cell_dep, + &[r.pub_key, signature.s], + u64::MAX, + ) + .map_err(|e| AdapterError::VerifySignature(e.to_string()))?; - InteroperationImpl::verify_by_ckb_vm( - Default::default(), - DataProvider::new(root), - &InteroperationImpl::dummy_transaction( - r.clone(), - s, - Some(stx.transaction.signature_hash(true).0), - ), - r.dummy_input(), - MAX_VERIFY_CKB_VM_CYCLES, - ) - .map_err(|e| AdapterError::VerifySignature(e.to_string()))?; - } - } Ok(()) } diff --git a/core/mempool/src/lib.rs b/core/mempool/src/lib.rs index b87386d8d..819056e9a 100644 --- a/core/mempool/src/lib.rs +++ b/core/mempool/src/lib.rs @@ -20,9 +20,7 @@ use futures::future::try_join_all; use common_apm::Instant; use protocol::traits::{Context, MemPool, MemPoolAdapter}; -use protocol::types::{ - AddressSource, BlockNumber, Hash, PackedTxHashes, SignedTransaction, H160, H256, U256, -}; +use protocol::types::{BlockNumber, Hash, PackedTxHashes, SignedTransaction, H160, H256, U256}; use protocol::{async_trait, tokio, Display, ProtocolError, ProtocolErrorKind, ProtocolResult}; use core_executor::is_call_system_script; @@ -451,12 +449,6 @@ pub enum MemPoolError { #[display(fmt = "Encode transaction to JSON failed")] EncodeJson, - #[display(fmt = "Invalid address source {:?}", _0)] - InvalidAddressSource(AddressSource), - - #[display(fmt = "Invalid dummy input")] - InvalidDummyInput, - #[display(fmt = "Invalid sender, expect: {:?}, get: {:?}", expect, actual)] InvalidSender { expect: H160, actual: H160 }, } diff --git a/protocol/src/codec/transaction.rs b/protocol/src/codec/transaction.rs index 5b5537d1b..9659b5a5d 100644 --- a/protocol/src/codec/transaction.rs +++ b/protocol/src/codec/transaction.rs @@ -370,10 +370,7 @@ mod tests { use common_crypto::secp256k1_recover; use crate::codec::hex_decode; - use crate::types::{ - AddressSource, Bytes, CKBTxMockByRefAndOneInput, CellDep, CellWithData, Public, Script, - SignatureR, SignatureS, Witness, H160, H256, U256, - }; + use crate::types::{Public, SignatureS, Witness, H160, U256}; #[test] fn test_legacy_decode() { @@ -616,44 +613,6 @@ mod tests { assert!(!utx.signature.as_ref().unwrap().is_eth_sig()); } - #[test] - fn test_signature_r_codec() { - let cell_dep = CellDep { - tx_hash: H256::from_slice(&[ - 243, 81, 120, 199, 161, 165, 164, 229, 177, 100, 21, 122, 165, 73, 164, 147, 206, - 188, 154, 48, 121, 182, 169, 237, 231, 174, 82, 7, 173, 179, 244, 212, - ]), - index: 0, - dep_type: 1, - }; - let cell_with_data = CellWithData { - type_script: None, - lock_script: Script { - code_hash: H256::from_slice(&[ - 210, 55, 97, 179, 100, 33, 7, 53, 193, 156, 96, 86, 29, 33, 63, 179, 190, 174, - 47, 214, 23, 39, 67, 113, 158, 255, 105, 32, 224, 32, 186, 172, - ]), - args: vec![ - 0, 1, 96, 145, 217, 61, 186, 177, 47, 22, 100, 15, 179, 160, 168, 241, 231, - 126, 3, 251, 197, 28, - ] - .into(), - hash_type: 1, - }, - data: Bytes::new(), - }; - let address_source = AddressSource { index: 0, type_: 0 }; - - let sig_r = SignatureR::ByRefAndOneInput(CKBTxMockByRefAndOneInput { - cell_deps: vec![cell_dep], - header_deps: vec![], - input_cell_with_data: cell_with_data, - out_point_addr_source: address_source, - }); - - assert_eq!(SignatureR::decode(&sig_r.encode()).unwrap(), sig_r); - } - #[test] fn test_signature_s_codec() { let witness = Witness { diff --git a/protocol/src/traits/interoperation.rs b/protocol/src/traits/interoperation.rs index 72b38d151..15409999f 100644 --- a/protocol/src/traits/interoperation.rs +++ b/protocol/src/traits/interoperation.rs @@ -1,9 +1,8 @@ use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; -use ckb_types::core::{cell::CellProvider, Cycle, TransactionView}; -use ckb_types::{packed, prelude::*}; +use ckb_types::core::cell::CellProvider; -use crate::types::{Bytes, CellDep, CellWithData, SignatureR, SignatureS, VMResp}; -use crate::{lazy::DUMMY_INPUT_OUT_POINT, traits::Context, ProtocolResult}; +use crate::types::{Bytes, CellDep, VMResp}; +use crate::{traits::Context, ProtocolResult}; pub const BYTE_SHANNONS: u64 = 100_000_000; pub const SIGNATURE_HASH_CELL_OCCUPIED_CAPACITY: u64 = signature_hash_cell_bytes() * BYTE_SHANNONS; @@ -37,99 +36,4 @@ pub trait Interoperation: Sync + Send { args: &[Bytes], max_cycles: u64, ) -> ProtocolResult; - - fn verify_by_ckb_vm( - ctx: Context, - data_loader: DL, - mocked_tx: &TransactionView, - dummy_input: Option, - max_cycles: u64, - ) -> ProtocolResult; - - /// The function construct the `TransactionView` payload required by - /// `verify_by_ckb_vm()`. - fn dummy_transaction( - r: SignatureR, - s: SignatureS, - signature_hash: Option<[u8; 32]>, - ) -> TransactionView { - let cell_deps = r.cell_deps(); - let header_deps = r.header_deps(); - let signature_hash = signature_hash.map(|hash| hash.to_vec()).unwrap_or_default(); - - let tx_builder = TransactionView::new_advanced_builder() - .cell_deps(cell_deps.iter().map(Into::into)) - .header_deps(header_deps.iter().map(|dep| dep.0.pack())) - .witnesses(s.witnesses.iter().map(|i| { - packed::WitnessArgsBuilder::default() - .input_type( - packed::BytesOptBuilder::default() - .set(i.input_type.clone().map(|inner| inner.pack())) - .build(), - ) - .output_type( - packed::BytesOptBuilder::default() - .set(i.output_type.clone().map(|inner| inner.pack())) - .build(), - ) - .lock( - packed::BytesOptBuilder::default() - .set(i.lock.clone().map(|inner| inner.pack())) - .build(), - ) - .build() - .as_bytes() - .pack() - })); - - if r.is_only_by_ref() { - return tx_builder - .inputs(r.out_points().iter().map(|i| { - packed::CellInput::new( - packed::OutPointBuilder::default() - .tx_hash(i.tx_hash.0.pack()) - .index(i.index.pack()) - .build(), - 0u64, - ) - })) - .output( - packed::CellOutputBuilder::default() - .capacity(SIGNATURE_HASH_CELL_OCCUPIED_CAPACITY.pack()) - .build(), - ) - .output_data(signature_hash.pack()) - .build(); - } - - let output_capacity = (r.dummy_input().unwrap().capacity() - BYTE_SHANNONS) - .max(SIGNATURE_HASH_CELL_OCCUPIED_CAPACITY); - - tx_builder - .input(packed::CellInput::new(DUMMY_INPUT_OUT_POINT.clone(), 0u64)) - .output( - packed::CellOutputBuilder::default() - .capacity(output_capacity.pack()) - .build(), - ) - .output_data(signature_hash.pack()) - .build() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use ckb_types::core::Capacity; - - #[test] - fn test_const_signature_hash_cell_bytes() { - let data_capacity = Capacity::bytes(32).unwrap(); - let actual = packed::CellOutputBuilder::default() - .build() - .occupied_capacity(data_capacity) - .unwrap() - .as_u64(); - assert_eq!(SIGNATURE_HASH_CELL_OCCUPIED_CAPACITY, actual); - } } diff --git a/protocol/src/types/interoperation.rs b/protocol/src/types/interoperation.rs index 4c5f5c84c..8524f5fda 100644 --- a/protocol/src/types/interoperation.rs +++ b/protocol/src/types/interoperation.rs @@ -1,13 +1,9 @@ -use ckb_types::{core::cell::CellMeta, packed, prelude::*}; +use ckb_types::{packed, prelude::*}; use derive_more::Display; use rlp_derive::{RlpDecodable, RlpEncodable}; use serde::{Deserialize, Serialize}; -use crate::traits::{BYTE_SHANNONS, SIGNATURE_HASH_CELL_OCCUPIED_CAPACITY}; -use crate::types::{Bytes, TypesError, H256}; -use crate::{ckb_blake2b_256, codec::ProtocolCodec, lazy::DUMMY_INPUT_OUT_POINT, ProtocolResult}; - -const CAPACITY_BYTES_LEN: usize = 8; +use crate::types::{Bytes, H256}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct VMResp { @@ -15,143 +11,6 @@ pub struct VMResp { pub cycles: u64, } -/// The address mapping for calculate an Axon address by the input cell, which -/// is `keccak(input[index].content).into()`. The `type_` field means the type -/// of content to calculate hash with the following rules: -/// `0u8`: use lock script hash. -/// `1u8`: use type script hash. -/// So that the default value of `AddressSource` means using -/// `blake2b_256(input[0].lock().as_bytes())` as `keccak()` input. -#[derive( - RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq, -)] -pub struct AddressSource { - pub type_: u8, - pub index: u32, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum SignatureR { - ByRef(CKBTxMockByRef), - ByRefAndOneInput(CKBTxMockByRefAndOneInput), -} - -impl SignatureR { - pub fn new_by_ref( - cell_deps: Vec, - header_deps: Vec, - out_points: Vec, - out_point_addr_source: AddressSource, - ) -> Self { - SignatureR::ByRef(CKBTxMockByRef { - cell_deps, - header_deps, - out_points, - out_point_addr_source, - }) - } - - pub fn decode(data: &[u8]) -> ProtocolResult { - if data.is_empty() { - return Err(TypesError::SignatureRIsEmpty.into()); - } - - let ret = match data[0] { - 1u8 => SignatureR::ByRef(CKBTxMockByRef::decode(&data[1..])?), - 2u8 => SignatureR::ByRefAndOneInput(CKBTxMockByRefAndOneInput::decode(&data[1..])?), - _ => return Err(TypesError::InvalidSignatureRType.into()), - }; - - if ret.address_source().type_ > 1 { - return Err(TypesError::InvalidAddressSourceType.into()); - } - - Ok(ret) - } - - pub fn inputs_len(&self) -> usize { - match self { - SignatureR::ByRef(i) => i.out_points.len(), - SignatureR::ByRefAndOneInput(_) => 1usize, - } - } - - pub fn address_source(&self) -> AddressSource { - match self { - SignatureR::ByRef(i) => i.out_point_addr_source, - SignatureR::ByRefAndOneInput(i) => i.out_point_addr_source, - } - } - - pub fn cell_deps(&self) -> &[CellDep] { - match self { - SignatureR::ByRef(i) => &i.cell_deps, - SignatureR::ByRefAndOneInput(i) => &i.cell_deps, - } - } - - pub fn header_deps(&self) -> &[H256] { - match self { - SignatureR::ByRef(i) => &i.header_deps, - SignatureR::ByRefAndOneInput(i) => &i.header_deps, - } - } - - pub(crate) fn out_points(&self) -> &[OutPoint] { - match self { - SignatureR::ByRef(i) => &i.out_points, - _ => unreachable!(), - } - } - - pub fn dummy_input(&self) -> Option { - match self { - SignatureR::ByRefAndOneInput(i) => Some(i.input_cell_with_data.clone()), - SignatureR::ByRef(_) => None, - } - } - - pub fn is_only_by_ref(&self) -> bool { - match self { - SignatureR::ByRef(_) => true, - SignatureR::ByRefAndOneInput(_) => false, - } - } - - #[cfg(test)] - pub(crate) fn encode(&self) -> Bytes { - match self { - SignatureR::ByRef(r) => { - let mut ret = vec![1]; - ret.extend_from_slice(&rlp::encode(r)); - ret - } - SignatureR::ByRefAndOneInput(r) => { - let mut ret = vec![2]; - ret.extend_from_slice(&rlp::encode(r)); - ret - } - } - .into() - } -} - -#[derive(RlpEncodable, RlpDecodable, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] -pub struct CKBTxMockByRef { - pub cell_deps: Vec, - pub header_deps: Vec, - pub out_points: Vec, - pub out_point_addr_source: AddressSource, -} - -#[derive(RlpEncodable, RlpDecodable, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] -pub struct CKBTxMockByRefAndOneInput { - pub cell_deps: Vec, - pub header_deps: Vec, - pub input_cell_with_data: CellWithData, - pub out_point_addr_source: AddressSource, -} - #[derive(RlpEncodable, RlpDecodable, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct CellWithData { pub type_script: Option