fixed trace_transaction crash when block contained suicide (#1781)
This commit is contained in:
parent
9e5e57fdcd
commit
dbfc5cd31c
@ -423,6 +423,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Extras {
|
||||
block_hashes: HashMap<BlockNumber, H256>,
|
||||
transaction_hashes: HashMap<BlockNumber, Vec<H256>>,
|
||||
@ -650,4 +651,36 @@ mod tests {
|
||||
assert_eq!(tracedb.trace(0, 0, vec![]).unwrap(), create_simple_localized_trace(0, block_0.clone(), tx_0.clone()));
|
||||
assert_eq!(tracedb.trace(1, 0, vec![]).unwrap(), create_simple_localized_trace(1, block_1.clone(), tx_1.clone()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query_trace_after_reopen() {
|
||||
let temp = RandomTempPath::new();
|
||||
let db = new_db(temp.as_str());
|
||||
let mut config = Config::default();
|
||||
let mut extras = Extras::default();
|
||||
let block_0 = H256::from(0xa1);
|
||||
let tx_0 = H256::from(0xff);
|
||||
|
||||
extras.block_hashes.insert(0, block_0.clone());
|
||||
extras.transaction_hashes.insert(0, vec![tx_0.clone()]);
|
||||
|
||||
// set tracing on
|
||||
config.enabled = Switch::On;
|
||||
|
||||
{
|
||||
let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras.clone())).unwrap();
|
||||
|
||||
// import block 0
|
||||
let request = create_simple_import_request(0, block_0.clone());
|
||||
let batch = DBTransaction::new(&db);
|
||||
tracedb.import(&batch, request);
|
||||
db.write(batch).unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
let tracedb = TraceDB::new(config.clone(), db.clone(), Arc::new(extras)).unwrap();
|
||||
let traces = tracedb.transaction_traces(0, 0);
|
||||
assert_eq!(traces.unwrap(), vec![create_simple_localized_trace(0, block_0, tx_0)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,31 +164,63 @@ impl Into<Vec<FlatTransactionTraces>> for FlatBlockTraces {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace};
|
||||
use trace::trace::{Action, Res, CallResult, Call};
|
||||
use trace::trace::{Action, Res, CallResult, Call, Suicide};
|
||||
use types::executed::CallType;
|
||||
|
||||
#[test]
|
||||
fn test_trace_serialization() {
|
||||
use util::rlp;
|
||||
// block #51921
|
||||
|
||||
let flat_trace = FlatTrace {
|
||||
action: Action::Call(Call {
|
||||
from: 1.into(),
|
||||
to: 2.into(),
|
||||
value: 3.into(),
|
||||
gas: 4.into(),
|
||||
input: vec![0x5],
|
||||
from: "8dda5e016e674683241bf671cced51e7239ea2bc".parse().unwrap(),
|
||||
to: "37a5e19cc2d49f244805d5c268c0e6f321965ab9".parse().unwrap(),
|
||||
value: "3627e8f712373c0000".parse().unwrap(),
|
||||
gas: 0x03e8.into(),
|
||||
input: vec![],
|
||||
call_type: CallType::Call,
|
||||
}),
|
||||
result: Res::Call(CallResult {
|
||||
gas_used: 10.into(),
|
||||
output: vec![0x11, 0x12]
|
||||
gas_used: 0.into(),
|
||||
output: vec![],
|
||||
}),
|
||||
trace_address: Default::default(),
|
||||
subtraces: 0,
|
||||
};
|
||||
|
||||
let block_traces = FlatBlockTraces(vec![FlatTransactionTraces(vec![flat_trace])]);
|
||||
let flat_trace1 = FlatTrace {
|
||||
action: Action::Call(Call {
|
||||
from: "3d0768da09ce77d25e2d998e6a7b6ed4b9116c2d".parse().unwrap(),
|
||||
to: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(),
|
||||
value: 0.into(),
|
||||
gas: 0x010c78.into(),
|
||||
input: vec![0x41, 0xc0, 0xe1, 0xb5],
|
||||
call_type: CallType::Call,
|
||||
}),
|
||||
result: Res::Call(CallResult {
|
||||
gas_used: 0x0127.into(),
|
||||
output: vec![],
|
||||
}),
|
||||
trace_address: Default::default(),
|
||||
subtraces: 1,
|
||||
};
|
||||
|
||||
let flat_trace2 = FlatTrace {
|
||||
action: Action::Suicide(Suicide {
|
||||
address: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(),
|
||||
balance: 0.into(),
|
||||
refund_address: "3d0768da09ce77d25e2d998e6a7b6ed4b9116c2d".parse().unwrap(),
|
||||
}),
|
||||
result: Res::None,
|
||||
trace_address: vec![0].into_iter().collect(),
|
||||
subtraces: 0,
|
||||
};
|
||||
|
||||
let block_traces = FlatBlockTraces(vec![
|
||||
FlatTransactionTraces(vec![flat_trace]),
|
||||
FlatTransactionTraces(vec![flat_trace1, flat_trace2])
|
||||
]);
|
||||
|
||||
let encoded = rlp::encode(&block_traces);
|
||||
let decoded = rlp::decode(&encoded);
|
||||
|
@ -252,7 +252,7 @@ impl Decodable for Suicide {
|
||||
let res = Suicide {
|
||||
address: try!(d.val_at(0)),
|
||||
refund_address: try!(d.val_at(1)),
|
||||
balance: try!(d.val_at(3)),
|
||||
balance: try!(d.val_at(2)),
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
@ -298,7 +298,7 @@ impl Decodable for Action {
|
||||
match action_type {
|
||||
0 => d.val_at(1).map(Action::Call),
|
||||
1 => d.val_at(1).map(Action::Create),
|
||||
2 => d.val_at(2).map(Action::Suicide),
|
||||
2 => d.val_at(1).map(Action::Suicide),
|
||||
_ => Err(DecoderError::Custom("Invalid action type.")),
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
use rlp::{View, DecoderError, UntrustedRlp, PayloadInfo, Prototype, RlpDecodable};
|
||||
|
||||
impl<'a> From<UntrustedRlp<'a>> for Rlp<'a> {
|
||||
@ -114,9 +115,9 @@ impl<'a, 'view> View<'a, 'view> for Rlp<'a> where 'a: 'view {
|
||||
}
|
||||
|
||||
impl <'a, 'view> Rlp<'a> where 'a: 'view {
|
||||
fn view_as_val<T, R>(r: &R) -> T where R: View<'a, 'view>, T: RlpDecodable {
|
||||
fn view_as_val<T, R>(r: &'view R) -> T where R: View<'a, 'view>, T: RlpDecodable {
|
||||
let res: Result<T, DecoderError> = r.as_val();
|
||||
res.unwrap_or_else(|e| panic!("DecodeError: {}", e))
|
||||
res.unwrap_or_else(|e| panic!("DecodeError: {}, {}", e, r.as_raw().to_hex()))
|
||||
}
|
||||
|
||||
/// Decode into an object
|
||||
|
Loading…
Reference in New Issue
Block a user