Skip to content

Commit

Permalink
feat: tx trace api (#181)
Browse files Browse the repository at this point in the history
Addeed two RPCs

- `trace_transaction` creates new transaction.
- `get_transaction_trace` gets the transaction processing status

See `rpc/doc.md` for details.
  • Loading branch information
zhangsoledad authored and doitian committed Jan 16, 2019
1 parent 64f2c9c commit e759128
Show file tree
Hide file tree
Showing 16 changed files with 517 additions and 14 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ channel = { package= "crossbeam-channel", version = "0.3" }
ckb-util = { path = "../util" }
fnv = "1.0.3"
merkle-root = {path = "../util/merkle-root"}
faster-hex = "0.3"
15 changes: 13 additions & 2 deletions core/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use crate::BlockNumber;
pub use crate::Capacity;
use bincode::{deserialize, serialize};
use ckb_util::u64_to_bytes;
use faster_hex::hex_string;
use hash::sha3_256;
use numext_fixed_hash::H256;
use serde_derive::{Deserialize, Serialize};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::{fmt, mem};

pub const VERSION: u32 = 0;

Expand Down Expand Up @@ -144,7 +145,7 @@ impl CellOutput {
}
}

#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, Default, Hash)]
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Default, Hash)]
pub struct ProposalShortId([u8; 10]);

impl Deref for ProposalShortId {
Expand All @@ -155,6 +156,16 @@ impl Deref for ProposalShortId {
}
}

impl fmt::Debug for ProposalShortId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"ProposalShortId(0x{})",
hex_string(&self.0).expect("hex proposal short id")
)
}
}

impl DerefMut for ProposalShortId {
fn deref_mut(&mut self) -> &mut [u8; 10] {
&mut self.0
Expand Down
3 changes: 2 additions & 1 deletion nodes_template/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"max_orphan_size": 10000,
"max_proposal_size": 10000,
"max_cache_size": 1000,
"max_pending_size": 10000
"max_pending_size": 10000,
"trace": 100
},
"miner": {
"new_transactions_threshold": 8,
Expand Down
1 change: 1 addition & 0 deletions pool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ env_logger = "0.6"
ckb-db = { path = "../db" }
hash = {path = "../util/hash"}
ckb-chain = { path = "../chain" }
tempfile = "3.0"
97 changes: 97 additions & 0 deletions pool/src/tests/pool.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::txs_pool::pool::TransactionPoolService;
use crate::txs_pool::trace::{Action, TxTrace};
use crate::txs_pool::types::*;
use channel::select;
use channel::{self, Receiver};
Expand All @@ -22,6 +23,7 @@ use std::io::Read;
use std::path::Path;
use std::sync::Arc;
use std::time;
use tempfile::TempPath;

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

fn prepare_trace(
pool: &mut TestPool<ChainKVStore<MemoryKeyValueDB>>,
faketime_file: &TempPath,
) -> Transaction {
let tx = test_transaction(&[OutPoint::new(pool.tx_hash.clone(), 0)], 2);

let block_number = { pool.shared.tip_header().read().number() };

pool.service.trace_transaction(tx.clone()).unwrap();
let prop_ids = pool.service.prepare_proposal(10);

assert_eq!(1, prop_ids.len());
assert_eq!(prop_ids[0], tx.proposal_short_id());

let header = HeaderBuilder::default().number(block_number + 1).build();
let block = BlockBuilder::default()
.header(header)
.proposal_transactions(vec![tx.proposal_short_id()])
.build();

faketime::write_millis(faketime_file, 9102).expect("write millis");

pool.service.reconcile_block(&block);
tx
}

#[cfg(not(disable_faketime))]
#[test]
fn test_get_transaction_traces() {
let mut pool = TestPool::<ChainKVStore<MemoryKeyValueDB>>::simple();
let faketime_file = faketime::millis_tempfile(8102).expect("create faketime file");
faketime::enable(&faketime_file);

let tx = prepare_trace(&mut pool, &faketime_file);
let tx_hash = tx.hash();

let trace = pool.service.get_transaction_traces(&tx_hash);
match trace.map(|t| t.as_slice()) {
Some(
[TxTrace {
action: Action::AddPending,
time: 8102,
..
}, TxTrace {
action: Action::Proposed,
info: proposal_info,
time: 9102,
}, TxTrace {
action: Action::AddCommit,
time: 9102,
..
}],
) => assert_eq!(
proposal_info,
concat!("ProposalShortId(0xda495f694cac79513d00) proposed ",
"in block number(2)-hash(0xb42c5305777987f80112e862a3e722c1d0e68c671f1d8920d16ebfc6783a6467)")
),
_ => assert!(false),
}

faketime::write_millis(&faketime_file, 9103).expect("write millis");
let block = apply_transactions(vec![tx.clone()], vec![], &mut pool);
let trace = pool.service.get_transaction_traces(&tx_hash);
match trace.map(|t| t.as_slice()) {
Some(
[TxTrace {
action: Action::AddPending,
time: 8102,
..
}, TxTrace {
action: Action::Proposed,
time: 9102,
..
}, TxTrace {
action: Action::AddCommit,
time: 9102,
..
}, TxTrace {
action: Action::Committed,
info: committed_info,
time: 9103,
}],
) => assert_eq!(
committed_info,
&format!(
"committed in block number({:?})-hash({:#x})",
block.header().number(),
block.header().hash()
)
),
_ => assert!(false),
}
}

struct TestPool<CI> {
service: TransactionPoolService<CI>,
chain: ChainController,
Expand Down Expand Up @@ -500,6 +596,7 @@ impl<CI: ChainIndex + 'static> TestPool<CI> {
max_proposal_size: 1000,
max_cache_size: 1000,
max_pending_size: 1000,
trace: Some(100),
},
shared.clone(),
notify.clone(),
Expand Down
2 changes: 2 additions & 0 deletions pool/src/txs_pool/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! The transaction pool, keeping a view of currently-valid transactions that

pub mod pool;
pub mod trace;
pub mod types;

pub use self::pool::{TransactionPoolController, TransactionPoolService};
pub use self::trace::TxTrace;
pub use self::types::{
Orphan, PendingQueue, Pool, PoolConfig, PoolError, ProposedQueue, TxStage, TxoStatus,
};
Loading

0 comments on commit e759128

Please sign in to comment.