From c78580e279420d83d685df0037fca7b8d55e6ae1 Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Sun, 28 Apr 2024 10:04:29 +0800 Subject: [PATCH] Add `test_tx_pool_accept` subcommand --- src/subcommands/rpc.rs | 45 +++++++++++++++++++++++++++++++++++++++++ src/utils/rpc/client.rs | 10 +++++++++ src/utils/rpc/types.rs | 18 +++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/subcommands/rpc.rs b/src/subcommands/rpc.rs index 2ab6a62c..8bbd2be0 100644 --- a/src/subcommands/rpc.rs +++ b/src/subcommands/rpc.rs @@ -1,24 +1,29 @@ use ckb_jsonrpc_types::{ self as rpc_types, Alert, BlockNumber, EpochNumber, JsonBytes, Transaction, }; +use ckb_types::packed::{CellOutput, OutPoint}; use ckb_types::{bytes::Bytes, packed, prelude::*, H256}; use clap::{App, Arg, ArgMatches}; use ipnetwork::IpNetwork; use multiaddr::Multiaddr; use serde_derive::{Deserialize, Serialize}; +use std::collections::HashMap; use std::fs; use std::path::PathBuf; use std::time::Duration; +use super::tx::ReprTxHelper; use super::{CliSubCommand, Output}; use crate::utils::arg_parser::{ ArgParser, DurationParser, FeeRateStatisticsTargetParser, FilePathParser, FixedHashParser, FromStrParser, HexParser, }; +use crate::utils::other::get_live_cell_with_cache; use crate::utils::rpc::{ parse_order, BannedAddr, BlockEconomicState, BlockView, EpochView, HeaderView, HttpRpcClient, RawHttpRpcClient, RemoteNode, Timestamp, TransactionProof, TransactionWithStatus, }; +use crate::utils::tx_helper::TxHelper; pub struct RpcSubCommand<'a> { rpc_client: &'a mut HttpRpcClient, @@ -295,6 +300,11 @@ impl<'a> RpcSubCommand<'a> { .about("Hash of a transaction"), ), App::new("tx_pool_info").about("Get transaction pool information"), + App::new("test_tx_pool_accept") + .about("Test if transaction can be accepted by Tx Pool") + .arg( + Arg::with_name("tx-file").long("tx-file").takes_value(true).required(true).about("transaction data file(format json)") + ), App::new("clear_tx_pool").about("Removes all transactions from the transaction pool"), App::new("get_raw_tx_pool") .about("Returns all transaction ids in tx pool as a json array of string transaction ids") @@ -1064,6 +1074,41 @@ impl<'a> CliSubCommand for RpcSubCommand<'a> { Ok(Output::new_output(resp)) } } + ("test_tx_pool_accept", Some(m)) => { + let tx_file: PathBuf = FilePathParser::new(false).from_matches(m, "tx-file")?; + + let mut live_cell_cache: HashMap<(OutPoint, bool), (CellOutput, Bytes)> = + Default::default(); + let mut get_live_cell = |out_point: OutPoint, with_data: bool| { + get_live_cell_with_cache( + &mut live_cell_cache, + self.rpc_client, + out_point, + with_data, + ) + .map(|(output, _)| output) + }; + + let file = fs::File::open(tx_file).map_err(|err| err.to_string())?; + let repr: ReprTxHelper = + serde_json::from_reader(&file).map_err(|err| err.to_string())?; + let helper = TxHelper::try_from(repr)?; + + let tx_view = helper.build_tx(&mut get_live_cell, true)?; + let tx = tx_view.data(); + + let is_raw_data = is_raw_data || m.is_present("raw-data"); + if is_raw_data { + let resp = self + .raw_rpc_client + .test_tx_pool_accept(tx.into(), None) + .map_err(|err| err.to_string())?; + Ok(Output::new_output(resp)) + } else { + let resp = self.rpc_client.test_tx_pool_accept(tx, None)?; + Ok(Output::new_output(resp)) + } + } ("clear_tx_pool", _) => { self.rpc_client.clear_tx_pool()?; Ok(Output::new_success()) diff --git a/src/utils/rpc/client.rs b/src/utils/rpc/client.rs index e76e1f2f..4ee18759 100644 --- a/src/utils/rpc/client.rs +++ b/src/utils/rpc/client.rs @@ -368,6 +368,16 @@ impl HttpRpcClient { .map(Into::into) .map_err(|err| err.to_string()) } + pub fn test_tx_pool_accept( + &mut self, + tx: packed::Transaction, + outputs_validator: Option, + ) -> Result { + self.client + .test_tx_pool_accept(tx.into(), outputs_validator) + .map(Into::into) + .map_err(|err| err.to_string()) + } pub fn clear_tx_pool(&mut self) -> Result<(), String> { self.client.clear_tx_pool().map_err(|err| err.to_string()) } diff --git a/src/utils/rpc/types.rs b/src/utils/rpc/types.rs index 6bae918d..ecbd9c39 100644 --- a/src/utils/rpc/types.rs +++ b/src/utils/rpc/types.rs @@ -929,6 +929,24 @@ impl From for HardForks { } } +/// Response type of the RPC method `test_tx_pool_accept`. +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct EntryCompleted { + /// Cached tx cycles + pub cycles: Cycle, + /// Cached tx fee + pub fee: Capacity, +} + +impl From for EntryCompleted { + fn from(value: ckb_jsonrpc_types::EntryCompleted) -> Self { + Self { + cycles: value.cycles.into(), + fee: value.fee.into(), + } + } +} + /// SoftFork information #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[serde(untagged)]