From 25b0b8641ecaf627fdf9dcd677294c0214fa2fb9 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 14 Nov 2016 17:47:56 +0100 Subject: [PATCH 01/52] indent state tests --- ethcore/src/state/mod.rs | 2102 +++++++++++++++++++------------------- 1 file changed, 1051 insertions(+), 1051 deletions(-) diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 01a7e3b15..23a9cf0d7 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -783,1107 +783,1107 @@ impl Clone for State { #[cfg(test)] mod tests { -use std::sync::Arc; -use std::str::FromStr; -use rustc_serialize::hex::FromHex; -use super::*; -use util::{U256, H256, FixedHash, Address, Hashable}; -use tests::helpers::*; -use devtools::*; -use env_info::EnvInfo; -use spec::*; -use transaction::*; -use util::log::init_log; -use trace::{FlatTrace, TraceError, trace}; -use types::executed::CallType; + use std::sync::Arc; + use std::str::FromStr; + use rustc_serialize::hex::FromHex; + use super::*; + use util::{U256, H256, FixedHash, Address, Hashable}; + use tests::helpers::*; + use devtools::*; + use env_info::EnvInfo; + use spec::*; + use transaction::*; + use util::log::init_log; + use trace::{FlatTrace, TraceError, trace}; + use types::executed::CallType; -#[test] -fn should_apply_create_transaction() { - init_log(); + #[test] + fn should_apply_create_transaction() { + init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Create, - value: 100.into(), - data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(), - }.sign(&"".sha3(), None); - - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 0, - action: trace::Action::Create(trace::Create { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - value: 100.into(), - gas: 77412.into(), - init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85], - }), - result: trace::Res::Create(trace::CreateResult { - gas_used: U256::from(3224), - address: Address::from_str("8988167e088c87cd314df6d3c2b83da5acb93ace").unwrap(), - code: vec![96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53] - }), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_work_when_cloned() { - init_log(); - - let a = Address::zero(); - - let temp = RandomTempPath::new(); - let mut state = { + let temp = RandomTempPath::new(); let mut state = get_temp_state_in(temp.as_path()); - assert_eq!(state.exists(&a), false); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, + value: 100.into(), + data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(), + }.sign(&"".sha3(), None); + + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 0, + action: trace::Action::Create(trace::Create { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + value: 100.into(), + gas: 77412.into(), + init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85], + }), + result: trace::Res::Create(trace::CreateResult { + gas_used: U256::from(3224), + address: Address::from_str("8988167e088c87cd314df6d3c2b83da5acb93ace").unwrap(), + code: vec![96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53] + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_work_when_cloned() { + init_log(); + + let a = Address::zero(); + + let temp = RandomTempPath::new(); + let mut state = { + let mut state = get_temp_state_in(temp.as_path()); + assert_eq!(state.exists(&a), false); + state.inc_nonce(&a); + state.commit().unwrap(); + state.clone() + }; + state.inc_nonce(&a); state.commit().unwrap(); - state.clone() - }; + } - state.inc_nonce(&a); - state.commit().unwrap(); -} + #[test] + fn should_trace_failed_create_transaction() { + init_log(); -#[test] -fn should_trace_failed_create_transaction() { - init_log(); + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Create, - value: 100.into(), - data: FromHex::from_hex("5b600056").unwrap(), - }.sign(&"".sha3(), None); - - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - action: trace::Action::Create(trace::Create { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, value: 100.into(), - gas: 78792.into(), - init: vec![91, 96, 0, 86], - }), - result: trace::Res::FailedCreate(TraceError::OutOfGas), - subtraces: 0 - }]; + data: FromHex::from_hex("5b600056").unwrap(), + }.sign(&"".sha3(), None); - assert_eq!(result.trace, expected_trace); -} + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + action: trace::Action::Create(trace::Create { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + value: 100.into(), + gas: 78792.into(), + init: vec![91, 96, 0, 86], + }), + result: trace::Res::FailedCreate(TraceError::OutOfGas), + subtraces: 0 + }]; -#[test] -fn should_trace_call_transaction() { - init_log(); + assert_eq!(result.trace, expected_trace); + } - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + #[test] + fn should_trace_call_transaction() { + init_log(); - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); - state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3), - output: vec![] - }), - subtraces: 0, - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_basic_call_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(0), - output: vec![] - }), - subtraces: 0, - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_call_transaction_to_builtin() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = &*Spec::new_test().engine; - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0x1.into()), - value: 0.into(), - data: vec![], - }.sign(&"".sha3(), None); - - let result = state.apply(&info, engine, &t, true).unwrap(); - - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: "0000000000000000000000000000000000000001".into(), - value: 0.into(), - gas: 79_000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3000), - output: vec![] - }), - subtraces: 0, - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_not_trace_subcall_transaction_to_builtin() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = &*Spec::new_test().engine; - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 0.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()); - let result = state.apply(&info, engine, &t, true).unwrap(); - - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 0.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(28_061), - output: vec![] - }), - subtraces: 0, - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_not_trace_callcode() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = &*Spec::new_test().engine; - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 0.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()); - state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); - let result = state.apply(&info, engine, &t, true).unwrap(); - - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 0.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: 64.into(), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xa.into(), - value: 0.into(), - gas: 4096.into(), - input: vec![], - call_type: CallType::CallCode, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: 3.into(), - output: vec![], - }), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_not_trace_delegatecall() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - info.number = 0x789b0; - let engine = &*Spec::new_test().engine; - - println!("schedule.have_delegate_call: {:?}", engine.schedule(&info).have_delegate_call); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 0.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap()); - state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); - let result = state.apply(&info, engine, &t, true).unwrap(); - - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 0.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(61), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 0.into(), - gas: 32768.into(), - input: vec![], - call_type: CallType::DelegateCall, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: 3.into(), - output: vec![], - }), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_failed_call_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::FailedCall(TraceError::OutOfGas), - subtraces: 0, - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_call_with_subcall_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(69), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), - value: 0.into(), - gas: 78934.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3), - output: vec![] - }), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_call_with_basic_subcall_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(31761), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), - value: 69.into(), - gas: 2300.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult::default()), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_not_trace_call_with_invalid_basic_subcall_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds. - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(31761), - output: vec![] - }), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_failed_subcall_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![],//600480600b6000396000f35b600056 - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(79_000), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), - value: 0.into(), - gas: 78934.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::FailedCall(TraceError::OutOfGas), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_call_with_subcall_with_subcall_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()); - state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(135), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), - value: 0.into(), - gas: 78934.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(69), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0, 0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: 0xb.into(), - to: 0xc.into(), - value: 0.into(), - gas: 78868.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3), - output: vec![] - }), - }]; - - assert_eq!(result.trace, expected_trace); -} - -#[test] -fn should_trace_failed_subcall_with_subcall_transaction() { - init_log(); - - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); - - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); - - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![],//600480600b6000396000f35b600056 - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()); - state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), - value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(79_000), - output: vec![] - }) - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 1, + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), - value: 0.into(), - gas: 78934.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::FailedCall(TraceError::OutOfGas), - }, FlatTrace { - trace_address: vec![0, 0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Call(trace::Call { - from: 0xb.into(), - to: 0xc.into(), - value: 0.into(), - gas: 78868.into(), - call_type: CallType::Call, - input: vec![], - }), - result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3), - output: vec![] - }), - }]; + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(3), + output: vec![] + }), + subtraces: 0, + }]; - assert_eq!(result.trace, expected_trace); -} + assert_eq!(result.trace, expected_trace); + } -#[test] -fn should_trace_suicide() { - init_log(); + #[test] + fn should_trace_basic_call_transaction() { + init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); - let mut info = EnvInfo::default(); - info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); - let t = Transaction { - nonce: 0.into(), - gas_price: 0.into(), - gas: 100_000.into(), - action: Action::Call(0xa.into()), - value: 100.into(), - data: vec![], - }.sign(&"".sha3(), None); - - state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap()); - state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty); - state.add_balance(t.sender().as_ref().unwrap(), &100.into(), CleanupMode::NoEmpty); - let result = state.apply(&info, &engine, &t, true).unwrap(); - let expected_trace = vec![FlatTrace { - trace_address: Default::default(), - subtraces: 1, - action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), value: 100.into(), - gas: 79000.into(), - input: vec![], - call_type: CallType::Call, - }), - result: trace::Res::Call(trace::CallResult { - gas_used: 3.into(), - output: vec![] - }), - }, FlatTrace { - trace_address: vec![0].into_iter().collect(), - subtraces: 0, - action: trace::Action::Suicide(trace::Suicide { - address: 0xa.into(), - refund_address: 0xb.into(), - balance: 150.into(), - }), - result: trace::Res::None, - }]; + data: vec![], + }.sign(&"".sha3(), None); - assert_eq!(result.trace, expected_trace); -} + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(0), + output: vec![] + }), + subtraces: 0, + }]; -#[test] -fn code_from_database() { - let a = Address::zero(); - let temp = RandomTempPath::new(); - let (root, db) = { + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_call_transaction_to_builtin() { + init_log(); + + let temp = RandomTempPath::new(); let mut state = get_temp_state_in(temp.as_path()); - state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}); - state.init_code(&a, vec![1, 2, 3]); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = &*Spec::new_test().engine; + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0x1.into()), + value: 0.into(), + data: vec![], + }.sign(&"".sha3(), None); + + let result = state.apply(&info, engine, &t, true).unwrap(); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: "0000000000000000000000000000000000000001".into(), + value: 0.into(), + gas: 79_000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(3000), + output: vec![] + }), + subtraces: 0, + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_not_trace_subcall_transaction_to_builtin() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = &*Spec::new_test().engine; + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 0.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()); + let result = state.apply(&info, engine, &t, true).unwrap(); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(28_061), + output: vec![] + }), + subtraces: 0, + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_not_trace_callcode() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = &*Spec::new_test().engine; + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 0.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); + let result = state.apply(&info, engine, &t, true).unwrap(); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: 64.into(), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: 0xa.into(), + to: 0xa.into(), + value: 0.into(), + gas: 4096.into(), + input: vec![], + call_type: CallType::CallCode, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: 3.into(), + output: vec![], + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_not_trace_delegatecall() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + info.number = 0x789b0; + let engine = &*Spec::new_test().engine; + + println!("schedule.have_delegate_call: {:?}", engine.schedule(&info).have_delegate_call); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 0.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); + let result = state.apply(&info, engine, &t, true).unwrap(); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(61), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 32768.into(), + input: vec![], + call_type: CallType::DelegateCall, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: 3.into(), + output: vec![], + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_failed_call_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::FailedCall(TraceError::OutOfGas), + subtraces: 0, + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_call_with_subcall_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(69), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(3), + output: vec![] + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_call_with_basic_subcall_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(31761), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: 0xa.into(), + to: 0xb.into(), + value: 69.into(), + gas: 2300.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult::default()), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_not_trace_call_with_invalid_basic_subcall_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds. + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(31761), + output: vec![] + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_failed_subcall_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![],//600480600b6000396000f35b600056 + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(79_000), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::FailedCall(TraceError::OutOfGas), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_call_with_subcall_with_subcall_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()); + state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(135), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(69), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0, 0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: 0xb.into(), + to: 0xc.into(), + value: 0.into(), + gas: 78868.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(3), + output: vec![] + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_failed_subcall_with_subcall_transaction() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![],//600480600b6000396000f35b600056 + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()); + state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into()), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(79_000), + output: vec![] + }) + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::FailedCall(TraceError::OutOfGas), + }, FlatTrace { + trace_address: vec![0, 0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Call(trace::Call { + from: 0xb.into(), + to: 0xc.into(), + value: 0.into(), + gas: 78868.into(), + call_type: CallType::Call, + input: vec![], + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(3), + output: vec![] + }), + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn should_trace_suicide() { + init_log(); + + let temp = RandomTempPath::new(); + let mut state = get_temp_state_in(temp.as_path()); + + let mut info = EnvInfo::default(); + info.gas_limit = 1_000_000.into(); + let engine = TestEngine::new(5); + + let t = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), + data: vec![], + }.sign(&"".sha3(), None); + + state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap()); + state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty); + state.add_balance(t.sender().as_ref().unwrap(), &100.into(), CleanupMode::NoEmpty); + let result = state.apply(&info, &engine, &t, true).unwrap(); + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: 3.into(), + output: vec![] + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Suicide(trace::Suicide { + address: 0xa.into(), + refund_address: 0xb.into(), + balance: 150.into(), + }), + result: trace::Res::None, + }]; + + assert_eq!(result.trace, expected_trace); + } + + #[test] + fn code_from_database() { + let a = Address::zero(); + let temp = RandomTempPath::new(); + let (root, db) = { + let mut state = get_temp_state_in(temp.as_path()); + state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}); + state.init_code(&a, vec![1, 2, 3]); + assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec()))); + state.commit().unwrap(); + assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec()))); + state.drop() + }; + + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec()))); - state.commit().unwrap(); - assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec()))); - state.drop() - }; + } - let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); - assert_eq!(state.code(&a), Some(Arc::new([1u8, 2, 3].to_vec()))); -} + #[test] + fn storage_at_from_database() { + let a = Address::zero(); + let temp = RandomTempPath::new(); + let (root, db) = { + let mut state = get_temp_state_in(temp.as_path()); + state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(69u64))); + state.commit().unwrap(); + state.drop() + }; -#[test] -fn storage_at_from_database() { - let a = Address::zero(); - let temp = RandomTempPath::new(); - let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); - state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(69u64))); - state.commit().unwrap(); - state.drop() - }; + let s = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + assert_eq!(s.storage_at(&a, &H256::from(&U256::from(1u64))), H256::from(&U256::from(69u64))); + } - let s = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); - assert_eq!(s.storage_at(&a, &H256::from(&U256::from(1u64))), H256::from(&U256::from(69u64))); -} + #[test] + fn get_from_database() { + let a = Address::zero(); + let temp = RandomTempPath::new(); + let (root, db) = { + let mut state = get_temp_state_in(temp.as_path()); + state.inc_nonce(&a); + state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); + state.commit().unwrap(); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.drop() + }; -#[test] -fn get_from_database() { - let a = Address::zero(); - let temp = RandomTempPath::new(); - let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); - state.inc_nonce(&a); - state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); - state.commit().unwrap(); + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.balance(&a), U256::from(69u64)); - state.drop() - }; - - let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); - assert_eq!(state.balance(&a), U256::from(69u64)); - assert_eq!(state.nonce(&a), U256::from(1u64)); -} - -#[test] -fn remove() { - let a = Address::zero(); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - assert_eq!(state.exists(&a), false); - assert_eq!(state.exists_and_not_null(&a), false); - state.inc_nonce(&a); - assert_eq!(state.exists(&a), true); - assert_eq!(state.exists_and_not_null(&a), true); - assert_eq!(state.nonce(&a), U256::from(1u64)); - state.kill_account(&a); - assert_eq!(state.exists(&a), false); - assert_eq!(state.exists_and_not_null(&a), false); - assert_eq!(state.nonce(&a), U256::from(0u64)); -} - -#[test] -fn empty_account_is_not_created() { - let a = Address::zero(); - let path = RandomTempPath::new(); - let db = get_temp_state_db_in(path.as_path()); - let (root, db) = { - let mut state = State::new(db, U256::from(0), Default::default()); - state.add_balance(&a, &U256::default(), CleanupMode::NoEmpty); // create an empty account - state.commit().unwrap(); - state.drop() - }; - let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); - assert!(!state.exists(&a)); - assert!(!state.exists_and_not_null(&a)); -} - -#[test] -fn empty_account_exists_when_creation_forced() { - let a = Address::zero(); - let path = RandomTempPath::new(); - let db = get_temp_state_db_in(path.as_path()); - let (root, db) = { - let mut state = State::new(db, U256::from(0), Default::default()); - state.add_balance(&a, &U256::default(), CleanupMode::ForceCreate); // create an empty account - state.commit().unwrap(); - state.drop() - }; - let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); - assert!(state.exists(&a)); - assert!(!state.exists_and_not_null(&a)); -} - -#[test] -fn remove_from_database() { - let a = Address::zero(); - let temp = RandomTempPath::new(); - let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); - state.inc_nonce(&a); - state.commit().unwrap(); - assert_eq!(state.exists(&a), true); assert_eq!(state.nonce(&a), U256::from(1u64)); - state.drop() - }; + } - let (root, db) = { - let mut state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + #[test] + fn remove() { + let a = Address::zero(); + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + assert_eq!(state.exists(&a), false); + assert_eq!(state.exists_and_not_null(&a), false); + state.inc_nonce(&a); assert_eq!(state.exists(&a), true); + assert_eq!(state.exists_and_not_null(&a), true); assert_eq!(state.nonce(&a), U256::from(1u64)); state.kill_account(&a); - state.commit().unwrap(); + assert_eq!(state.exists(&a), false); + assert_eq!(state.exists_and_not_null(&a), false); + assert_eq!(state.nonce(&a), U256::from(0u64)); + } + + #[test] + fn empty_account_is_not_created() { + let a = Address::zero(); + let path = RandomTempPath::new(); + let db = get_temp_state_db_in(path.as_path()); + let (root, db) = { + let mut state = State::new(db, U256::from(0), Default::default()); + state.add_balance(&a, &U256::default(), CleanupMode::NoEmpty); // create an empty account + state.commit().unwrap(); + state.drop() + }; + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + assert!(!state.exists(&a)); + assert!(!state.exists_and_not_null(&a)); + } + + #[test] + fn empty_account_exists_when_creation_forced() { + let a = Address::zero(); + let path = RandomTempPath::new(); + let db = get_temp_state_db_in(path.as_path()); + let (root, db) = { + let mut state = State::new(db, U256::from(0), Default::default()); + state.add_balance(&a, &U256::default(), CleanupMode::ForceCreate); // create an empty account + state.commit().unwrap(); + state.drop() + }; + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + assert!(state.exists(&a)); + assert!(!state.exists_and_not_null(&a)); + } + + #[test] + fn remove_from_database() { + let a = Address::zero(); + let temp = RandomTempPath::new(); + let (root, db) = { + let mut state = get_temp_state_in(temp.as_path()); + state.inc_nonce(&a); + state.commit().unwrap(); + assert_eq!(state.exists(&a), true); + assert_eq!(state.nonce(&a), U256::from(1u64)); + state.drop() + }; + + let (root, db) = { + let mut state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + assert_eq!(state.exists(&a), true); + assert_eq!(state.nonce(&a), U256::from(1u64)); + state.kill_account(&a); + state.commit().unwrap(); + assert_eq!(state.exists(&a), false); + assert_eq!(state.nonce(&a), U256::from(0u64)); + state.drop() + }; + + let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!(state.exists(&a), false); assert_eq!(state.nonce(&a), U256::from(0u64)); - state.drop() - }; + } - let state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); - assert_eq!(state.exists(&a), false); - assert_eq!(state.nonce(&a), U256::from(0u64)); -} + #[test] + fn alter_balance() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + let a = Address::zero(); + let b = 1u64.into(); + state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.commit().unwrap(); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.sub_balance(&a, &U256::from(42u64)); + assert_eq!(state.balance(&a), U256::from(27u64)); + state.commit().unwrap(); + assert_eq!(state.balance(&a), U256::from(27u64)); + state.transfer_balance(&a, &b, &U256::from(18u64), CleanupMode::NoEmpty); + assert_eq!(state.balance(&a), U256::from(9u64)); + assert_eq!(state.balance(&b), U256::from(18u64)); + state.commit().unwrap(); + assert_eq!(state.balance(&a), U256::from(9u64)); + assert_eq!(state.balance(&b), U256::from(18u64)); + } -#[test] -fn alter_balance() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - let a = Address::zero(); - let b = 1u64.into(); - state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); - assert_eq!(state.balance(&a), U256::from(69u64)); - state.commit().unwrap(); - assert_eq!(state.balance(&a), U256::from(69u64)); - state.sub_balance(&a, &U256::from(42u64)); - assert_eq!(state.balance(&a), U256::from(27u64)); - state.commit().unwrap(); - assert_eq!(state.balance(&a), U256::from(27u64)); - state.transfer_balance(&a, &b, &U256::from(18u64), CleanupMode::NoEmpty); - assert_eq!(state.balance(&a), U256::from(9u64)); - assert_eq!(state.balance(&b), U256::from(18u64)); - state.commit().unwrap(); - assert_eq!(state.balance(&a), U256::from(9u64)); - assert_eq!(state.balance(&b), U256::from(18u64)); -} + #[test] + fn alter_nonce() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + let a = Address::zero(); + state.inc_nonce(&a); + assert_eq!(state.nonce(&a), U256::from(1u64)); + state.inc_nonce(&a); + assert_eq!(state.nonce(&a), U256::from(2u64)); + state.commit().unwrap(); + assert_eq!(state.nonce(&a), U256::from(2u64)); + state.inc_nonce(&a); + assert_eq!(state.nonce(&a), U256::from(3u64)); + state.commit().unwrap(); + assert_eq!(state.nonce(&a), U256::from(3u64)); + } -#[test] -fn alter_nonce() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - let a = Address::zero(); - state.inc_nonce(&a); - assert_eq!(state.nonce(&a), U256::from(1u64)); - state.inc_nonce(&a); - assert_eq!(state.nonce(&a), U256::from(2u64)); - state.commit().unwrap(); - assert_eq!(state.nonce(&a), U256::from(2u64)); - state.inc_nonce(&a); - assert_eq!(state.nonce(&a), U256::from(3u64)); - state.commit().unwrap(); - assert_eq!(state.nonce(&a), U256::from(3u64)); -} + #[test] + fn balance_nonce() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + let a = Address::zero(); + assert_eq!(state.balance(&a), U256::from(0u64)); + assert_eq!(state.nonce(&a), U256::from(0u64)); + state.commit().unwrap(); + assert_eq!(state.balance(&a), U256::from(0u64)); + assert_eq!(state.nonce(&a), U256::from(0u64)); + } -#[test] -fn balance_nonce() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - let a = Address::zero(); - assert_eq!(state.balance(&a), U256::from(0u64)); - assert_eq!(state.nonce(&a), U256::from(0u64)); - state.commit().unwrap(); - assert_eq!(state.balance(&a), U256::from(0u64)); - assert_eq!(state.nonce(&a), U256::from(0u64)); -} + #[test] + fn ensure_cached() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + let a = Address::zero(); + state.require(&a, false); + state.commit().unwrap(); + assert_eq!(state.root().hex(), "0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785"); + } -#[test] -fn ensure_cached() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - let a = Address::zero(); - state.require(&a, false); - state.commit().unwrap(); - assert_eq!(state.root().hex(), "0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785"); -} + #[test] + fn checkpoint_basic() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + let a = Address::zero(); + state.checkpoint(); + state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.discard_checkpoint(); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.checkpoint(); + state.add_balance(&a, &U256::from(1u64), CleanupMode::NoEmpty); + assert_eq!(state.balance(&a), U256::from(70u64)); + state.revert_to_checkpoint(); + assert_eq!(state.balance(&a), U256::from(69u64)); + } -#[test] -fn checkpoint_basic() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - let a = Address::zero(); - state.checkpoint(); - state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); - assert_eq!(state.balance(&a), U256::from(69u64)); - state.discard_checkpoint(); - assert_eq!(state.balance(&a), U256::from(69u64)); - state.checkpoint(); - state.add_balance(&a, &U256::from(1u64), CleanupMode::NoEmpty); - assert_eq!(state.balance(&a), U256::from(70u64)); - state.revert_to_checkpoint(); - assert_eq!(state.balance(&a), U256::from(69u64)); -} + #[test] + fn checkpoint_nested() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + let a = Address::zero(); + state.checkpoint(); + state.checkpoint(); + state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.discard_checkpoint(); + assert_eq!(state.balance(&a), U256::from(69u64)); + state.revert_to_checkpoint(); + assert_eq!(state.balance(&a), U256::from(0)); + } -#[test] -fn checkpoint_nested() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - let a = Address::zero(); - state.checkpoint(); - state.checkpoint(); - state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty); - assert_eq!(state.balance(&a), U256::from(69u64)); - state.discard_checkpoint(); - assert_eq!(state.balance(&a), U256::from(69u64)); - state.revert_to_checkpoint(); - assert_eq!(state.balance(&a), U256::from(0)); -} + #[test] + fn create_empty() { + let mut state_result = get_temp_state(); + let mut state = state_result.reference_mut(); + state.commit().unwrap(); + assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); + } -#[test] -fn create_empty() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - state.commit().unwrap(); - assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); -} + #[test] + fn should_not_panic_on_state_diff_with_storage() { + let state = get_temp_state(); + let mut state = state.reference().clone(); -#[test] -fn should_not_panic_on_state_diff_with_storage() { - let state = get_temp_state(); - let mut state = state.reference().clone(); + let a: Address = 0xa.into(); + state.init_code(&a, b"abcdefg".to_vec()); + state.add_balance(&a, &256.into(), CleanupMode::NoEmpty); + state.set_storage(&a, 0xb.into(), 0xc.into()); - let a: Address = 0xa.into(); - state.init_code(&a, b"abcdefg".to_vec()); - state.add_balance(&a, &256.into(), CleanupMode::NoEmpty); - state.set_storage(&a, 0xb.into(), 0xc.into()); + let mut new_state = state.clone(); + new_state.set_storage(&a, 0xb.into(), 0xd.into()); - let mut new_state = state.clone(); - new_state.set_storage(&a, 0xb.into(), 0xd.into()); - - new_state.diff_from(state); -} + new_state.diff_from(state); + } } From cd6f565f69d71deead5336be2b71f3ff396ba37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 22 Nov 2016 11:56:27 +0100 Subject: [PATCH 02/52] RPC Middleware & Get/Set dapp-specific accounts --- Cargo.lock | 92 +++---- Cargo.toml | 1 - dapps/Cargo.toml | 4 +- dapps/src/rpc.rs | 94 ++++++- .../mod.rs} | 136 +++------- ethcore/src/account_provider/stores.rs | 247 ++++++++++++++++++ json/src/misc/account_meta.rs | 2 +- json/src/misc/dapps_settings.rs | 51 ++++ json/src/misc/mod.rs | 2 + parity/main.rs | 2 - parity/rpc.rs | 8 +- rpc/Cargo.toml | 6 +- rpc/src/lib.rs | 7 +- rpc/src/v1/impls/eth.rs | 15 +- rpc/src/v1/impls/parity_accounts.rs | 11 +- rpc/src/v1/tests/eth.rs | 2 +- rpc/src/v1/tests/mocked/eth.rs | 16 +- rpc/src/v1/tests/mocked/net.rs | 2 +- rpc/src/v1/tests/mocked/parity.rs | 2 +- rpc/src/v1/tests/mocked/parity_accounts.rs | 17 +- rpc/src/v1/tests/mocked/parity_set.rs | 2 +- rpc/src/v1/tests/mocked/personal.rs | 2 +- rpc/src/v1/tests/mocked/rpc.rs | 2 +- rpc/src/v1/tests/mocked/signer.rs | 2 +- rpc/src/v1/tests/mocked/signing.rs | 48 ++-- rpc/src/v1/tests/mocked/web3.rs | 2 +- rpc/src/v1/traits/eth.rs | 4 +- rpc/src/v1/traits/parity_accounts.rs | 8 +- rpc/src/v1/types/dapp_id.rs | 60 +++++ rpc/src/v1/types/mod.rs.in | 2 + signer/Cargo.toml | 2 +- signer/src/ws_server/session.rs | 20 +- stratum/Cargo.toml | 4 +- stratum/src/lib.rs | 4 +- 34 files changed, 655 insertions(+), 224 deletions(-) rename ethcore/src/{account_provider.rs => account_provider/mod.rs} (80%) create mode 100644 ethcore/src/account_provider/stores.rs create mode 100644 json/src/misc/dapps_settings.rs create mode 100644 rpc/src/v1/types/dapp_id.rs diff --git a/Cargo.lock b/Cargo.lock index 02e45b49e..eaede16ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,6 @@ dependencies = [ "fdlimit 0.1.0", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -341,8 +340,8 @@ dependencies = [ "ethcore-util 1.5.0", "fetch 0.1.0", "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -503,9 +502,9 @@ dependencies = [ "ethstore 0.1.0", "ethsync 1.5.0", "fetch 0.1.0", - "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.1.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -526,7 +525,7 @@ dependencies = [ "ethcore-io 1.5.0", "ethcore-rpc 1.5.0", "ethcore-util 1.5.0", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-ui 1.4.0", @@ -545,8 +544,8 @@ dependencies = [ "ethcore-ipc-codegen 1.4.0", "ethcore-ipc-nano 1.4.0", "ethcore-util 1.5.0", - "json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", @@ -831,39 +830,10 @@ name = "itoa" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "json-ipc-server" -version = "0.2.4" -source = "git+https://github.com/ethcore/json-ipc-server.git#4642cd03ec1d23db89df80d22d5a88e7364ab885" -dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "json-tcp-server" -version = "0.1.0" -source = "git+https://github.com/ethcore/json-tcp-server#c2858522274ae56042472bb5d22845a1b85e5338" -dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpc-core" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "4.0.0" +source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -875,14 +845,44 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc-http-server.git#cd6d4cb37d672cc3057aecd0692876f9e85f3ba5" +source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" dependencies = [ "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-ipc-server" +version = "0.2.4" +source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpc-tcp-server" +version = "0.1.0" +source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -2032,10 +2032,10 @@ dependencies = [ "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" "checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" -"checksum json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)" = "" -"checksum json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)" = "" -"checksum jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5094610b07f28f3edaf3947b732dadb31dbba4941d4d0c1c7a8350208f4414" -"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)" = "" +"checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "" +"checksum jsonrpc-tcp-server 0.1.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" diff --git a/Cargo.toml b/Cargo.toml index a8d7ba794..871e2f0a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ serde = "0.8.0" serde_json = "0.8.0" hyper = { version = "0.9", default-features = false } ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" } -json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } fdlimit = { path = "util/fdlimit" } ethcore = { path = "ethcore" } ethcore-util = { path = "util" } diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 15e537820..b8b0e3c78 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -12,8 +12,8 @@ build = "build.rs" rand = "0.3.14" log = "0.3" env_logger = "0.3" -jsonrpc-core = "3.0" -jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } hyper = { default-features = false, git = "https://github.com/ethcore/hyper" } unicase = "1.3" url = "1.0" diff --git a/dapps/src/rpc.rs b/dapps/src/rpc.rs index 625bfc269..cb595e1e1 100644 --- a/dapps/src/rpc.rs +++ b/dapps/src/rpc.rs @@ -16,13 +16,14 @@ use std::sync::{Arc, Mutex}; use hyper; -use jsonrpc_core::IoHandler; -use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin}; + +use jsonrpc_core::{IoHandler, ResponseHandler, Request, Response}; +use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin, RpcHandler}; use endpoint::{Endpoint, EndpointPath, Handler}; pub fn rpc(handler: Arc, panic_handler: Arc () + Send>>>>) -> Box { Box::new(RpcEndpoint { - handler: handler, + handler: Arc::new(RpcMiddleware::new(handler)), panic_handler: panic_handler, cors_domain: None, // NOTE [ToDr] We don't need to do any hosts validation here. It's already done in router. @@ -31,7 +32,7 @@ pub fn rpc(handler: Arc, panic_handler: Arc } struct RpcEndpoint { - handler: Arc, + handler: Arc, panic_handler: Arc () + Send>>>>, cors_domain: Option>, allowed_hosts: Option>, @@ -49,3 +50,88 @@ impl Endpoint for RpcEndpoint { )) } } + +const MIDDLEWARE_METHOD: &'static str = "eth_accounts"; + +struct RpcMiddleware { + handler: Arc, +} + +impl RpcMiddleware { + fn new(handler: Arc) -> Self { + RpcMiddleware { + handler: handler, + } + } + + /// Appends additional parameter for specific calls. + fn augment_request(&self, request: &mut Request, meta: Option) { + use jsonrpc_core::{Call, Params, to_value}; + + fn augment_call(call: &mut Call, meta: Option<&Meta>) { + match (call, meta) { + (&mut Call::MethodCall(ref mut method_call), Some(meta)) if &method_call.method == MIDDLEWARE_METHOD => { + let session = to_value(&meta.app_id); + + let params = match method_call.params { + Some(Params::Array(ref vec)) if vec.len() == 0 => Some(Params::Array(vec![session])), + // invalid params otherwise + _ => None, + }; + + method_call.params = params; + }, + _ => {} + } + } + + match *request { + Request::Single(ref mut call) => augment_call(call, meta.as_ref()), + Request::Batch(ref mut vec) => { + for mut call in vec { + augment_call(call, meta.as_ref()) + } + }, + } + } +} + +#[derive(Debug)] +struct Meta { + app_id: String, +} + +impl RpcHandler for RpcMiddleware { + type Metadata = Meta; + + fn read_metadata(&self, request: &hyper::server::Request) -> Option { + let meta = request.headers().get::() + .and_then(|referer| hyper::Url::parse(referer).ok()) + .and_then(|url| { + url.path_segments() + .and_then(|mut split| split.next()) + .map(|app_id| Meta { + app_id: app_id.to_owned(), + }) + }); + println!("{:?}, {:?}", meta, request.headers()); + meta + } + + fn handle_request(&self, request_str: &str, response_handler: H, meta: Option) where + H: ResponseHandler, Option> + 'static + { + let handler = IoHandler::convert_handler(response_handler); + let request = IoHandler::read_request(request_str); + trace!(target: "rpc", "Request metadata: {:?}", meta); + + match request { + Ok(mut request) => { + self.augment_request(&mut request, meta); + self.handler.request_handler().handle_request(request, handler, None) + }, + Err(error) => handler.send(Some(Response::from(error))), + } + } +} + diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider/mod.rs similarity index 80% rename from ethcore/src/account_provider.rs rename to ethcore/src/account_provider/mod.rs index e906aefe9..75c3e2683 100644 --- a/ethcore/src/account_provider.rs +++ b/ethcore/src/account_provider/mod.rs @@ -16,9 +16,12 @@ //! Account management. -use std::{fs, fmt}; +mod stores; + +use self::stores::{AddressBook, DappsSettingsStore}; + +use std::fmt; use std::collections::HashMap; -use std::path::PathBuf; use std::time::{Instant, Duration}; use util::{Mutex, RwLock}; use ethstore::{SecretStore, Error as SSError, SafeAccount, EthStore}; @@ -91,84 +94,16 @@ impl KeyDirectory for NullDir { } } -/// Disk-backed map from Address to String. Uses JSON. -struct AddressBook { - path: PathBuf, - cache: HashMap, - transient: bool, -} - -impl AddressBook { - pub fn new(path: String) -> Self { - trace!(target: "addressbook", "new({})", path); - let mut path: PathBuf = path.into(); - path.push("address_book.json"); - trace!(target: "addressbook", "path={:?}", path); - let mut r = AddressBook { - path: path, - cache: HashMap::new(), - transient: false, - }; - r.revert(); - r - } - - pub fn transient() -> Self { - let mut book = AddressBook::new(Default::default()); - book.transient = true; - book - } - - pub fn get(&self) -> HashMap { - self.cache.clone() - } - - pub fn set_name(&mut self, a: Address, name: String) { - let mut x = self.cache.get(&a) - .cloned() - .unwrap_or_else(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None}); - x.name = name; - self.cache.insert(a, x); - self.save(); - } - - pub fn set_meta(&mut self, a: Address, meta: String) { - let mut x = self.cache.get(&a) - .cloned() - .unwrap_or_else(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None}); - x.meta = meta; - self.cache.insert(a, x); - self.save(); - } - - fn revert(&mut self) { - if self.transient { return; } - trace!(target: "addressbook", "revert"); - let _ = fs::File::open(self.path.clone()) - .map_err(|e| trace!(target: "addressbook", "Couldn't open address book: {}", e)) - .and_then(|f| AccountMeta::read_address_map(&f) - .map_err(|e| warn!(target: "addressbook", "Couldn't read address book: {}", e)) - .and_then(|m| { self.cache = m; Ok(()) }) - ); - } - - fn save(&mut self) { - if self.transient { return; } - trace!(target: "addressbook", "save"); - let _ = fs::File::create(self.path.clone()) - .map_err(|e| warn!(target: "addressbook", "Couldn't open address book for writing: {}", e)) - .and_then(|mut f| AccountMeta::write_address_map(&self.cache, &mut f) - .map_err(|e| warn!(target: "addressbook", "Couldn't write to address book: {}", e)) - ); - } -} +/// Dapp identifier +pub type DappId = String; /// Account management. /// Responsible for unlocking accounts. pub struct AccountProvider { unlocked: Mutex>, sstore: Box, - address_book: Mutex, + address_book: RwLock, + dapps_settings: RwLock, } impl AccountProvider { @@ -176,7 +111,8 @@ impl AccountProvider { pub fn new(sstore: Box) -> Self { AccountProvider { unlocked: Mutex::new(HashMap::new()), - address_book: Mutex::new(AddressBook::new(sstore.local_path().into())), + address_book: RwLock::new(AddressBook::new(sstore.local_path().into())), + dapps_settings: RwLock::new(DappsSettingsStore::new(sstore.local_path().into())), sstore: sstore, } } @@ -185,7 +121,8 @@ impl AccountProvider { pub fn transient_provider() -> Self { AccountProvider { unlocked: Mutex::new(HashMap::new()), - address_book: Mutex::new(AddressBook::transient()), + address_book: RwLock::new(AddressBook::transient()), + dapps_settings: RwLock::new(DappsSettingsStore::transient()), sstore: Box::new(EthStore::open(Box::new(NullDir::default())) .expect("NullDir load always succeeds; qed")) } @@ -230,19 +167,31 @@ impl AccountProvider { Ok(accounts) } + /// Gets addresses visile for dapp. + pub fn dapps_addresses(&self, dapp: DappId) -> Result, Error> { + let accounts = self.dapps_settings.read().get(); + Ok(accounts.get(&dapp).map(|settings| settings.accounts.clone()).unwrap_or_else(Vec::new)) + } + + /// Sets addresses visile for dapp. + pub fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec
) -> Result<(), Error> { + self.dapps_settings.write().set_accounts(dapp, addresses); + Ok(()) + } + /// Returns each address along with metadata. pub fn addresses_info(&self) -> Result, Error> { - Ok(self.address_book.lock().get()) + Ok(self.address_book.read().get()) } /// Returns each address along with metadata. pub fn set_address_name(&self, account: Address, name: String) -> Result<(), Error> { - Ok(self.address_book.lock().set_name(account, name)) + Ok(self.address_book.write().set_name(account, name)) } /// Returns each address along with metadata. pub fn set_address_meta(&self, account: Address, meta: String) -> Result<(), Error> { - Ok(self.address_book.lock().set_meta(account, meta)) + Ok(self.address_book.write().set_meta(account, meta)) } /// Returns each account along with name and meta. @@ -373,23 +322,9 @@ impl AccountProvider { #[cfg(test)] mod tests { - use super::{AccountProvider, AddressBook, Unlock}; - use std::collections::HashMap; + use super::{AccountProvider, Unlock}; use std::time::Instant; - use ethjson::misc::AccountMeta; use ethstore::ethkey::{Generator, Random}; - use devtools::RandomTempPath; - - #[test] - fn should_save_and_reload_address_book() { - let temp = RandomTempPath::create_dir(); - let path = temp.as_str().to_owned(); - let mut b = AddressBook::new(path.clone()); - b.set_name(1.into(), "One".to_owned()); - b.set_meta(1.into(), "{1:1}".to_owned()); - let b = AddressBook::new(path); - assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]); - } #[test] fn unlock_account_temp() { @@ -427,4 +362,17 @@ mod tests { ap.unlocked.lock().get_mut(&kp.address()).unwrap().unlock = Unlock::Timed(Instant::now()); assert!(ap.sign(kp.address(), None, Default::default()).is_err()); } + + #[test] + fn should_set_dapps_addresses() { + // given + let ap = AccountProvider::transient_provider(); + let app = "app1".to_owned(); + + // when + ap.set_dapps_addresses(app.clone(), vec![1.into(), 2.into()]).unwrap(); + + // then + assert_eq!(ap.dapps_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]); + } } diff --git a/ethcore/src/account_provider/stores.rs b/ethcore/src/account_provider/stores.rs new file mode 100644 index 000000000..cfc81f495 --- /dev/null +++ b/ethcore/src/account_provider/stores.rs @@ -0,0 +1,247 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Address Book and Dapps Settings Store + +use std::{fs, fmt, hash, ops}; +use std::collections::HashMap; +use std::path::PathBuf; + +use ethstore::ethkey::Address; +use ethjson::misc::{AccountMeta, DappsSettings as JsonSettings}; +use account_provider::DappId; + +/// Disk-backed map from Address to String. Uses JSON. +pub struct AddressBook { + cache: DiskMap, +} + +impl AddressBook { + /// Creates new address book at given directory. + pub fn new(path: String) -> Self { + let mut r = AddressBook { + cache: DiskMap::new(path, "address_book.json".into()) + }; + r.cache.revert(AccountMeta::read_address_map); + r + } + + /// Creates transient address book (no changes are saved to disk). + pub fn transient() -> Self { + AddressBook { + cache: DiskMap::transient() + } + } + + /// Get the address book. + pub fn get(&self) -> HashMap { + self.cache.clone() + } + + fn save(&self) { + self.cache.save(AccountMeta::write_address_map) + } + + /// Sets new name for given address. + pub fn set_name(&mut self, a: Address, name: String) { + { + let mut x = self.cache.entry(a) + .or_insert_with(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None}); + x.name = name; + } + self.save(); + } + + /// Sets new meta for given address. + pub fn set_meta(&mut self, a: Address, meta: String) { + { + let mut x = self.cache.entry(a) + .or_insert_with(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None}); + x.meta = meta; + } + self.save(); + } +} + +/// Dapps user settings +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub struct DappsSettings { + /// A list of visible accounts + pub accounts: Vec
, +} + +impl From for DappsSettings { + fn from(s: JsonSettings) -> Self { + DappsSettings { + accounts: s.accounts.into_iter().map(Into::into).collect(), + } + } +} + +impl From for JsonSettings { + fn from(s: DappsSettings) -> Self { + JsonSettings { + accounts: s.accounts.into_iter().map(Into::into).collect(), + } + } +} + +/// Disk-backed map from DappId to Settings. Uses JSON. +pub struct DappsSettingsStore { + cache: DiskMap, +} + +impl DappsSettingsStore { + /// Creates new store at given directory path. + pub fn new(path: String) -> Self { + let mut r = DappsSettingsStore { + cache: DiskMap::new(path, "dapps_accounts.json".into()) + }; + r.cache.revert(JsonSettings::read_dapps_settings); + r + } + + /// Creates transient store (no changes are saved to disk). + pub fn transient() -> Self { + DappsSettingsStore { + cache: DiskMap::transient() + } + } + + /// Get copy of the dapps settings + pub fn get(&self) -> HashMap { + self.cache.clone() + } + + fn save(&self) { + self.cache.save(JsonSettings::write_dapps_settings) + } + + pub fn set_accounts(&mut self, id: DappId, accounts: Vec
) { + { + let mut settings = self.cache.entry(id).or_insert_with(DappsSettings::default); + settings.accounts = accounts; + } + self.save(); + } +} + +/// Disk-serializable HashMap +#[derive(Debug)] +struct DiskMap { + path: PathBuf, + cache: HashMap, + transient: bool, +} + +impl ops::Deref for DiskMap { + type Target = HashMap; + fn deref(&self) -> &Self::Target { + &self.cache + } +} + +impl ops::DerefMut for DiskMap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.cache + } +} + +impl DiskMap { + pub fn new(path: String, file_name: String) -> Self { + trace!(target: "diskmap", "new({})", path); + let mut path: PathBuf = path.into(); + path.push(file_name); + trace!(target: "diskmap", "path={:?}", path); + DiskMap { + path: path, + cache: HashMap::new(), + transient: false, + } + } + + pub fn transient() -> Self { + let mut map = DiskMap::new(Default::default(), "diskmap.json".into()); + map.transient = true; + map + } + + fn revert(&mut self, read: F) where + F: Fn(fs::File) -> Result, E>, + E: fmt::Display, + { + if self.transient { return; } + trace!(target: "diskmap", "revert {:?}", self.path); + let _ = fs::File::open(self.path.clone()) + .map_err(|e| trace!(target: "diskmap", "Couldn't open disk map: {}", e)) + .and_then(|f| read(f).map_err(|e| warn!(target: "diskmap", "Couldn't read disk map: {}", e))) + .and_then(|m| { + self.cache = m; + Ok(()) + }); + } + + fn save(&self, write: F) where + F: Fn(&HashMap, &mut fs::File) -> Result<(), E>, + E: fmt::Display, + { + if self.transient { return; } + trace!(target: "diskmap", "save {:?}", self.path); + let _ = fs::File::create(self.path.clone()) + .map_err(|e| warn!(target: "diskmap", "Couldn't open disk map for writing: {}", e)) + .and_then(|mut f| { + write(&self.cache, &mut f).map_err(|e| warn!(target: "diskmap", "Couldn't write to disk map: {}", e)) + }); + } +} + +#[cfg(test)] +mod tests { + use super::{AddressBook, DappsSettingsStore, DappsSettings}; + use std::collections::HashMap; + use ethjson::misc::AccountMeta; + use devtools::RandomTempPath; + + #[test] + fn should_save_and_reload_address_book() { + let temp = RandomTempPath::create_dir(); + let path = temp.as_str().to_owned(); + let mut b = AddressBook::new(path.clone()); + b.set_name(1.into(), "One".to_owned()); + b.set_meta(1.into(), "{1:1}".to_owned()); + let b = AddressBook::new(path); + assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]); + } + + #[test] + fn should_save_and_reload_dapps_settings() { + // given + let temp = RandomTempPath::create_dir(); + let path = temp.as_str().to_owned(); + let mut b = DappsSettingsStore::new(path.clone()); + + // when + b.set_accounts("dappOne".into(), vec![1.into(), 2.into()]); + + // then + let b = DappsSettingsStore::new(path); + assert_eq!(b.get(), hash_map![ + "dappOne".into() => DappsSettings { + accounts: vec![1.into(), 2.into()], + } + ]); + } +} diff --git a/json/src/misc/account_meta.rs b/json/src/misc/account_meta.rs index 242b58a01..400f9b8df 100644 --- a/json/src/misc/account_meta.rs +++ b/json/src/misc/account_meta.rs @@ -51,7 +51,7 @@ impl AccountMeta { ) } - /// Write a hash map of Address -> AccountMeta. + /// Write a hash map of Address -> AccountMeta. pub fn write_address_map(m: &HashMap, writer: &mut W) -> Result<(), serde_json::Error> where W: Write { serde_json::to_writer(writer, &m.iter().map(|(a, m)| (a.clone().into(), m)).collect::>()) } diff --git a/json/src/misc/dapps_settings.rs b/json/src/misc/dapps_settings.rs new file mode 100644 index 000000000..893e7e93e --- /dev/null +++ b/json/src/misc/dapps_settings.rs @@ -0,0 +1,51 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Dapps settings de/serialization. + +use std::io; +use std::collections::HashMap; +use serde_json; +use hash; + +type DappId = String; + +/// Settings for specific dapp. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct DappsSettings { + /// A list of accounts this Dapp can see. + pub accounts: Vec, +} + +impl DappsSettings { + /// Read a hash map of DappId -> DappsSettings + pub fn read_dapps_settings(reader: R) -> Result, serde_json::Error> where + R: io::Read, + S: From + Clone, + { + serde_json::from_reader(reader).map(|ok: HashMap| + ok.into_iter().map(|(a, m)| (a.into(), m.into())).collect() + ) + } + + /// Write a hash map of DappId -> DappsSettings + pub fn write_dapps_settings(m: &HashMap, writer: &mut W) -> Result<(), serde_json::Error> where + W: io::Write, + S: Into + Clone, + { + serde_json::to_writer(writer, &m.iter().map(|(a, m)| (a.clone().into(), m.clone().into())).collect::>()) + } +} diff --git a/json/src/misc/mod.rs b/json/src/misc/mod.rs index 5db868d03..baab83d08 100644 --- a/json/src/misc/mod.rs +++ b/json/src/misc/mod.rs @@ -17,5 +17,7 @@ //! Misc deserialization. mod account_meta; +mod dapps_settings; +pub use self::dapps_settings::DappsSettings; pub use self::account_meta::AccountMeta; diff --git a/parity/main.rs b/parity/main.rs index 274d29de2..c125e87f6 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -44,8 +44,6 @@ extern crate serde_json; extern crate rlp; extern crate ethcore_hash_fetch as hash_fetch; -extern crate json_ipc_server as jsonipc; - extern crate ethcore_ipc_hypervisor as hypervisor; extern crate ethcore_rpc; diff --git a/parity/rpc.rs b/parity/rpc.rs index 59279eaea..52a5bcc0f 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -19,14 +19,12 @@ use std::sync::Arc; use std::net::SocketAddr; use std::io; use io::PanicHandler; -use ethcore_rpc::{RpcServerError, RpcServer as Server}; -use jsonipc; +use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError}; use rpc_apis; use rpc_apis::ApiSet; use helpers::parity_ipc_path; -pub use jsonipc::Server as IpcServer; -pub use ethcore_rpc::Server as HttpServer; +pub use ethcore_rpc::{IpcServer, Server as HttpServer}; #[derive(Debug, PartialEq)] pub struct HttpConfiguration { @@ -126,7 +124,7 @@ pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result Result { let server = try!(setup_rpc_server(apis, dependencies)); match server.start_ipc(addr) { - Err(jsonipc::Error::Io(io_error)) => Err(format!("RPC io error: {}", io_error)), + Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)), Err(any_error) => Err(format!("Rpc error: {:?}", any_error)), Ok(server) => Ok(server) } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 4a8c4d76a..68470b963 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -12,8 +12,9 @@ build = "build.rs" log = "0.3" serde = "0.8" serde_json = "0.8" -jsonrpc-core = "3.0" -jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" } ethcore-io = { path = "../util/io" } ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } @@ -30,7 +31,6 @@ rustc-serialize = "0.3" transient-hashmap = "0.1" serde_macros = { version = "0.8.0", optional = true } clippy = { version = "0.0.96", optional = true} -json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } ethcore-ipc = { path = "../ipc/rpc" } time = "0.1" diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 3b67ae7f0..e02a18509 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -32,7 +32,7 @@ extern crate ethcrypto as crypto; extern crate ethstore; extern crate ethsync; extern crate transient_hashmap; -extern crate json_ipc_server as ipc; +extern crate jsonrpc_ipc_server as ipc; extern crate ethcore_ipc; extern crate time; extern crate rlp; @@ -51,8 +51,9 @@ extern crate ethcore_devtools as devtools; use std::sync::Arc; use std::net::SocketAddr; use io::PanicHandler; -use self::jsonrpc_core::{IoHandler, IoDelegate}; +use jsonrpc_core::{IoHandler, IoDelegate}; +pub use ipc::{Server as IpcServer, Error as IpcServerError}; pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError}; pub mod v1; pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings}; @@ -66,7 +67,7 @@ pub trait Extendable { /// Http server. pub struct RpcServer { - handler: Arc, + handler: Arc, } impl Extendable for RpcServer { diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5f1449e07..6b9f47de3 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -20,7 +20,6 @@ extern crate ethash; use std::io::{Write}; use std::process::{Command, Stdio}; -use std::collections::BTreeSet; use std::thread; use std::time::{Instant, Duration}; use std::sync::{Arc, Weak}; @@ -46,7 +45,7 @@ use self::ethash::SeedHashCompute; use v1::traits::Eth; use v1::types::{ RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, - Transaction, CallRequest, Index, Filter, Log, Receipt, Work, + Transaction, CallRequest, Index, Filter, Log, Receipt, Work, DappId, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256, }; use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; @@ -335,15 +334,15 @@ impl Eth for EthClient where Ok(RpcU256::from(default_gas_price(&*client, &*miner))) } - fn accounts(&self) -> Result, Error> { + fn accounts(&self, id: Trailing) -> Result, Error> { try!(self.active()); - let store = take_weak!(self.accounts); - let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e))); - let addresses = try!(store.addresses_info().map_err(|e| errors::internal("Could not fetch accounts.", e))); + let dapp = id.0; - let set: BTreeSet
= accounts.into_iter().chain(addresses.keys().cloned()).collect(); - Ok(set.into_iter().map(Into::into).collect()) + let store = take_weak!(self.accounts); + let accounts = try!(store.dapps_addresses(dapp.into()).map_err(|e| errors::internal("Could not fetch accounts.", e))); + + Ok(accounts.into_iter().map(Into::into).collect()) } fn block_number(&self) -> Result { diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index 2644c59e3..25d3c0904 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -25,7 +25,7 @@ use ethcore::client::MiningBlockChainClient; use jsonrpc_core::{Value, Error, to_value}; use v1::traits::ParityAccounts; -use v1::types::{H160 as RpcH160, H256 as RpcH256}; +use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId}; use v1::helpers::errors; /// Account management (personal) rpc implementation. @@ -143,6 +143,15 @@ impl ParityAccounts for ParityAccountsClient where C: MiningBlock Ok(false) } + fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec) -> Result { + let store = take_weak!(self.accounts); + let addresses = addresses.into_iter().map(Into::into).collect(); + + store.set_dapps_addresses(dapp.into(), addresses) + .map_err(|e| errors::account("Couldn't set dapps addresses.", e)) + .map(|_| true) + } + fn import_geth_accounts(&self, addresses: Vec) -> Result, Error> { let store = take_weak!(self.accounts); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 2f5131f32..7894fa111 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -30,7 +30,7 @@ use devtools::RandomTempPath; use util::Hashable; use io::IoChannel; use util::{U256, H256, Uint, Address}; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use ethjson::blockchain::BlockChain; use v1::impls::{EthClient, SigningUnsafeClient}; diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 861bb5234..2f31aa4e1 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -31,7 +31,7 @@ use ethcore::transaction::{Transaction, Action}; use ethcore::miner::{ExternalMiner, MinerService}; use ethsync::SyncState; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService}; @@ -357,15 +357,15 @@ fn rpc_eth_accounts() { let address = tester.accounts_provider.new_account("").unwrap(); let address2 = Address::default(); - tester.accounts_provider.set_address_name(address2, "Test Account".into()).unwrap(); - + // even with some account it should return empty list (no dapp detected) let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() - + &format!("0x{:?}", address2) - + r#"",""# - + &format!("0x{:?}", address) - + r#""],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#; + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); + // when we add visible address it should return that. + tester.accounts_provider.set_dapps_addresses("app1".into(), vec![10.into()]).unwrap(); + let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": ["app1"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#; assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/net.rs b/rpc/src/v1/tests/mocked/net.rs index 0a5eb43e7..37ef84fca 100644 --- a/rpc/src/v1/tests/mocked/net.rs +++ b/rpc/src/v1/tests/mocked/net.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::sync::Arc; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Net, NetClient}; use v1::tests::helpers::{Config, TestSyncProvider}; diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 5226e2f96..9b4daaccd 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -23,7 +23,7 @@ use ethcore::client::{TestBlockChainClient}; use ethcore::miner::LocalTransactionStatus; use ethstore::ethkey::{Generator, Random}; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Parity, ParityClient}; use v1::helpers::{SignerService, NetworkSettings}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs index c5ed4172e..bd6e1ffba 100644 --- a/rpc/src/v1/tests/mocked/parity_accounts.rs +++ b/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{ParityAccounts, ParityAccountsClient}; struct ParityAccountsTester { @@ -116,3 +116,18 @@ fn should_be_able_to_set_meta() { assert_eq!(res, Some(response)); } + +#[test] +fn rpc_parity_set_dapps_accounts() { + // given + let tester = setup(); + assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![]); + + // when + let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappsAddresses","params":["app1",["0x000000000000000000000000000000000000000a"]], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); + + // then + assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![10.into()]); +} diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 3202374a7..01f33e251 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -23,7 +23,7 @@ use ethcore::miner::MinerService; use ethcore::client::TestBlockChainClient; use ethsync::ManageNetwork; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{ParitySet, ParitySetClient}; use v1::tests::helpers::{TestMinerService, TestFetch}; use super::manage_network::TestManageNetwork; diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 6e2de1e2e..a1e8fe982 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use std::str::FromStr; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use util::{U256, Uint, Address}; use ethcore::account_provider::AccountProvider; use v1::{PersonalClient, Personal}; diff --git a/rpc/src/v1/tests/mocked/rpc.rs b/rpc/src/v1/tests/mocked/rpc.rs index b2c340d94..44406f4e3 100644 --- a/rpc/src/v1/tests/mocked/rpc.rs +++ b/rpc/src/v1/tests/mocked/rpc.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::collections::BTreeMap; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{Rpc, RpcClient}; diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index e2ba580e0..912dddc81 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -23,7 +23,7 @@ use ethcore::client::TestBlockChainClient; use ethcore::transaction::{Transaction, Action}; use rlp::encode; -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use v1::{SignerClient, Signer}; use v1::tests::helpers::TestMinerService; use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload}; diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 7431bc45e..629fbe707 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -15,10 +15,10 @@ // along with Parity. If not, see . use std::str::FromStr; -use std::sync::Arc; +use std::sync::{mpsc, Arc}; use rlp; -use jsonrpc_core::{IoHandler, Success}; +use jsonrpc_core::{IoHandler, Success, GenericIoHandler}; use v1::impls::SigningQueueClient; use v1::traits::{EthSigning, ParitySigning, Parity}; use v1::helpers::{SignerService, SigningQueue}; @@ -87,13 +87,16 @@ fn should_add_sign_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - let async_result = tester.io.handle_request(&request).unwrap(); + let (tx, rx) = mpsc::channel(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Signature(0.into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } #[test] @@ -227,13 +230,16 @@ fn should_add_transaction_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - let async_result = tester.io.handle_request(&request).unwrap(); + let (tx, rx) = mpsc::channel(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SendTransaction(0.into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } #[test] @@ -289,14 +295,17 @@ fn should_add_sign_transaction_to_the_queue() { r#"}},"id":1}"#; // then + let (tx, rx) = mpsc::channel(); tester.miner.last_nonces.write().insert(address.clone(), U256::zero()); - let async_result = tester.io.handle_request(&request).unwrap(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } #[test] @@ -387,11 +396,14 @@ fn should_add_decryption_to_the_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#; // then - let async_result = tester.io.handle_request(&request).unwrap(); + let (tx, rx) = mpsc::channel(); + tester.io.handle_request(&request, move |response| { + tx.send(response).unwrap(); + }); assert_eq!(tester.signer.requests().len(), 1); // respond tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Decrypt(vec![0x1, 0x2].into()))); - assert!(async_result.on_result(move |res| { - assert_eq!(res, response.to_owned()); - })); + + let res = rx.try_recv().unwrap(); + assert_eq!(res, Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/web3.rs b/rpc/src/v1/tests/mocked/web3.rs index b9f80b0a8..c3bd79110 100644 --- a/rpc/src/v1/tests/mocked/web3.rs +++ b/rpc/src/v1/tests/mocked/web3.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use jsonrpc_core::IoHandler; +use jsonrpc_core::{IoHandler, GenericIoHandler}; use util::version; use v1::{Web3, Web3Client}; diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 6308be324..64a87c175 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -17,7 +17,7 @@ //! Eth rpc interface. use jsonrpc_core::Error; -use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index}; +use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index, DappId}; use v1::types::{Log, Receipt, SyncStatus, Transaction, Work}; use v1::types::{H64, H160, H256, U256}; @@ -52,7 +52,7 @@ build_rpc_trait! { /// Returns accounts list. #[rpc(name = "eth_accounts")] - fn accounts(&self) -> Result, Error>; + fn accounts(&self, Trailing) -> Result, Error>; /// Returns highest block number. #[rpc(name = "eth_blockNumber")] diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index 0f62f59d1..e8a24bbaf 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -19,7 +19,7 @@ use std::collections::BTreeMap; use jsonrpc_core::{Value, Error}; use v1::helpers::auto_args::Wrap; -use v1::types::{H160, H256}; +use v1::types::{H160, H256, DappId}; build_rpc_trait! { /// Personal Parity rpc interface. @@ -61,10 +61,14 @@ build_rpc_trait! { #[rpc(name = "parity_setAccountMeta")] fn set_account_meta(&self, H160, String) -> Result; - /// Returns accounts information. + /// Sets account visibility #[rpc(name = "parity_setAccountVisiblity")] fn set_account_visibility(&self, H160, H256, bool) -> Result; + /// Sets accounts exposed for particular dapp. + #[rpc(name = "parity_setDappsAddresses")] + fn set_dapps_addresses(&self, DappId, Vec) -> Result; + /// Imports a number of Geth accounts, with the list provided as the argument. #[rpc(name = "parity_importGethAccounts")] fn import_geth_accounts(&self, Vec) -> Result, Error>; diff --git a/rpc/src/v1/types/dapp_id.rs b/rpc/src/v1/types/dapp_id.rs new file mode 100644 index 000000000..04aa80e3a --- /dev/null +++ b/rpc/src/v1/types/dapp_id.rs @@ -0,0 +1,60 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Dapp Id type + +/// Dapplication Internal Id +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct DappId(pub String); + +impl Into for DappId { + fn into(self) -> String { + self.0 + } +} + +#[cfg(test)] +mod tests { + + use serde_json; + use super::DappId; + + #[test] + fn should_serialize_dapp_id() { + // given + let id = DappId("testapp".into()); + + // when + let res = serde_json::to_string(&id).unwrap(); + + // then + assert_eq!(res, r#""testapp""#); + } + + #[test] + fn should_deserialize_dapp_id() { + // given + let id = r#""testapp""#; + + // when + let res: DappId = serde_json::from_str(id).unwrap(); + + // then + assert_eq!(res, DappId("testapp".into())); + } + + +} diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in index c10d6e36f..282d70c27 100644 --- a/rpc/src/v1/types/mod.rs.in +++ b/rpc/src/v1/types/mod.rs.in @@ -19,6 +19,7 @@ mod block; mod block_number; mod call_request; mod confirmations; +mod dapp_id; mod filter; mod hash; mod index; @@ -39,6 +40,7 @@ pub use self::block::{RichBlock, Block, BlockTransactions}; pub use self::block_number::BlockNumber; pub use self::call_request::CallRequest; pub use self::confirmations::{ConfirmationPayload, ConfirmationRequest, ConfirmationResponse, TransactionModification, SignRequest, DecryptRequest, Either}; +pub use self::dapp_id::DappId; pub use self::filter::{Filter, FilterChanges}; pub use self::hash::{H64, H160, H256, H512, H520, H2048}; pub use self::index::Index; diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 2a3742ec8..1b91e1a33 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -12,7 +12,7 @@ rustc_version = "0.1" [dependencies] rand = "0.3.14" -jsonrpc-core = "3.0" +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } log = "0.3" env_logger = "0.3" parity-dapps-glue = { version = "1.4", optional = true } diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index 5adc3fa80..0c9283f6d 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -21,8 +21,8 @@ use authcode_store::AuthCodes; use std::path::{PathBuf, Path}; use std::sync::Arc; use std::str::FromStr; -use jsonrpc_core::IoHandler; -use util::{H256, Mutex, version}; +use jsonrpc_core::{IoHandler, GenericIoHandler}; +use util::{H256, version}; #[cfg(feature = "parity-ui")] mod ui { @@ -130,7 +130,7 @@ fn add_headers(mut response: ws::Response, mime: &str) -> ws::Response { } pub struct Session { - out: Arc>, + out: ws::Sender, skip_origin_validation: bool, self_origin: String, authcodes_path: PathBuf, @@ -208,15 +208,15 @@ impl ws::Handler for Session { fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> { let req = try!(msg.as_text()); - if let Some(async) = self.handler.handle_request(req) { - let out = self.out.clone(); - async.on_result(move |result| { - let res = out.lock().send(result); + let out = self.out.clone(); + self.handler.handle_request(req, move |response| { + if let Some(result) = response { + let res = out.send(result); if let Err(e) = res { warn!(target: "signer", "Error while sending response: {:?}", e); } - }); - } + } + }); Ok(()) } } @@ -246,7 +246,7 @@ impl ws::Factory for Factory { fn connection_made(&mut self, sender: ws::Sender) -> Self::Handler { Session { - out: Arc::new(Mutex::new(sender)), + out: sender, handler: self.handler.clone(), skip_origin_validation: self.skip_origin_validation, self_origin: self.self_origin.clone(), diff --git a/stratum/Cargo.toml b/stratum/Cargo.toml index d300106aa..28f5208dd 100644 --- a/stratum/Cargo.toml +++ b/stratum/Cargo.toml @@ -11,8 +11,8 @@ ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] log = "0.3" -json-tcp-server = { git = "https://github.com/ethcore/json-tcp-server" } -jsonrpc-core = "3.0" +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } +jsonrpc-tcp-server = { git = "https://github.com/ethcore/jsonrpc.git" } mio = { git = "https://github.com/ethcore/mio", branch = "v0.5.x" } ethcore-util = { path = "../util" } ethcore-devtools = { path = "../devtools" } diff --git a/stratum/src/lib.rs b/stratum/src/lib.rs index ecec535c2..0743fba6d 100644 --- a/stratum/src/lib.rs +++ b/stratum/src/lib.rs @@ -16,7 +16,7 @@ //! Stratum protocol implementation for parity ethereum/bitcoin clients -extern crate json_tcp_server; +extern crate jsonrpc_tcp_server; extern crate jsonrpc_core; #[macro_use] extern crate log; extern crate ethcore_util as util; @@ -44,7 +44,7 @@ pub use traits::{ RemoteWorkHandler, RemoteJobDispatcher, }; -use json_tcp_server::Server as JsonRpcServer; +use jsonrpc_tcp_server::Server as JsonRpcServer; use jsonrpc_core::{IoHandler, Params, IoDelegate, to_value, from_params}; use std::sync::Arc; From f080f33c4171fb30d4dcea1de1e576ec1c3eefc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 24 Nov 2016 11:22:26 +0100 Subject: [PATCH 03/52] JSON-RPC bump / update hyper Conflicts: Cargo.lock --- Cargo.lock | 78 ++++++++++++++++++++++------------- dapps/src/handlers/content.rs | 1 - dapps/src/handlers/mod.rs | 2 +- dapps/src/page/handler.rs | 3 +- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eaede16ba..61c36078a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,15 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cookie" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam" version = "0.2.9" @@ -295,7 +304,7 @@ dependencies = [ "ethstore 0.1.0", "evmjit 1.4.0", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -339,9 +348,9 @@ dependencies = [ "ethcore-rpc 1.5.0", "ethcore-util 1.5.0", "fetch 0.1.0", - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", + "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -685,7 +694,7 @@ name = "fetch" version = "0.1.0" dependencies = [ "https-fetch 0.1.0", - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -747,27 +756,6 @@ dependencies = [ "rustls 0.1.2 (git+https://github.com/ctz/rustls)", ] -[[package]] -name = "hyper" -version = "0.9.4" -source = "git+https://github.com/ethcore/hyper#9e346c1d4bc30cd4142dea9d8a0b117d30858ca4" -dependencies = [ - "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rotor 0.6.3 (git+https://github.com/ethcore/rotor)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hyper" version = "0.9.10" @@ -788,6 +776,25 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.10.0-a.0" +source = "git+https://github.com/ethcore/hyper#7d4f7fa0baddcb2b0c523f7c05855d67de94fe88" +dependencies = [ + "cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rotor 0.6.3 (git+https://github.com/ethcore/rotor)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.0" @@ -883,6 +890,17 @@ dependencies = [ "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-http-server" +version = "6.1.1" +source = "git+https://github.com/ethcore/jsonrpc-http-server.git#cd6d4cb37d672cc3057aecd0692876f9e85f3ba5" +dependencies = [ + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", + "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1503,11 +1521,12 @@ dependencies = [ [[package]] name = "rotor" version = "0.6.3" -source = "git+https://github.com/ethcore/rotor#e63d45137b2eb66d1e085a7c6321a5db8b187576" +source = "git+https://github.com/ethcore/rotor#c1a2dd0046c5ea2517a5b637fca8ee2e77021e82" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", + "mio 0.6.1 (git+https://github.com/ethcore/mio)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2008,6 +2027,7 @@ dependencies = [ "checksum clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)" = "6eacf01b0aad84a0817703498f72d252df7c0faf6a5b86d0be4265f1829e459f" "checksum clippy_lints 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)" = "a49960c9aab544ce86b004dcb61620e8b898fea5fc0f697a028f460f48221ed6" "checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245" +"checksum cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d53b80dde876f47f03cda35303e368a79b91c70b0d65ecba5fd5280944a08591" "checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc" "checksum ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)" = "" "checksum daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "271ec51b7e0bee92f0d04601422c73eb76ececf197026711c97ad25038a010cf" @@ -2025,8 +2045,8 @@ dependencies = [ "checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c" "checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" "checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae" +"checksum hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)" = "" "checksum hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "eb27e8a3e8f17ac43ffa41bbda9cf5ad3f9f13ef66fa4873409d4902310275f7" -"checksum hyper 0.9.4 (git+https://github.com/ethcore/hyper)" = "" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" "checksum igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8c12b1795b8b168f577c45fa10379b3814dcb11b7ab702406001f0d63f40484" "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" diff --git a/dapps/src/handlers/content.rs b/dapps/src/handlers/content.rs index 738a9a890..fde5fbcf0 100644 --- a/dapps/src/handlers/content.rs +++ b/dapps/src/handlers/content.rs @@ -16,7 +16,6 @@ //! Simple Content Handler -use std::io::Write; use hyper::{header, server, Decoder, Encoder, Next}; use hyper::net::HttpStream; use hyper::mime::Mime; diff --git a/dapps/src/handlers/mod.rs b/dapps/src/handlers/mod.rs index b575509a5..1299a9c12 100644 --- a/dapps/src/handlers/mod.rs +++ b/dapps/src/handlers/mod.rs @@ -58,7 +58,7 @@ pub fn extract_url(req: &server::Request) -> Option { _ => None, } }, - uri::RequestUri::AbsolutePath(ref path) => { + uri::RequestUri::AbsolutePath { ref path, .. } => { // Attempt to prepend the Host header (mandatory in HTTP/1.1) let url_string = match req.headers().get::() { Some(ref host) => { diff --git a/dapps/src/page/handler.rs b/dapps/src/page/handler.rs index 74eabf917..1494a04c7 100644 --- a/dapps/src/page/handler.rs +++ b/dapps/src/page/handler.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::io::Write; use time::{self, Duration}; use hyper::header; @@ -126,7 +125,7 @@ impl PageHandler { impl server::Handler for PageHandler { fn on_request(&mut self, req: server::Request) -> Next { self.file = match *req.uri() { - RequestUri::AbsolutePath(ref path) => { + RequestUri::AbsolutePath { ref path, .. } => { self.app.file(&self.extract_path(path)) }, RequestUri::AbsoluteUri(ref url) => { From 789d6608cf40bf667b59788499eeaf07fd18f0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 25 Nov 2016 16:13:48 +0100 Subject: [PATCH 04/52] Bumping jsonrpc --- Cargo.lock | 44 +++++++++++++++++++--------------- dapps/src/lib.rs | 2 +- rpc/src/v1/tests/mocked/eth.rs | 3 +-- stratum/src/lib.rs | 2 +- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61c36078a..1cd3f87f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,8 +349,8 @@ dependencies = [ "ethcore-util 1.5.0", "fetch 0.1.0", "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc-http-server.git)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", + "jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -840,7 +840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "4.0.0" -source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -852,9 +852,9 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" dependencies = [ - "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", + "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -863,7 +863,7 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" version = "0.2.4" -source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -878,7 +878,7 @@ dependencies = [ [[package]] name = "jsonrpc-tcp-server" version = "0.1.0" -source = "git+https://github.com/ethcore/jsonrpc.git#59919f9f0a2ebb675670b72430803605d868904c" +source = "git+https://github.com/ethcore/jsonrpc.git#20c7e55b84d7fd62732f062dc3058e1b71133e4a" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -890,17 +890,6 @@ dependencies = [ "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "jsonrpc-http-server" -version = "6.1.1" -source = "git+https://github.com/ethcore/jsonrpc-http-server.git#cd6d4cb37d672cc3057aecd0692876f9e85f3ba5" -dependencies = [ - "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1057,6 +1046,22 @@ dependencies = [ "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio" +version = "0.6.1" +source = "git+https://github.com/ethcore/mio.git#ef182bae193a9c7457cd2cf661fcaffb226e3eef" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miow" version = "0.1.3" @@ -1524,7 +1529,7 @@ version = "0.6.3" source = "git+https://github.com/ethcore/rotor#c1a2dd0046c5ea2517a5b637fca8ee2e77021e82" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.1 (git+https://github.com/ethcore/mio)", + "mio 0.6.1 (git+https://github.com/ethcore/mio.git)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2074,6 +2079,7 @@ dependencies = [ "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)" = "" "checksum mio 0.6.1 (git+https://github.com/carllerche/mio)" = "" +"checksum mio 0.6.1 (git+https://github.com/ethcore/mio.git)" = "" "checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a" "checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8" "checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "" diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 7c7ea0a86..b185eb57a 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -266,7 +266,7 @@ impl Server { #[cfg(test)] /// Returns address that this server is bound to. pub fn addr(&self) -> &SocketAddr { - self.server.as_ref().expect("server is always Some at the start; it's consumed only when object is dropped; qed").addr() + &self.server.as_ref().expect("server is always Some at the start; it's consumed only when object is dropped; qed").addrs()[0] } } diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 2f31aa4e1..2b5942af6 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -354,8 +354,7 @@ fn rpc_eth_gas_price() { #[test] fn rpc_eth_accounts() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); - let address2 = Address::default(); + let _address = tester.accounts_provider.new_account("").unwrap(); // even with some account it should return empty list (no dapp detected) let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; diff --git a/stratum/src/lib.rs b/stratum/src/lib.rs index 0743fba6d..45d8a3639 100644 --- a/stratum/src/lib.rs +++ b/stratum/src/lib.rs @@ -72,7 +72,7 @@ impl Stratum { addr: &SocketAddr, dispatcher: Arc, secret: Option, - ) -> Result, json_tcp_server::Error> { + ) -> Result, jsonrpc_tcp_server::Error> { let handler = Arc::new(IoHandler::new()); let server = try!(JsonRpcServer::new(addr, &handler)); let stratum = Arc::new(Stratum { From 3e69ff0b887fc14efb463def8d7dd3806cd767ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 28 Nov 2016 11:41:46 +0100 Subject: [PATCH 05/52] Separating serialization of send and signTransaction --- rpc/src/v1/tests/mocked/signer.rs | 2 +- rpc/src/v1/types/confirmations.rs | 48 +++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index e2ba580e0..447c809cd 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -89,7 +89,7 @@ fn should_return_list_of_items_to_confirm() { let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; let response = concat!( r#"{"jsonrpc":"2.0","result":["#, - r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, + r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#, r#"],"id":1}"# ); diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index 2b7813df9..5b396725b 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -105,10 +105,10 @@ impl Serialize for ConfirmationResponse { #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)] pub enum ConfirmationPayload { /// Send Transaction - #[serde(rename="transaction")] + #[serde(rename="sendTransaction")] SendTransaction(TransactionRequest), /// Sign Transaction - #[serde(rename="transaction")] + #[serde(rename="signTransaction")] SignTransaction(TransactionRequest), /// Signature #[serde(rename="sign")] @@ -220,7 +220,49 @@ mod tests { // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"transaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; + let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; + + // then + assert_eq!(res.unwrap(), expected.to_owned()); + } + + #[test] + fn should_serialize_sign_transaction_confirmation() { + // given + let request = helpers::ConfirmationRequest { + id: 15.into(), + payload: helpers::ConfirmationPayload::SignTransaction(helpers::FilledTransactionRequest { + from: 0.into(), + to: None, + gas: 15_000.into(), + gas_price: 10_000.into(), + value: 100_000.into(), + data: vec![1, 2, 3], + nonce: Some(1.into()), + }), + }; + + // when + let res = serde_json::to_string(&ConfirmationRequest::from(request)); + let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; + + // then + assert_eq!(res.unwrap(), expected.to_owned()); + } + + #[test] + fn should_serialize_decrypt_confirmation() { + // given + let request = helpers::ConfirmationRequest { + id: 15.into(), + payload: helpers::ConfirmationPayload::Decrypt( + 10.into(), vec![1, 2, 3].into(), + ), + }; + + // when + let res = serde_json::to_string(&ConfirmationRequest::from(request)); + let expected = r#"{"id":"0xf","payload":{"decrypt":{"address":"0x000000000000000000000000000000000000000a","msg":"0x010203"}}}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); From 8686339b0c742a7b79752cbf3647c644791569fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 28 Nov 2016 11:55:29 +0100 Subject: [PATCH 06/52] Fixing UI to support both send and signTransaction --- js/src/api/format/output.js | 3 ++- js/src/redux/providers/signerMiddleware.js | 4 ++-- .../Signer/components/RequestFinished/requestFinished.js | 7 ++++--- .../Signer/components/RequestPending/requestPending.js | 7 ++++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/js/src/api/format/output.js b/js/src/api/format/output.js index 262a275a0..1094cdb83 100644 --- a/js/src/api/format/output.js +++ b/js/src/api/format/output.js @@ -144,7 +144,8 @@ export function outSignerRequest (request) { break; case 'payload': - request[key].transaction = outTransaction(request[key].transaction); + request[key].signTransaction = outTransaction(request[key].signTransaction); + request[key].sendTransaction = outTransaction(request[key].sendTransaction); break; } }); diff --git a/js/src/redux/providers/signerMiddleware.js b/js/src/redux/providers/signerMiddleware.js index 4cc877ced..2af1bfe65 100644 --- a/js/src/redux/providers/signerMiddleware.js +++ b/js/src/redux/providers/signerMiddleware.js @@ -72,8 +72,8 @@ export default class SignerMiddleware { }; // Sign request in-browser - if (wallet && payload.transaction) { - const { transaction } = payload; + if (wallet && (payload.sendTransaction || payload.signTransaction)) { + const transaction = payload.sendTransaction || payload.signTransaction; (transaction.nonce.isZero() ? this._api.parity.nextNonce(transaction.from) diff --git a/js/src/views/Signer/components/RequestFinished/requestFinished.js b/js/src/views/Signer/components/RequestFinished/requestFinished.js index bce9e4038..edc5c4a47 100644 --- a/js/src/views/Signer/components/RequestFinished/requestFinished.js +++ b/js/src/views/Signer/components/RequestFinished/requestFinished.js @@ -25,7 +25,8 @@ export default class RequestFinished extends Component { result: PropTypes.any.isRequired, date: PropTypes.instanceOf(Date).isRequired, payload: PropTypes.oneOfType([ - PropTypes.shape({ transaction: PropTypes.object.isRequired }), + PropTypes.shape({ signTransaction: PropTypes.object.isRequired }), + PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }), PropTypes.shape({ sign: PropTypes.object.isRequired }) ]).isRequired, msg: PropTypes.string, @@ -58,8 +59,8 @@ export default class RequestFinished extends Component { ); } - if (payload.transaction) { - const { transaction } = payload; + if (payload.sendTransaction || payload.signTransaction) { + const transaction = payload.sendTransaction || payload.signTransaction; return ( Date: Tue, 29 Nov 2016 11:52:55 +0100 Subject: [PATCH 07/52] Addressing tiny grumbles --- js/src/redux/providers/signerMiddleware.js | 5 ++--- .../Signer/components/RequestFinished/requestFinished.js | 5 ++--- .../views/Signer/components/RequestPending/requestPending.js | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/js/src/redux/providers/signerMiddleware.js b/js/src/redux/providers/signerMiddleware.js index 2af1bfe65..f5cbbd8f9 100644 --- a/js/src/redux/providers/signerMiddleware.js +++ b/js/src/redux/providers/signerMiddleware.js @@ -72,9 +72,8 @@ export default class SignerMiddleware { }; // Sign request in-browser - if (wallet && (payload.sendTransaction || payload.signTransaction)) { - const transaction = payload.sendTransaction || payload.signTransaction; - + const transaction = payload.sendTransaction || payload.signTransaction; + if (wallet && transaction) { (transaction.nonce.isZero() ? this._api.parity.nextNonce(transaction.from) : Promise.resolve(transaction.nonce) diff --git a/js/src/views/Signer/components/RequestFinished/requestFinished.js b/js/src/views/Signer/components/RequestFinished/requestFinished.js index edc5c4a47..fcca55540 100644 --- a/js/src/views/Signer/components/RequestFinished/requestFinished.js +++ b/js/src/views/Signer/components/RequestFinished/requestFinished.js @@ -59,9 +59,8 @@ export default class RequestFinished extends Component { ); } - if (payload.sendTransaction || payload.signTransaction) { - const transaction = payload.sendTransaction || payload.signTransaction; - + const transaction = payload.sendTransaction || payload.signTransaction; + if (transaction) { return ( Date: Tue, 29 Nov 2016 16:36:54 +0100 Subject: [PATCH 08/52] Methods use either input or data elements --- js/src/ui/MethodDecoding/methodDecoding.css | 4 ++-- js/src/ui/MethodDecoding/methodDecoding.js | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/js/src/ui/MethodDecoding/methodDecoding.css b/js/src/ui/MethodDecoding/methodDecoding.css index 2de91cf9b..48070c45f 100644 --- a/js/src/ui/MethodDecoding/methodDecoding.css +++ b/js/src/ui/MethodDecoding/methodDecoding.css @@ -30,9 +30,9 @@ } .gasDetails { - padding-top: 1em; + padding-top: 0.75em; font-size: 0.75em; - line-height: 2em; + line-height: 1.5em; opacity: 0.5; } diff --git a/js/src/ui/MethodDecoding/methodDecoding.js b/js/src/ui/MethodDecoding/methodDecoding.js index d446a19b4..e82139adf 100644 --- a/js/src/ui/MethodDecoding/methodDecoding.js +++ b/js/src/ui/MethodDecoding/methodDecoding.js @@ -135,21 +135,23 @@ class MethodDecoding extends Component { renderInputValue () { const { api } = this.context; const { transaction } = this.props; + const input = transaction.input || transaction.data; - if (!/^(0x)?([0]*[1-9a-f]+[0]*)+$/.test(transaction.input)) { + if (!/^(0x)?([0]*[1-9a-f]+[0]*)+$/.test(input)) { return null; } - const ascii = api.util.hex2Ascii(transaction.input); - + const ascii = api.util.hex2Ascii(input); const text = ASCII_INPUT.test(ascii) ? ascii - : transaction.input; + : input; return ( -
- with the input   - { text } +
+
+ with the input   + { text } +
); } @@ -385,11 +387,12 @@ class MethodDecoding extends Component { const isReceived = transaction.to === address; const contractAddress = isReceived ? transaction.from : transaction.to; + const input = transaction.input || transaction.data; const token = (tokens || {})[contractAddress]; this.setState({ token, isReceived, contractAddress }); - if (!transaction.input || transaction.input === '0x') { + if (!input || input === '0x') { return; } @@ -408,7 +411,7 @@ class MethodDecoding extends Component { return; } - const { signature, paramdata } = api.util.decodeCallData(transaction.input); + const { signature, paramdata } = api.util.decodeCallData(input); this.setState({ methodSignature: signature, methodParams: paramdata }); if (!signature || signature === CONTRACT_CREATE || transaction.creates) { From efd4e6f96af73f0b82f24a1d684acbc81e547081 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 29 Nov 2016 16:37:25 +0100 Subject: [PATCH 09/52] Pass MethodDecoding as to/destination view --- js/src/views/Signer/_layout.css | 2 +- .../RequestPending/requestPending.js | 7 +-- .../TransactionMainDetails.css | 37 ++++++----- .../TransactionMainDetails.js | 61 +++---------------- .../TransactionPending/TransactionPending.css | 6 +- .../TransactionPending/TransactionPending.js | 43 +++++++------ .../TransactionPendingForm.css | 2 +- 7 files changed, 56 insertions(+), 102 deletions(-) diff --git a/js/src/views/Signer/_layout.css b/js/src/views/Signer/_layout.css index 3970a7e02..40e5df3e8 100644 --- a/js/src/views/Signer/_layout.css +++ b/js/src/views/Signer/_layout.css @@ -19,6 +19,6 @@ $pendingHeight: 190px; $finishedHeight: 120px; $embedWidth: 920px; -$statusWidth: 260px; +$statusWidth: 270px; $accountPadding: 75px; diff --git a/js/src/views/Signer/components/RequestPending/requestPending.js b/js/src/views/Signer/components/RequestPending/requestPending.js index d8e2e0565..aa797f526 100644 --- a/js/src/views/Signer/components/RequestPending/requestPending.js +++ b/js/src/views/Signer/components/RequestPending/requestPending.js @@ -74,12 +74,7 @@ export default class RequestPending extends Component { onReject={ onReject } isSending={ isSending } id={ id } - gasPrice={ transaction.gasPrice } - gas={ transaction.gas } - data={ transaction.data } - from={ transaction.from } - to={ transaction.to } - value={ transaction.value } + transaction={ transaction } date={ date } isTest={ isTest } store={ store } diff --git a/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.css b/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.css index 107694b8e..92ed968d1 100644 --- a/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.css +++ b/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.css @@ -30,27 +30,26 @@ text-align: center; } -.from, .to { - width: 50%; +.from { + width: 40%; + vertical-align: top; + + img { + display: inline-block; + width: 50px; + height: 50px; + margin: 5px; + } + + span { + display: block; + } } -.from .account { - padding-right: $accountPadding; -} - -.to .account { - padding-left: $accountPadding; -} - -.from img, .to img { - display: inline-block; - width: 50px; - height: 50px; - margin: 5px; -} - -.from span, .to span { - display: block; +.method { + width: 60%; + vertical-align: top; + line-height: 1em; } .tx { diff --git a/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js b/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js index 6e83e0c7e..fb10392d3 100644 --- a/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js +++ b/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js @@ -16,9 +16,10 @@ import React, { Component, PropTypes } from 'react'; -import ContractIcon from 'material-ui/svg-icons/action/code'; import ReactTooltip from 'react-tooltip'; +import { MethodDecoding } from '../../../../ui'; + import * as tUtil from '../util/transaction'; import Account from '../Account'; import styles from './TransactionMainDetails.css'; @@ -32,6 +33,7 @@ export default class TransactionMainDetails extends Component { totalValue: PropTypes.object.isRequired, // wei BigNumber isTest: PropTypes.bool.isRequired, to: PropTypes.string, // undefined if it's a contract + transaction: PropTypes.object.isRequired, toBalance: PropTypes.object, // eth BigNumber - undefined if it's a contract or until it's fetched children: PropTypes.node }; @@ -59,15 +61,7 @@ export default class TransactionMainDetails extends Component { } render () { - const { to } = this.props; - - return to - ? this.renderTransfer() - : this.renderContract(); - } - - renderTransfer () { - const { children, from, fromBalance, to, toBalance, isTest } = this.props; + const { children, from, fromBalance, transaction, isTest } = this.props; return (
@@ -79,48 +73,11 @@ export default class TransactionMainDetails extends Component { isTest={ isTest } />
-
- { this.renderValue() } -
- { this.renderTotalValue() } -
-
-
- -
-
- { children } - - ); - } - - renderContract () { - const { children, from, fromBalance, isTest } = this.props; - - return ( -
-
-
- -
-
-
- { this.renderValue() } -
- { this.renderTotalValue() } -
-
-
- -
- Contract -
+
+
{ children }
diff --git a/js/src/views/Signer/components/TransactionPending/TransactionPending.css b/js/src/views/Signer/components/TransactionPending/TransactionPending.css index 5cd2d10f5..877066e57 100644 --- a/js/src/views/Signer/components/TransactionPending/TransactionPending.css +++ b/js/src/views/Signer/components/TransactionPending/TransactionPending.css @@ -19,9 +19,13 @@ .container { display: flex; - padding: 1.5em 0 1em; + padding: 1em 0 1em; & > * { vertical-align: middle; } } + +.container+.container { + padding-top: 2em; +} diff --git a/js/src/views/Signer/components/TransactionPending/TransactionPending.js b/js/src/views/Signer/components/TransactionPending/TransactionPending.js index 013d887a5..98c83be3b 100644 --- a/js/src/views/Signer/components/TransactionPending/TransactionPending.js +++ b/js/src/views/Signer/components/TransactionPending/TransactionPending.js @@ -19,7 +19,6 @@ import { observer } from 'mobx-react'; import TransactionMainDetails from '../TransactionMainDetails'; import TransactionPendingForm from '../TransactionPendingForm'; -import TransactionSecondaryDetails from '../TransactionSecondaryDetails'; import styles from './TransactionPending.css'; @@ -29,13 +28,15 @@ import * as tUtil from '../util/transaction'; export default class TransactionPending extends Component { static propTypes = { id: PropTypes.object.isRequired, - from: PropTypes.string.isRequired, - value: PropTypes.object.isRequired, // wei hex - gasPrice: PropTypes.object.isRequired, // wei hex - gas: PropTypes.object.isRequired, // hex + transaction: PropTypes.shape({ + from: PropTypes.string.isRequired, + value: PropTypes.object.isRequired, // wei hex + gasPrice: PropTypes.object.isRequired, // wei hex + gas: PropTypes.object.isRequired, // hex + data: PropTypes.string, // hex + to: PropTypes.string // undefined if it's a contract + }).isRequired, date: PropTypes.instanceOf(Date).isRequired, - to: PropTypes.string, // undefined if it's a contract - data: PropTypes.string, // hex nonce: PropTypes.number, onConfirm: PropTypes.func.isRequired, onReject: PropTypes.func.isRequired, @@ -50,7 +51,8 @@ export default class TransactionPending extends Component { }; componentWillMount () { - const { gas, gasPrice, value, from, to, store } = this.props; + const { transaction, store } = this.props; + const { gas, gasPrice, value, from, to } = transaction; const fee = tUtil.getFee(gas, gasPrice); // BigNumber object const totalValue = tUtil.getTotalValue(fee, value); @@ -62,8 +64,9 @@ export default class TransactionPending extends Component { } render () { - const { className, id, date, data, from, to, store } = this.props; - const { totalValue, gasPriceEthmDisplay, gasToDisplay } = this.state; + const { className, id, transaction, store } = this.props; + const { from, to, value } = transaction; + const { totalValue } = this.state; const fromBalance = store.balances[from]; const toBalance = store.balances[to]; @@ -71,20 +74,15 @@ export default class TransactionPending extends Component { return (
- - + transaction={ transaction } + totalValue={ totalValue } /> { - const { id, gasPrice } = this.props; + const { id, transaction } = this.props; + const { gasPrice } = transaction; const { password, wallet } = data; this.props.onConfirm({ id, password, wallet, gasPrice }); diff --git a/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingForm.css b/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingForm.css index aaea1de8d..feb456bce 100644 --- a/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingForm.css +++ b/js/src/views/Signer/components/TransactionPendingForm/TransactionPendingForm.css @@ -19,7 +19,7 @@ .container { box-sizing: border-box; - padding: 1em 1em 0 1em; + padding: 1em 0 0 2em; flex: 0 0 $statusWidth; } From 0ddd33c643a99be51f32ff02859fe953811092b0 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 29 Nov 2016 16:55:59 +0100 Subject: [PATCH 10/52] Trim unused components --- .../TransactionFinished.css | 54 ------ .../TransactionFinished.js | 120 ------------ .../components/TransactionFinished/index.js | 17 -- .../TransactionMainDetails.js | 2 - .../TransactionPending/TransactionPending.js | 5 +- .../TransactionSecondaryDetails.css | 90 --------- .../TransactionSecondaryDetails.js | 178 ------------------ .../TransactionSecondaryDetails/index.js | 1 - .../containers/RequestsPage/RequestsPage.js | 42 +---- 9 files changed, 2 insertions(+), 507 deletions(-) delete mode 100644 js/src/views/Signer/components/TransactionFinished/TransactionFinished.css delete mode 100644 js/src/views/Signer/components/TransactionFinished/TransactionFinished.js delete mode 100644 js/src/views/Signer/components/TransactionFinished/index.js delete mode 100644 js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.css delete mode 100644 js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.js delete mode 100644 js/src/views/Signer/components/TransactionSecondaryDetails/index.js diff --git a/js/src/views/Signer/components/TransactionFinished/TransactionFinished.css b/js/src/views/Signer/components/TransactionFinished/TransactionFinished.css deleted file mode 100644 index 3617f666a..000000000 --- a/js/src/views/Signer/components/TransactionFinished/TransactionFinished.css +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2015, 2016 Ethcore (UK) Ltd. -/* This file is part of Parity. -/* -/* Parity is free software: you can redistribute it and/or modify -/* it under the terms of the GNU General Public License as published by -/* the Free Software Foundation, either version 3 of the License, or -/* (at your option) any later version. -/* -/* Parity is distributed in the hope that it will be useful, -/* but WITHOUT ANY WARRANTY; without even the implied warranty of -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/* GNU General Public License for more details. -/* -/* You should have received a copy of the GNU General Public License -/* along with Parity. If not, see . -*/ - -@import '../../_layout.css'; - -.container { - display: flex; - padding: 1.5em 0 1em; - - & > * { - vertical-align: middle; - min-height: $finishedHeight; - } -} - -.statusContainer { - box-sizing: border-box; - float: right; - padding: 0 1em; - flex: 0 0 $statusWidth; -} - -.transactionDetails { - width: 100%; - box-sizing: border-box; -} - -.isConfirmed { - color: green; -} - -.isRejected { - opacity: 0.5; - padding-top: 2em; -} - -.txHash { - display: block; - word-break: break-all; -} diff --git a/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js b/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js deleted file mode 100644 index f24481e57..000000000 --- a/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -import React, { Component, PropTypes } from 'react'; -import { observer } from 'mobx-react'; - -import { TxHash } from '../../../../ui'; - -import TransactionMainDetails from '../TransactionMainDetails'; -import TxHashLink from '../TxHashLink'; -import TransactionSecondaryDetails from '../TransactionSecondaryDetails'; - -import styles from './TransactionFinished.css'; - -import * as tUtil from '../util/transaction'; -import { capitalize } from '../util/util'; - -@observer -export default class TransactionFinished extends Component { - static propTypes = { - id: PropTypes.object.isRequired, - from: PropTypes.string.isRequired, - value: PropTypes.object.isRequired, // wei hex - gasPrice: PropTypes.object.isRequired, // wei hex - gas: PropTypes.object.isRequired, // hex - status: PropTypes.string.isRequired, // rejected, confirmed - date: PropTypes.instanceOf(Date).isRequired, - to: PropTypes.string, // undefined if it's a contract - txHash: PropTypes.string, // undefined if transacation is rejected - className: PropTypes.string, - data: PropTypes.string, - isTest: PropTypes.bool.isRequired, - store: PropTypes.object.isRequired - }; - - componentWillMount () { - const { from, to, gas, gasPrice, value, store } = this.props; - const fee = tUtil.getFee(gas, gasPrice); // BigNumber object - const totalValue = tUtil.getTotalValue(fee, value); - - this.setState({ totalValue }); - store.fetchBalances([from, to]); - } - - render () { - const { className, date, id, from, to, store } = this.props; - - const fromBalance = store.balances[from]; - const toBalance = store.balances[to]; - - return ( -
- - - -
- { this.renderStatus() } -
-
- ); - } - - renderStatus () { - const { status, txHash } = this.props; - - if (status !== 'confirmed') { - return ( -
- { capitalize(status) } -
- ); - } - - return ( - - ); - } - - renderTxHash () { - const { txHash, isTest } = this.props; - - if (!txHash) { - return; - } - - return ( -
- Transaction hash: - -
- ); - } -} diff --git a/js/src/views/Signer/components/TransactionFinished/index.js b/js/src/views/Signer/components/TransactionFinished/index.js deleted file mode 100644 index fe606e1d4..000000000 --- a/js/src/views/Signer/components/TransactionFinished/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -export default from './TransactionFinished'; diff --git a/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js b/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js index fb10392d3..ca2061791 100644 --- a/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js +++ b/js/src/views/Signer/components/TransactionMainDetails/TransactionMainDetails.js @@ -32,9 +32,7 @@ export default class TransactionMainDetails extends Component { value: PropTypes.object.isRequired, // wei hex totalValue: PropTypes.object.isRequired, // wei BigNumber isTest: PropTypes.bool.isRequired, - to: PropTypes.string, // undefined if it's a contract transaction: PropTypes.object.isRequired, - toBalance: PropTypes.object, // eth BigNumber - undefined if it's a contract or until it's fetched children: PropTypes.node }; diff --git a/js/src/views/Signer/components/TransactionPending/TransactionPending.js b/js/src/views/Signer/components/TransactionPending/TransactionPending.js index 98c83be3b..4fba02826 100644 --- a/js/src/views/Signer/components/TransactionPending/TransactionPending.js +++ b/js/src/views/Signer/components/TransactionPending/TransactionPending.js @@ -65,11 +65,10 @@ export default class TransactionPending extends Component { render () { const { className, id, transaction, store } = this.props; - const { from, to, value } = transaction; + const { from, value } = transaction; const { totalValue } = this.state; const fromBalance = store.balances[from]; - const toBalance = store.balances[to]; return (
@@ -78,8 +77,6 @@ export default class TransactionPending extends Component { value={ value } from={ from } fromBalance={ fromBalance } - to={ to } - toBalance={ toBalance } className={ styles.transactionDetails } transaction={ transaction } totalValue={ totalValue } /> diff --git a/js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.css b/js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.css deleted file mode 100644 index ae71b1004..000000000 --- a/js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.css +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright 2015, 2016 Ethcore (UK) Ltd. -/* This file is part of Parity. -/* -/* Parity is free software: you can redistribute it and/or modify -/* it under the terms of the GNU General Public License as published by -/* the Free Software Foundation, either version 3 of the License, or -/* (at your option) any later version. -/* -/* Parity is distributed in the hope that it will be useful, -/* but WITHOUT ANY WARRANTY; without even the implied warranty of -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/* GNU General Public License for more details. -/* -/* You should have received a copy of the GNU General Public License -/* along with Parity. If not, see . -*/ - -.container { - display: block; -} - -.iconsContainer { - display: block; - text-align: center; - font-size: .8em; - opacity: 0.5; - padding: 1em 0 0 0; -} - -.iconsContainer > * { - margin-right: 3px; - display: inline-block; -} - -.iconsContainer:after { - clear: both; -} - -.hasInfoIcon svg, -.miningTime svg, -.gasPrice svg, -.data svg, -.date svg { - width: 16px !important; - height: 16px !important; - position: relative; - bottom: -3px; - margin: 0 0.25rem 0 0.75rem; -} - -/* TODO [ToDr] composes was handling weird errors when linking from other app */ -.miningTime { - /* composes: hasInfoIcon; */ -} - -.gasPrice { - /* composes: hasInfoIcon; */ -} - -.data { - /* composes: hasInfoIcon; */ - cursor: pointer; -} - -.data.noData { - cursor: text; -} - - -.dataTooltip { - word-wrap: break-word; - max-width: 400px; -} - -.expandedData { - display: block; - padding: 15px; - background: gray; - word-wrap: break-word; - color: #fff; -} - -.expandedContainer { - padding: 10px; - border-radius: 4px; -} - -.expandedContainer:empty { - padding: 0; -} diff --git a/js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.js b/js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.js deleted file mode 100644 index 283712ed0..000000000 --- a/js/src/views/Signer/components/TransactionSecondaryDetails/TransactionSecondaryDetails.js +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -import React, { Component, PropTypes } from 'react'; - -import ReactTooltip from 'react-tooltip'; -import DescriptionIcon from 'material-ui/svg-icons/action/description'; -import GasIcon from 'material-ui/svg-icons/maps/local-gas-station'; -import TimeIcon from 'material-ui/svg-icons/device/access-time'; -import moment from 'moment'; - -import styles from './TransactionSecondaryDetails.css'; - -import * as tUtil from '../util/transaction'; - -export default class TransactionSecondaryDetails extends Component { - static propTypes = { - id: PropTypes.object.isRequired, - date: PropTypes.instanceOf(Date), - data: PropTypes.string, // hex - gasPriceEthmDisplay: PropTypes.string, - gasToDisplay: PropTypes.string, - className: PropTypes.string - }; - - state = { - isDataExpanded: false - }; - - render () { - const className = this.props.className || ''; - - return ( -
-
- { this.renderGasPrice() } - { this.renderData() } - { this.renderDate() } -
-
- { this.renderDataExpanded() } -
-
- ); - } - - renderGasPrice () { - if (!this.props.gasPriceEthmDisplay && !this.props.gasToDisplay) { - return null; - } - - const { id } = this.props; - const { gasPriceEthmDisplay, gasToDisplay } = this.props; - - return ( -
- - - { gasPriceEthmDisplay } ETH/MGAS - - { /* dynamic id required in case there are multple transactions in page */ } - - Cost of 1,000,000 units of gas. This transaction will use up to { gasToDisplay } MGAS. - -
- ); - } - - renderData () { - if (!this.props.data) { - return null; - } - - const { data, id } = this.props; - let dataToDisplay = this.noData() ? 'no data' : tUtil.getShortData(data); - const noDataClass = this.noData() ? styles.noData : ''; - - return ( -
- - { dataToDisplay } - { /* dynamic id required in case there are multple transactions in page */ } - - Extra data for the transaction: -
- { dataToDisplay }. -
- { this.noData() ? '' : Click to expand. } -
-
- ); - } - - renderDate () { - const { date, id } = this.props; - - const dateToDisplay = moment(date).fromNow(); - const fullDate = moment(date).format('LL LTS'); - - return ( -
- - { dateToDisplay } - { /* dynamic id required in case there are multple transactions in page */ } - - Date of the request: -
- { fullDate } -
-
- ); - } - - renderDataExpanded () { - if (!this.props.data) return null; - - const { isDataExpanded } = this.state; - const { data } = this.props; - - if (!isDataExpanded) { - return; - } - - return ( -
-

Transaction's Data

- { data } -
- ); - } - - noData () { - return this.props.data === '0x'; - } - - toggleDataExpanded = () => { - if (this.noData()) { - return; - } - this.setState({ - isDataExpanded: !this.state.isDataExpanded - }); - } - -} diff --git a/js/src/views/Signer/components/TransactionSecondaryDetails/index.js b/js/src/views/Signer/components/TransactionSecondaryDetails/index.js deleted file mode 100644 index 4b352c41a..000000000 --- a/js/src/views/Signer/components/TransactionSecondaryDetails/index.js +++ /dev/null @@ -1 +0,0 @@ -export default from './TransactionSecondaryDetails'; diff --git a/js/src/views/Signer/containers/RequestsPage/RequestsPage.js b/js/src/views/Signer/containers/RequestsPage/RequestsPage.js index ae2ba05fb..a15cb537d 100644 --- a/js/src/views/Signer/containers/RequestsPage/RequestsPage.js +++ b/js/src/views/Signer/containers/RequestsPage/RequestsPage.js @@ -24,7 +24,7 @@ import Store from '../../store'; import * as RequestsActions from '../../../../redux/providers/signerActions'; import { Container, Page, TxList } from '../../../../ui'; -import { RequestPending, RequestFinished } from '../../components'; +import { RequestPending } from '../../components'; import styles from './RequestsPage.css'; @@ -57,7 +57,6 @@ class RequestsPage extends Component {
{ this.renderPendingRequests() }
{ this.renderLocalQueue() }
-
{ this.renderFinishedRequests() }
); } @@ -106,24 +105,6 @@ class RequestsPage extends Component { ); } - renderFinishedRequests () { - const { finished } = this.props.signer; - - if (!finished.length) { - return; - } - - const items = finished.sort(this._sortRequests).map(this.renderFinished); - - return ( - -
- { items } -
-
- ); - } - renderPending = (data) => { const { actions, isTest } = this.props; const { payload, id, isSending, date } = data; @@ -143,27 +124,6 @@ class RequestsPage extends Component { /> ); } - - renderFinished = (data) => { - const { isTest } = this.props; - const { payload, id, result, msg, status, error, date } = data; - - return ( - - ); - } } function mapStateToProps (state) { From 7e2a072a2b8e183784482e62a7abfa02f36fae3b Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 29 Nov 2016 16:59:44 +0100 Subject: [PATCH 11/52] Remove finished rendering completely --- .../components/RequestFinished/index.js | 17 ---- .../RequestFinished/requestFinished.js | 87 ------------------- js/src/views/Signer/components/index.js | 18 ---- .../Signer/containers/Embedded/embedded.js | 2 +- .../containers/RequestsPage/RequestsPage.js | 2 +- 5 files changed, 2 insertions(+), 124 deletions(-) delete mode 100644 js/src/views/Signer/components/RequestFinished/index.js delete mode 100644 js/src/views/Signer/components/RequestFinished/requestFinished.js delete mode 100644 js/src/views/Signer/components/index.js diff --git a/js/src/views/Signer/components/RequestFinished/index.js b/js/src/views/Signer/components/RequestFinished/index.js deleted file mode 100644 index c5ed83b6b..000000000 --- a/js/src/views/Signer/components/RequestFinished/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -export default from './requestFinished'; diff --git a/js/src/views/Signer/components/RequestFinished/requestFinished.js b/js/src/views/Signer/components/RequestFinished/requestFinished.js deleted file mode 100644 index bce9e4038..000000000 --- a/js/src/views/Signer/components/RequestFinished/requestFinished.js +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -import React, { Component, PropTypes } from 'react'; - -import TransactionFinished from '../TransactionFinished'; -import SignRequest from '../SignRequest'; - -export default class RequestFinished extends Component { - static propTypes = { - id: PropTypes.object.isRequired, - result: PropTypes.any.isRequired, - date: PropTypes.instanceOf(Date).isRequired, - payload: PropTypes.oneOfType([ - PropTypes.shape({ transaction: PropTypes.object.isRequired }), - PropTypes.shape({ sign: PropTypes.object.isRequired }) - ]).isRequired, - msg: PropTypes.string, - status: PropTypes.string, - error: PropTypes.string, - className: PropTypes.string, - isTest: PropTypes.bool.isRequired, - store: PropTypes.object.isRequired - } - - render () { - const { payload, id, result, msg, status, error, date, className, isTest, store } = this.props; - - if (payload.sign) { - const { sign } = payload; - - return ( - - ); - } - - if (payload.transaction) { - const { transaction } = payload; - - return ( - - ); - } - - // Unknown payload - return null; - } -} diff --git a/js/src/views/Signer/components/index.js b/js/src/views/Signer/components/index.js deleted file mode 100644 index 7c891f621..000000000 --- a/js/src/views/Signer/components/index.js +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015, 2016 Ethcore (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -export RequestFinished from './RequestFinished'; -export RequestPending from './RequestPending'; diff --git a/js/src/views/Signer/containers/Embedded/embedded.js b/js/src/views/Signer/containers/Embedded/embedded.js index b62c1a6c0..af008609c 100644 --- a/js/src/views/Signer/containers/Embedded/embedded.js +++ b/js/src/views/Signer/containers/Embedded/embedded.js @@ -23,7 +23,7 @@ import Store from '../../store'; import * as RequestsActions from '../../../../redux/providers/signerActions'; import { Container } from '../../../../ui'; -import { RequestPending } from '../../components'; +import RequestPending from '../../components/RequestPending'; import styles from './embedded.css'; diff --git a/js/src/views/Signer/containers/RequestsPage/RequestsPage.js b/js/src/views/Signer/containers/RequestsPage/RequestsPage.js index a15cb537d..1ee88fc09 100644 --- a/js/src/views/Signer/containers/RequestsPage/RequestsPage.js +++ b/js/src/views/Signer/containers/RequestsPage/RequestsPage.js @@ -24,7 +24,7 @@ import Store from '../../store'; import * as RequestsActions from '../../../../redux/providers/signerActions'; import { Container, Page, TxList } from '../../../../ui'; -import { RequestPending } from '../../components'; +import RequestPending from '../../components/RequestPending'; import styles from './RequestsPage.css'; From df3c07b0a9a3919ad8d2550f986a04a314741de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 29 Nov 2016 17:14:28 +0100 Subject: [PATCH 12/52] adding proof to a panicker --- dapps/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index b185eb57a..9bb3be4a7 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -266,7 +266,11 @@ impl Server { #[cfg(test)] /// Returns address that this server is bound to. pub fn addr(&self) -> &SocketAddr { - &self.server.as_ref().expect("server is always Some at the start; it's consumed only when object is dropped; qed").addrs()[0] + self.server.as_ref() + .expect("server is always Some at the start; it's consumed only when object is dropped; qed") + .addrs() + .first() + .expect("You cannot start the server without binding to at least one address; qed") } } From cce195a98bd6abe9c3ba9d02d817cb2ab36423a7 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 30 Nov 2016 17:28:55 +0100 Subject: [PATCH 13/52] fix status bar to bottom of the screen --- js/src/views/Application/Status/status.css | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/js/src/views/Application/Status/status.css b/js/src/views/Application/Status/status.css index de043a1ad..90b40b606 100644 --- a/js/src/views/Application/Status/status.css +++ b/js/src/views/Application/Status/status.css @@ -15,10 +15,15 @@ /* along with Parity. If not, see . */ .status { - padding: 0.5em; + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 1000; + padding: .4em .5em; font-size: x-small; color: #ccc; - background-color: rgba(0, 0, 0, 0.2) + background-color: rgba(0, 0, 0, 0.8); } .title { @@ -42,7 +47,7 @@ .netinfo { display: flex; align-items: center; - color: #ddd; + color: #ddd; } .netinfo > * { From f9f91837c29a1136efdd86665268a92b81344ed5 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 30 Nov 2016 17:41:23 +0100 Subject: [PATCH 14/52] rework status bar layout - floats -> Flexbox - align to content width --- js/src/views/Application/Status/status.css | 27 +++++----------------- js/src/views/Application/Status/status.js | 2 +- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/js/src/views/Application/Status/status.css b/js/src/views/Application/Status/status.css index 90b40b606..a761801e4 100644 --- a/js/src/views/Application/Status/status.css +++ b/js/src/views/Application/Status/status.css @@ -20,19 +20,16 @@ left: 0; right: 0; z-index: 1000; + display: flex; + align-items: center; padding: .4em .5em; font-size: x-small; color: #ccc; background-color: rgba(0, 0, 0, 0.8); } -.title { - margin: 0 0.5em 0 2em; -} - .enode { word-wrap: break-word; - float: right; } .enode > * { @@ -40,25 +37,24 @@ margin: 0.25em 0.5em; vertical-align: top; } - -.block { +.enode > :last-child { + margin-right: 0; } .netinfo { display: flex; + flex-grow: 1; align-items: center; color: #ddd; } .netinfo > * { - display: inline-block; margin-left: 1em; } .network { padding: 0.25em 0.5em; - display: inline-block; - border-radius: 4px; + border-radius: .4em; line-height: 1.2; text-transform: uppercase; } @@ -70,14 +66,3 @@ .networktest { background: rgb(136, 0, 0); } - -.peers { -} - -.version { - padding: 0.25em 0.5em; - float: left; -} - -.syncing { -} diff --git a/js/src/views/Application/Status/status.js b/js/src/views/Application/Status/status.js index 6417d5d28..0c9c5d6ec 100644 --- a/js/src/views/Application/Status/status.js +++ b/js/src/views/Application/Status/status.js @@ -46,7 +46,6 @@ class Status extends Component {
{ clientVersion }
- { this.renderEnode() }
@@ -56,6 +55,7 @@ class Status extends Component { { netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
+ { this.renderEnode() }
); } From 890f880a890c4c7f8c4f597bd80664b3cfe968cc Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 30 Nov 2016 17:45:14 +0100 Subject: [PATCH 15/52] status bar: beautify enode icon --- js/src/views/Application/Status/status.css | 4 ++-- js/src/views/Application/Status/status.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/src/views/Application/Status/status.css b/js/src/views/Application/Status/status.css index a761801e4..8721bc4c2 100644 --- a/js/src/views/Application/Status/status.css +++ b/js/src/views/Application/Status/status.css @@ -34,8 +34,8 @@ .enode > * { display: inline-block; - margin: 0.25em 0.5em; - vertical-align: top; + margin: 0 .25em; + vertical-align: middle; } .enode > :last-child { margin-right: 0; diff --git a/js/src/views/Application/Status/status.js b/js/src/views/Application/Status/status.js index 0c9c5d6ec..287e7a6ee 100644 --- a/js/src/views/Application/Status/status.js +++ b/js/src/views/Application/Status/status.js @@ -73,7 +73,7 @@ class Status extends Component { return (
- +
{ abbreviated }
); From 60a8aabe1961b4795d4d41bbbe13483234a4a2d9 Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 30 Nov 2016 17:58:18 +0100 Subject: [PATCH 16/52] differentiate Snackbar from background --- js/src/views/Application/Snackbar/snackbar.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/js/src/views/Application/Snackbar/snackbar.js b/js/src/views/Application/Snackbar/snackbar.js index ac6e6b950..fdeb48c57 100644 --- a/js/src/views/Application/Snackbar/snackbar.js +++ b/js/src/views/Application/Snackbar/snackbar.js @@ -19,10 +19,17 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { Snackbar as SnackbarMUI } from 'material-ui'; -import { darkBlack } from 'material-ui/styles/colors'; +import { darkBlack, grey800 } from 'material-ui/styles/colors'; import { closeSnackbar } from '../../../redux/providers/snackbarActions'; +const bodyStyle = { + backgroundColor: darkBlack, + borderStyle: 'solid', + borderColor: grey800, + borderWidth: '1px 1px 0 1px' +}; + class Snackbar extends Component { static propTypes = { closeSnackbar: PropTypes.func.isRequired, @@ -40,7 +47,7 @@ class Snackbar extends Component { open={ open } message={ message } autoHideDuration={ cooldown } - bodyStyle={ { backgroundColor: darkBlack } } + bodyStyle={ bodyStyle } onRequestClose={ this.handleClose } /> ); From eee03b542de3b01ca651d7d4bf06e1d1f7b6362c Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 30 Nov 2016 19:48:10 +0100 Subject: [PATCH 17/52] add account recovery phrase page --- js/package.json | 1 + .../AccountDetails/recovery-page.ejs | 34 +++++++++++++++++++ js/webpack/app.js | 4 +++ 3 files changed, 39 insertions(+) create mode 100644 js/src/modals/CreateAccount/AccountDetails/recovery-page.ejs diff --git a/js/package.json b/js/package.json index 408706016..7f2a3fb9d 100644 --- a/js/package.json +++ b/js/package.json @@ -72,6 +72,7 @@ "core-js": "~2.4.1", "coveralls": "~2.11.11", "css-loader": "~0.26.0", + "ejs-loader": "~0.3.0", "enzyme": "2.3.0", "eslint": "~3.10.2", "eslint-config-semistandard": "~7.0.0", diff --git a/js/src/modals/CreateAccount/AccountDetails/recovery-page.ejs b/js/src/modals/CreateAccount/AccountDetails/recovery-page.ejs new file mode 100644 index 000000000..88966bbb8 --- /dev/null +++ b/js/src/modals/CreateAccount/AccountDetails/recovery-page.ejs @@ -0,0 +1,34 @@ + + + + + Recovery phrase for <%= name %> + + + + + +

Recovery phrase for your Parity account <%= name %>

+
<%= phrase %>
+ + diff --git a/js/webpack/app.js b/js/webpack/app.js index 320410b2e..aff9b8aac 100644 --- a/js/webpack/app.js +++ b/js/webpack/app.js @@ -64,6 +64,10 @@ module.exports = { test: /\.json$/, use: [ 'json-loader' ] }, + { + test: /\.ejs$/, + use: [ 'ejs-loader' ] + }, { test: /\.html$/, use: [ From 35fe4de6224cbc514d745e74d1fb917dde91534c Mon Sep 17 00:00:00 2001 From: Jannis R Date: Wed, 30 Nov 2016 19:58:52 +0100 Subject: [PATCH 18/52] add recovery page print button --- .../AccountDetails/accountDetails.js | 26 ++++++++ .../CreateAccount/AccountDetails/print.js | 61 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 js/src/modals/CreateAccount/AccountDetails/print.js diff --git a/js/src/modals/CreateAccount/AccountDetails/accountDetails.js b/js/src/modals/CreateAccount/AccountDetails/accountDetails.js index 14c858c06..6323350f8 100644 --- a/js/src/modals/CreateAccount/AccountDetails/accountDetails.js +++ b/js/src/modals/CreateAccount/AccountDetails/accountDetails.js @@ -15,8 +15,13 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; +import PrintIcon from 'material-ui/svg-icons/action/print'; import { Form, Input, InputAddress } from '../../../ui'; +import Button from '../../../ui/Button'; + +import print from './print'; +import recoveryPage from './recovery-page.ejs'; export default class AccountDetails extends Component { static propTypes = { @@ -42,6 +47,7 @@ export default class AccountDetails extends Component { label='address' value={ address } /> { this.renderPhrase() } + { this.renderPhraseCopyButton() } ); } @@ -62,4 +68,24 @@ export default class AccountDetails extends Component { value={ phrase } /> ); } + + renderPhraseCopyButton () { + const { phrase } = this.props; + if (!phrase) { + return null; + } + + return ( +
diff --git a/js/src/views/Account/account.js b/js/src/views/Account/account.js index e27333cbf..21d2f380c 100644 --- a/js/src/views/Account/account.js +++ b/js/src/views/Account/account.js @@ -64,12 +64,6 @@ class Account extends Component { } componentDidMount () { - const { api } = this.context; - const { address } = this.props.params; - const { isTestnet } = this.props; - - const verificationStore = new VerificationStore(api, address, isTestnet); - this.setState({ verificationStore }); this.setVisibleAccounts(); } @@ -80,6 +74,15 @@ class Account extends Component { if (prevAddress !== nextAddress) { this.setVisibleAccounts(nextProps); } + + const { isTestnet } = nextProps; + if (typeof isTestnet === 'boolean' && !this.state.verificationStore) { + const { api } = this.context; + const { address } = nextProps.params; + this.setState({ + verificationStore: new VerificationStore(api, address, isTestnet) + }); + } } componentWillUnmount () { @@ -115,7 +118,8 @@ class Account extends Component {
+ balance={ balance } + /> diff --git a/js/src/views/Contract/contract.js b/js/src/views/Contract/contract.js index 613bf70b9..54d06f228 100644 --- a/js/src/views/Contract/contract.js +++ b/js/src/views/Contract/contract.js @@ -132,7 +132,8 @@ class Contract extends Component {
+ balance={ balance } + /> @@ -447,7 +448,10 @@ function mapStateToProps (state) { } function mapDispatchToProps (dispatch) { - return bindActionCreators({ newError, setVisibleAccounts }, dispatch); + return bindActionCreators({ + newError, + setVisibleAccounts + }, dispatch); } export default connect( From 4f4bfb2239d5d0d62a370c792935fe9ed17796be Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Wed, 30 Nov 2016 20:46:47 +0000 Subject: [PATCH 22/52] [ci skip] js-precompiled 20161130-204501 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index caeb7a986..4d1bba344 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#da35604af4259da3abd7a12a4c4925906c78f746" +source = "git+https://github.com/ethcore/js-precompiled.git#b3f0e3ddedf9afee35ca8384a74158df572973c7" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 408706016..c6fab4119 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.79", + "version": "0.2.80", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From b7dc60ace53922e4bcf5cd25830f5c623758b9b0 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 30 Nov 2016 23:33:17 +0100 Subject: [PATCH 23/52] Don't share the snapshot while downloading old blocks --- sync/src/chain.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index ff60d1748..bd312c9ee 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1426,7 +1426,10 @@ impl ChainSync { packet.append(&chain.best_block_hash); packet.append(&chain.genesis_hash); if warp_protocol { - let manifest = io.snapshot_service().manifest(); + let manifest = match self.old_blocks.is_some() { + true => None, + false => io.snapshot_service().manifest(), + }; let block_number = manifest.as_ref().map_or(0, |m| m.block_number); let manifest_hash = manifest.map_or(H256::new(), |m| m.into_rlp().sha3()); packet.append(&manifest_hash); From c4125a84b16bfecec33004587042306a1225f1ec Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Thu, 1 Dec 2016 07:07:52 +0700 Subject: [PATCH 24/52] Update gitlab-ci CARGOFLAGS -> -j $(nproc) --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6662caee6..df1085020 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ variables: SIMPLECOV: "true" RUST_BACKTRACE: "1" RUSTFLAGS: "" - CARGOFLAGS: "" + CARGOFLAGS: "-j $(nproc)" cache: key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME" untracked: true @@ -312,8 +312,8 @@ darwin: - stable - triggers script: - - cargo build --release -p ethstore $CARGOFLAGS - - cargo build --release $CARGOFLAGS + - cargo build -j 8 --release -p ethstore #$CARGOFLAGS + - cargo build -j 8 --release #$CARGOFLAGS - rm -rf parity.md5 - md5sum target/release/parity > parity.md5 - packagesbuild -v mac/Parity.pkgproj @@ -350,7 +350,7 @@ windows: - set RUST_BACKTRACE=1 - set RUSTFLAGS=%RUSTFLAGS% - rustup default stable-x86_64-pc-windows-msvc - - cargo build --release %CARGOFLAGS% + - cargo build -j 8 --release #%CARGOFLAGS% - curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll - curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe From 70c6aebca5fa25555cb6846718004fab081df5fa Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Thu, 1 Dec 2016 07:15:35 +0700 Subject: [PATCH 25/52] Update gitlab-ci -j $(nproc) in build --- .gitlab-ci.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index df1085020..94ac69d2c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ variables: SIMPLECOV: "true" RUST_BACKTRACE: "1" RUSTFLAGS: "" - CARGOFLAGS: "-j $(nproc)" + CARGOFLAGS: "" cache: key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME" untracked: true @@ -20,7 +20,7 @@ linux-stable: - stable - triggers script: - - cargo build --release $CARGOFLAGS + - cargo build -j $(nproc) --release $CARGOFLAGS - strip target/release/parity - md5sum target/release/parity > parity.md5 - sh scripts/deb-build.sh amd64 @@ -52,7 +52,7 @@ linux-beta: - stable - triggers script: - - cargo build --release $CARGOFLAGS + - cargo build -j $(nproc) --release $CARGOFLAGS - strip target/release/parity tags: - rust @@ -71,7 +71,7 @@ linux-nightly: - stable - triggers script: - - cargo build --release $CARGOFLAGS + - cargo build -j $(nproc) --release $CARGOFLAGS - strip target/release/parity tags: - rust @@ -92,7 +92,7 @@ linux-centos: script: - export CXX="g++" - export CC="gcc" - - cargo build --release $CARGOFLAGS + - cargo build -j $(nproc) --release $CARGOFLAGS - strip target/release/parity - md5sum target/release/parity > parity.md5 - aws configure set aws_access_key_id $s3_key @@ -119,7 +119,7 @@ linux-i686: script: - export HOST_CC=gcc - export HOST_CXX=g++ - - cargo build --target i686-unknown-linux-gnu --release $CARGOFLAGS + - cargo build -j $(nproc) --target i686-unknown-linux-gnu --release $CARGOFLAGS - strip target/i686-unknown-linux-gnu/release/parity - md5sum target/i686-unknown-linux-gnu/release/parity > parity.md5 - sh scripts/deb-build.sh i386 @@ -161,7 +161,7 @@ linux-armv7: - echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - cat .cargo/config - - cargo build --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS + - cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS - arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity - md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5 - sh scripts/deb-build.sh armhf @@ -203,7 +203,7 @@ linux-arm: - echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - cat .cargo/config - - cargo build --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS + - cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS - arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity - md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5 - sh scripts/deb-build.sh armhf @@ -245,7 +245,7 @@ linux-armv6: - echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config - echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config - cat .cargo/config - - cargo build --target arm-unknown-linux-gnueabi --release $CARGOFLAGS + - cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --release $CARGOFLAGS - arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity - md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5 - aws configure set aws_access_key_id $s3_key @@ -280,7 +280,7 @@ linux-aarch64: - echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config - echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config - cat .cargo/config - - cargo build --target aarch64-unknown-linux-gnu --release $CARGOFLAGS + - cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --release $CARGOFLAGS - aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity - md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5 - sh scripts/deb-build.sh arm64 @@ -413,7 +413,7 @@ test-windows: - git submodule update --init --recursive script: - set RUST_BACKTRACE=1 - - cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release + - cargo -j 8 test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release tags: - rust-windows allow_failure: true From 61eb2a910462d154a2e9f1572d942add2e6b7080 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Thu, 1 Dec 2016 07:48:06 +0700 Subject: [PATCH 26/52] Update test.sh add -j 8 for test --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 44bffa7d9..3e9074478 100755 --- a/test.sh +++ b/test.sh @@ -19,5 +19,5 @@ case $1 in esac . ./scripts/targets.sh -cargo test $OPTIONS --features "$FEATURES" $TARGETS $1 \ +cargo test -j 8 $OPTIONS --features "$FEATURES" $TARGETS $1 \ From 3ef569329acd51ce1355fe6bd037c67b396eba4e Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Thu, 1 Dec 2016 01:21:59 +0000 Subject: [PATCH 27/52] [ci skip] js-precompiled 20161201-011624 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d1bba344..95a795bc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#b3f0e3ddedf9afee35ca8384a74158df572973c7" +source = "git+https://github.com/ethcore/js-precompiled.git#41719ab7b7cb9682a8a32fdfaad7749d5a1285b1" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 67fd98976..bd4be6802 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.80", + "version": "0.2.81", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 0f987a2206bcfbfdcee7e2d8696c3fb44f618301 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Thu, 1 Dec 2016 04:48:29 +0000 Subject: [PATCH 28/52] [ci skip] js-precompiled 20161201-044643 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95a795bc3..035e5517c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1263,7 +1263,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#41719ab7b7cb9682a8a32fdfaad7749d5a1285b1" +source = "git+https://github.com/ethcore/js-precompiled.git#d99369b5010cfa73c3a62eb8c031bf873a7ca709" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index bd4be6802..4957c7f19 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "0.2.81", + "version": "0.2.82", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 08a6be5d62325c5e358f4d737ebe6119bacb13ac Mon Sep 17 00:00:00 2001 From: Jannis R Date: Thu, 1 Dec 2016 12:11:03 +0100 Subject: [PATCH 29/52] recovery phrase: move print button to modal actions --- .../AccountDetails/accountDetails.js | 30 ------------------- js/src/modals/CreateAccount/createAccount.js | 23 ++++++++++++-- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/js/src/modals/CreateAccount/AccountDetails/accountDetails.js b/js/src/modals/CreateAccount/AccountDetails/accountDetails.js index 945bcc975..14c858c06 100644 --- a/js/src/modals/CreateAccount/AccountDetails/accountDetails.js +++ b/js/src/modals/CreateAccount/AccountDetails/accountDetails.js @@ -15,15 +15,8 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; -import PrintIcon from 'material-ui/svg-icons/action/print'; import { Form, Input, InputAddress } from '../../../ui'; -import Button from '../../../ui/Button'; - -import { createIdentityImg } from '../../../api/util/identity'; -import print from './print'; -import recoveryPage from './recovery-page.ejs'; -import ParityLogo from '../../../../assets/images/parity-logo-black-no-text.svg'; export default class AccountDetails extends Component { static propTypes = { @@ -49,7 +42,6 @@ export default class AccountDetails extends Component { label='address' value={ address } /> { this.renderPhrase() } - { this.renderPhraseCopyButton() } ); } @@ -70,26 +62,4 @@ export default class AccountDetails extends Component { value={ phrase } /> ); } - - renderPhraseCopyButton () { - const { phrase } = this.props; - if (!phrase) { - return null; - } - - return ( -