Skip to content

Commit e759128

Browse files
zhangsoledaddoitian
authored andcommitted
feat: tx trace api (#181)
Addeed two RPCs - `trace_transaction` creates new transaction. - `get_transaction_trace` gets the transaction processing status See `rpc/doc.md` for details.
1 parent 64f2c9c commit e759128

16 files changed

Lines changed: 517 additions & 14 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ channel = { package= "crossbeam-channel", version = "0.3" }
1818
ckb-util = { path = "../util" }
1919
fnv = "1.0.3"
2020
merkle-root = {path = "../util/merkle-root"}
21+
faster-hex = "0.3"

core/src/transaction.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ use crate::BlockNumber;
55
pub use crate::Capacity;
66
use bincode::{deserialize, serialize};
77
use ckb_util::u64_to_bytes;
8+
use faster_hex::hex_string;
89
use hash::sha3_256;
910
use numext_fixed_hash::H256;
1011
use serde_derive::{Deserialize, Serialize};
11-
use std::mem;
1212
use std::ops::{Deref, DerefMut};
13+
use std::{fmt, mem};
1314

1415
pub const VERSION: u32 = 0;
1516

@@ -144,7 +145,7 @@ impl CellOutput {
144145
}
145146
}
146147

147-
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, Default, Hash)]
148+
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Default, Hash)]
148149
pub struct ProposalShortId([u8; 10]);
149150

150151
impl Deref for ProposalShortId {
@@ -155,6 +156,16 @@ impl Deref for ProposalShortId {
155156
}
156157
}
157158

159+
impl fmt::Debug for ProposalShortId {
160+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
161+
write!(
162+
f,
163+
"ProposalShortId(0x{})",
164+
hex_string(&self.0).expect("hex proposal short id")
165+
)
166+
}
167+
}
168+
158169
impl DerefMut for ProposalShortId {
159170
fn deref_mut(&mut self) -> &mut [u8; 10] {
160171
&mut self.0

nodes_template/default.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"max_orphan_size": 10000,
4141
"max_proposal_size": 10000,
4242
"max_cache_size": 1000,
43-
"max_pending_size": 10000
43+
"max_pending_size": 10000,
44+
"trace": 100
4445
},
4546
"miner": {
4647
"new_transactions_threshold": 8,

pool/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ env_logger = "0.6"
2626
ckb-db = { path = "../db" }
2727
hash = {path = "../util/hash"}
2828
ckb-chain = { path = "../chain" }
29+
tempfile = "3.0"

pool/src/tests/pool.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::txs_pool::pool::TransactionPoolService;
2+
use crate::txs_pool::trace::{Action, TxTrace};
23
use crate::txs_pool::types::*;
34
use channel::select;
45
use channel::{self, Receiver};
@@ -22,6 +23,7 @@ use std::io::Read;
2223
use std::path::Path;
2324
use std::sync::Arc;
2425
use std::time;
26+
use tempfile::TempPath;
2527

2628
macro_rules! expect_output_parent {
2729
($pool:expr, $expected:pat, $( $output:expr ),+ ) => {
@@ -469,6 +471,100 @@ fn test_switch_fork() {
469471
assert_eq!(mtxs, vec![txs[3].clone(), txs[6].clone(), txs[5].clone()]);
470472
}
471473

474+
fn prepare_trace(
475+
pool: &mut TestPool<ChainKVStore<MemoryKeyValueDB>>,
476+
faketime_file: &TempPath,
477+
) -> Transaction {
478+
let tx = test_transaction(&[OutPoint::new(pool.tx_hash.clone(), 0)], 2);
479+
480+
let block_number = { pool.shared.tip_header().read().number() };
481+
482+
pool.service.trace_transaction(tx.clone()).unwrap();
483+
let prop_ids = pool.service.prepare_proposal(10);
484+
485+
assert_eq!(1, prop_ids.len());
486+
assert_eq!(prop_ids[0], tx.proposal_short_id());
487+
488+
let header = HeaderBuilder::default().number(block_number + 1).build();
489+
let block = BlockBuilder::default()
490+
.header(header)
491+
.proposal_transactions(vec![tx.proposal_short_id()])
492+
.build();
493+
494+
faketime::write_millis(faketime_file, 9102).expect("write millis");
495+
496+
pool.service.reconcile_block(&block);
497+
tx
498+
}
499+
500+
#[cfg(not(disable_faketime))]
501+
#[test]
502+
fn test_get_transaction_traces() {
503+
let mut pool = TestPool::<ChainKVStore<MemoryKeyValueDB>>::simple();
504+
let faketime_file = faketime::millis_tempfile(8102).expect("create faketime file");
505+
faketime::enable(&faketime_file);
506+
507+
let tx = prepare_trace(&mut pool, &faketime_file);
508+
let tx_hash = tx.hash();
509+
510+
let trace = pool.service.get_transaction_traces(&tx_hash);
511+
match trace.map(|t| t.as_slice()) {
512+
Some(
513+
[TxTrace {
514+
action: Action::AddPending,
515+
time: 8102,
516+
..
517+
}, TxTrace {
518+
action: Action::Proposed,
519+
info: proposal_info,
520+
time: 9102,
521+
}, TxTrace {
522+
action: Action::AddCommit,
523+
time: 9102,
524+
..
525+
}],
526+
) => assert_eq!(
527+
proposal_info,
528+
concat!("ProposalShortId(0xda495f694cac79513d00) proposed ",
529+
"in block number(2)-hash(0xb42c5305777987f80112e862a3e722c1d0e68c671f1d8920d16ebfc6783a6467)")
530+
),
531+
_ => assert!(false),
532+
}
533+
534+
faketime::write_millis(&faketime_file, 9103).expect("write millis");
535+
let block = apply_transactions(vec![tx.clone()], vec![], &mut pool);
536+
let trace = pool.service.get_transaction_traces(&tx_hash);
537+
match trace.map(|t| t.as_slice()) {
538+
Some(
539+
[TxTrace {
540+
action: Action::AddPending,
541+
time: 8102,
542+
..
543+
}, TxTrace {
544+
action: Action::Proposed,
545+
time: 9102,
546+
..
547+
}, TxTrace {
548+
action: Action::AddCommit,
549+
time: 9102,
550+
..
551+
}, TxTrace {
552+
action: Action::Committed,
553+
info: committed_info,
554+
time: 9103,
555+
}],
556+
) => assert_eq!(
557+
committed_info,
558+
&format!(
559+
"committed in block number({:?})-hash({:#x})",
560+
block.header().number(),
561+
block.header().hash()
562+
)
563+
),
564+
_ => assert!(false),
565+
}
566+
}
567+
472568
struct TestPool<CI> {
473569
service: TransactionPoolService<CI>,
474570
chain: ChainController,
@@ -500,6 +596,7 @@ impl<CI: ChainIndex + 'static> TestPool<CI> {
500596
max_proposal_size: 1000,
501597
max_cache_size: 1000,
502598
max_pending_size: 1000,
599+
trace: Some(100),
503600
},
504601
shared.clone(),
505602
notify.clone(),

pool/src/txs_pool/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! The transaction pool, keeping a view of currently-valid transactions that
22
33
pub mod pool;
4+
pub mod trace;
45
pub mod types;
56

67
pub use self::pool::{TransactionPoolController, TransactionPoolService};
8+
pub use self::trace::TxTrace;
79
pub use self::types::{
810
Orphan, PendingQueue, Pool, PoolConfig, PoolError, ProposedQueue, TxStage, TxoStatus,
911
};

0 commit comments

Comments
 (0)