Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: rlp decode of SignedTransction with interoperation signature #1533

Merged
merged 2 commits into from
Nov 15, 2023
Merged
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
105 changes: 7 additions & 98 deletions core/api/src/jsonrpc/impl/web3.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
use std::{sync::Arc, time::Duration};

use ckb_types::core::cell::{CellProvider, CellStatus};
use ckb_types::prelude::Entity;
use jsonrpsee::core::RpcResult;

use common_apm::metrics_rpc;
use protocol::traits::{APIAdapter, Context, Interoperation};
use protocol::traits::{APIAdapter, Context};
use protocol::types::{
Block, BlockNumber, Bytes, CellDepWithPubKey, EthAccountProof, Hash, Hasher, Header, Hex,
Proposal, Receipt, SignatureComponents, SignatureR, SignatureS, SignedTransaction, TxResp,
UnverifiedTransaction, BASE_FEE_PER_GAS, H160, H256, MAX_FEE_HISTORY, MAX_RPC_GAS_CAP,
MIN_TRANSACTION_GAS_LIMIT, U256,
Block, BlockNumber, Bytes, EthAccountProof, Hash, Header, Hex, Proposal, Receipt,
SignedTransaction, TxResp, UnverifiedTransaction, BASE_FEE_PER_GAS, H160, H256,
MAX_FEE_HISTORY, MAX_RPC_GAS_CAP, MIN_TRANSACTION_GAS_LIMIT, U256,
};
use protocol::{
async_trait, ckb_blake2b_256, codec::ProtocolCodec, lazy::PROTOCOL_VERSION, tokio::time::sleep,
ProtocolResult, MEMPOOL_REFRESH_TIMEOUT,
async_trait, codec::ProtocolCodec, lazy::PROTOCOL_VERSION, tokio::time::sleep, ProtocolResult,
MEMPOOL_REFRESH_TIMEOUT,
};

use core_executor::system_contract::DataProvider;
use core_interoperation::utils::is_dummy_out_point;
use core_interoperation::InteroperationImpl;

use crate::jsonrpc::web3_types::{
BlockCount, BlockId, FeeHistoryEmpty, FeeHistoryWithReward, FeeHistoryWithoutReward,
RichTransactionOrHash, Web3Block, Web3CallRequest, Web3FeeHistory, Web3Filter, Web3Log,
Expand Down Expand Up @@ -191,80 +184,6 @@ impl<Adapter: APIAdapter> Web3RpcImpl<Adapter> {
reward,
))
}

async fn extract_interoperation_tx_sender(
&self,
utx: &UnverifiedTransaction,
signature: &SignatureComponents,
) -> RpcResult<H160> {
// Call CKB-VM mode
if signature.r[0] == 0 {
let r = rlp::decode::<CellDepWithPubKey>(&signature.r[1..])
.map_err(|e| RpcError::DecodeInteroperationSigR(e.to_string()))?;

return Ok(Hasher::digest(&r.pub_key).into());
}

// Verify by CKB-VM mode
let r = SignatureR::decode(&signature.r)
.map_err(|e| RpcError::DecodeInteroperationSigR(e.to_string()))?;
let s = SignatureS::decode(&signature.s)
.map_err(|e| RpcError::DecodeInteroperationSigS(e.to_string()))?;
let address_source = r.address_source();

let ckb_tx_view =
InteroperationImpl::dummy_transaction(r.clone(), s, Some(utx.signature_hash(true).0));
let dummy_input = r.dummy_input();

let input = ckb_tx_view
.inputs()
.get(address_source.index as usize)
.ok_or(RpcError::InvalidAddressSource)?;

log::debug!("[mempool]: verify interoperation tx sender \ntx view \n{:?}\ndummy input\n {:?}\naddress source\n{:?}\n", ckb_tx_view, dummy_input, address_source);

// Dummy input mode
if is_dummy_out_point(&input.previous_output()) {
log::debug!("[mempool]: verify interoperation tx dummy input mode.");

if let Some(cell) = dummy_input {
if address_source.type_ == 1 && cell.type_script.is_none() {
return Err(RpcError::InvalidAddressSource.into());
}

let script_hash = if address_source.type_ == 0 {
cell.lock_script_hash()
} else {
cell.type_script_hash().unwrap()
};

return Ok(Hasher::digest(script_hash).into());
}

return Err(RpcError::MissingDummyInputCell.into());
}

// Reality input mode
let root = self
.adapter
.get_image_cell_root(Context::new())
.await
.map_err(|e| RpcError::Internal(e.to_string()))?;
match DataProvider::new(root).cell(&input.previous_output(), true) {
CellStatus::Live(cell) => {
let script_hash = if address_source.type_ == 0 {
ckb_blake2b_256(cell.cell_output.lock().as_slice())
} else if let Some(type_script) = cell.cell_output.type_().to_opt() {
ckb_blake2b_256(type_script.as_slice())
} else {
return Err(RpcError::InvalidAddressSource.into());
};

Ok(Hasher::digest(script_hash).into())
}
_ => Err(RpcError::CannotFindImageCell.into()),
}
}
}

#[async_trait]
Expand Down Expand Up @@ -297,17 +216,7 @@ impl<Adapter: APIAdapter + 'static> Web3RpcServer for Web3RpcImpl<Adapter> {
utx.check_hash()
.map_err(|e| RpcError::Internal(e.to_string()))?;

let interoperation_sender = if let Some(sig) = utx.signature.as_ref() {
if sig.is_eth_sig() {
None
} else {
Some(self.extract_interoperation_tx_sender(&utx, sig).await?)
}
} else {
return Err(RpcError::TransactionIsNotSigned.into());
};

let stx = SignedTransaction::from_unverified(utx, interoperation_sender)
let stx = SignedTransaction::from_unverified(utx)
.map_err(|e| RpcError::Internal(e.to_string()))?;
let hash = stx.transaction.hash;

Expand Down
2 changes: 1 addition & 1 deletion core/api/src/jsonrpc/web3_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ mod tests {
// https://etherscan.io/getRawTx?tx=0x07c7388b03ab8403deeaefc551efbc632f8531f04dc9993a274dbba9bbb98cbf
let tx = Hex::from_str("0x02f902f801728405f5e1008509898edcf78302ffb8943fc91a3afd70395cd496c647d5a6cc9d4b2b7fad8802c68af0bb140000b902843593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006480c64700000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000002c68af0bb1400000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000002c68af0bb1400000000000000000000000000000000000000000004a715ce36374beaa635218d9700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000c3681a720605bd6f8fe9a2fabff6a7cdecdc605dc080a0d253ee687ab2d9734a5073d64a0ba26bc3bc1cf4582005137bba05ef88616ea89e8ba79925267b17403fdf3ab47641b4aa52322dc385429cc92a7003c5d7c2").unwrap();
let tx = UnverifiedTransaction::decode(tx).unwrap();
let tx = SignedTransaction::from_unverified(tx, None).unwrap();
let tx = SignedTransaction::from_unverified(tx).unwrap();
let tx_json = serde_json::to_value(Web3Transaction::from(tx)).unwrap();

assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion core/consensus/benches/bench_wal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn mock_sign_tx() -> SignedTransaction {
.to_bytes();
utx.signature = Some(signature.into());

SignedTransaction::from_unverified(utx, None).unwrap()
SignedTransaction::from_unverified(utx).unwrap()
}

fn criterion_save_wal(c: &mut Criterion) {
Expand Down
2 changes: 1 addition & 1 deletion core/consensus/src/wal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ mod tests {
.to_bytes();
utx.signature = Some(signature.into());

SignedTransaction::from_unverified(utx, None).unwrap()
SignedTransaction::from_unverified(utx).unwrap()
}

pub fn mock_wal_txs(size: usize) -> Vec<SignedTransaction> {
Expand Down
1 change: 0 additions & 1 deletion core/executor/src/precompiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ mod sha256;

#[cfg(test)]
mod tests;
mod verify_by_ckb_vm;

use std::collections::BTreeMap;

Expand Down
140 changes: 0 additions & 140 deletions core/executor/src/precompiles/verify_by_ckb_vm.rs

This file was deleted.

51 changes: 4 additions & 47 deletions core/interoperation/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
}
Expand Down Expand Up @@ -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<DL: CkbDataProvider + Sync + Send + 'static>(
_ctx: Context,
data_loader: DL,
mocked_tx: &TransactionView,
dummy_input: Option<CellWithData>,
max_cycles: u64,
) -> ProtocolResult<Cycle> {
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)]
Expand Down
Loading
Loading