diff --git a/api/src/handlers.rs b/api/src/handlers.rs index 3754894ae..cba7994dc 100644 --- a/api/src/handlers.rs +++ b/api/src/handlers.rs @@ -58,7 +58,7 @@ impl UtxoHandler { .get_block_header_by_output_commit(&commit) .map_err(|_| Error::NotFound)?; - Ok(Output::from_output(&out, &header)) + Ok(Output::from_output(&out, &header, false)) } } @@ -138,10 +138,10 @@ impl Handler for SumTreeHandler { } } match *path_elems.last().unwrap() { - "roots" => json_response(&self.get_roots()), - "lastutxos" => json_response(&self.get_last_n_utxo(last_n)), - "lastrangeproofs" => json_response(&self.get_last_n_rangeproof(last_n)), - "lastkernels" => json_response(&self.get_last_n_kernel(last_n)), + "roots" => json_response_pretty(&self.get_roots()), + "lastutxos" => json_response_pretty(&self.get_last_n_utxo(last_n)), + "lastrangeproofs" => json_response_pretty(&self.get_last_n_rangeproof(last_n)), + "lastkernels" => json_response_pretty(&self.get_last_n_kernel(last_n)), _ => Ok(Response::with((status::BadRequest, ""))), } } @@ -154,7 +154,7 @@ pub struct PeersAllHandler { impl Handler for PeersAllHandler { fn handle(&self, _req: &mut Request) -> IronResult { let peers = &self.peer_store.all_peers(); - json_response(&peers) + json_response_pretty(&peers) } } @@ -266,12 +266,22 @@ fn json_response(s: &T) -> IronResult where T: Serialize, { - match serde_json::to_string_pretty(s) { + match serde_json::to_string(s) { Ok(json) => Ok(Response::with((status::Ok, json))), Err(_) => Ok(Response::with((status::InternalServerError, ""))), } } +// pretty-printed version of above +fn json_response_pretty(s: &T) -> IronResult +where + T: Serialize, +{ + match serde_json::to_string_pretty(s) { + Ok(json) => Ok(Response::with((status::Ok, json))), + Err(_) => Ok(Response::with((status::InternalServerError, ""))), + } +} /// Start all server HTTP handlers. Register all of them with Iron /// and runs the corresponding HTTP server. pub fn start_rest_apis( diff --git a/api/src/types.rs b/api/src/types.rs index bc61eb523..1f76e3a90 100644 --- a/api/src/types.rs +++ b/api/src/types.rs @@ -138,7 +138,7 @@ pub struct Output { /// The homomorphic commitment representing the output's amount pub commit: pedersen::Commitment, /// A proof that the commitment is in the right range - pub proof: pedersen::RangeProof, + pub proof: Option, /// The height of the block creating this output pub height: u64, /// The lock height (earliest block this output can be spent) @@ -146,7 +146,7 @@ pub struct Output { } impl Output { - pub fn from_output(output: &core::Output, block_header: &core::BlockHeader) -> Output { + pub fn from_output(output: &core::Output, block_header: &core::BlockHeader, include_proof:bool) -> Output { let (output_type, lock_height) = match output.features { x if x.contains(core::transaction::COINBASE_OUTPUT) => ( OutputType::Coinbase, @@ -158,7 +158,10 @@ impl Output { Output { output_type: output_type, commit: output.commit, - proof: output.proof, + proof: match include_proof { + true => Some(output.proof), + false => None, + }, height: block_header.height, lock_height: lock_height, } diff --git a/chain/src/sumtree.rs b/chain/src/sumtree.rs index 9071bd77f..bd6feef9a 100644 --- a/chain/src/sumtree.rs +++ b/chain/src/sumtree.rs @@ -20,7 +20,6 @@ use std::collections::HashMap; use std::path::Path; use std::sync::Arc; -use util::secp; use util::secp::pedersen::{RangeProof, Commitment}; use core::core::{Block, Output, SumCommit, TxKernel}; @@ -229,7 +228,6 @@ impl<'a> Extension<'a> { /// applied in order of the provided Vec. If pruning is enabled, inputs also /// prune MMR data. pub fn apply_block(&mut self, b: &Block) -> Result<(), Error> { - let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit); // doing inputs first guarantees an input can't spend an output in the // same block, enforcing block cut-through @@ -261,7 +259,6 @@ impl<'a> Extension<'a> { .push( SumCommit { commit: out.commitment(), - secp: secp.clone(), }, Some(out.switch_commit_hash()), ) diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 57b21f39f..e6c827814 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -17,6 +17,7 @@ use byteorder::{BigEndian, ByteOrder}; use blake2::blake2b::blake2b; use util::secp::{self, Message, Secp256k1, Signature}; +use util::static_secp_instance; use util::secp::pedersen::{Commitment, RangeProof}; use std::cmp::Ordering; use std::ops; @@ -322,6 +323,7 @@ impl Transaction { Ok(rsum) } + /// Builds a transaction kernel pub fn build_kernel(&self, excess: Commitment) -> TxKernel { TxKernel { features: DEFAULT_KERNEL, @@ -533,8 +535,6 @@ impl Output { pub struct SumCommit { /// Output commitment pub commit: Commitment, - /// Secp256k1 used to sum - pub secp: Secp256k1, } /// Outputs get summed through their commitments. @@ -544,7 +544,6 @@ impl Summable for SumCommit { fn sum(&self) -> SumCommit { SumCommit { commit: self.commit.clone(), - secp: self.secp.clone(), } } @@ -562,12 +561,10 @@ impl Writeable for SumCommit { impl Readable for SumCommit { fn read(reader: &mut Reader) -> Result { - let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit); let commit = Commitment::read(reader)?; Ok(SumCommit { commit: commit, - secp: secp, }) } } @@ -576,7 +573,8 @@ impl ops::Add for SumCommit { type Output = SumCommit; fn add(self, other: SumCommit) -> SumCommit { - let sum = match self.secp + let secp = static_secp_instance(); + let sum = match secp.lock().unwrap() .commit_sum(vec![self.commit.clone(), other.commit.clone()], vec![]) { Ok(s) => s, @@ -584,7 +582,6 @@ impl ops::Add for SumCommit { }; SumCommit { commit: sum, - secp: self.secp, } } } diff --git a/keychain/Cargo.toml b/keychain/Cargo.toml index 41102fb97..b7af88dec 100644 --- a/keychain/Cargo.toml +++ b/keychain/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Antioch Peverell"] byteorder = "~1" blake2-rfc = "~0.2.17" rand = "~0.3" +slog = { version = "^2.0.12", features = ["max_level_trace", "release_max_level_trace"] } serde = "~1.0.8" serde_derive = "~1.0.8" serde_json = "~1.0.3" diff --git a/keychain/src/extkey.rs b/keychain/src/extkey.rs index 78c3235f6..87481a9a0 100644 --- a/keychain/src/extkey.rs +++ b/keychain/src/extkey.rs @@ -134,7 +134,7 @@ impl Identifier { } fn from_hex(hex: &str) -> Result { - let bytes = util::from_hex(hex.to_string())?; + let bytes = util::from_hex(hex.to_string()).unwrap(); Ok(Identifier::from_bytes(&bytes)) } diff --git a/keychain/src/keychain.rs b/keychain/src/keychain.rs index fc9fd0d86..d5297f387 100644 --- a/keychain/src/keychain.rs +++ b/keychain/src/keychain.rs @@ -19,6 +19,7 @@ use util::secp; use util::secp::{Message, Secp256k1, Signature}; use util::secp::key::SecretKey; use util::secp::pedersen::{Commitment, ProofMessage, ProofInfo, RangeProof}; +use util::logger::LOGGER; use blake2; use blind::{BlindSum, BlindingFactor}; use extkey::{self, Identifier}; @@ -93,11 +94,18 @@ impl Keychain { Ok(key_id) } - fn derived_key(&self, key_id: &Identifier) -> Result { + fn derived_key_search(&self, key_id: &Identifier, n_child: Option) -> Result { if let Some(key) = self.key_overrides.get(key_id) { return Ok(*key); } + trace!(LOGGER, "Derived Key key_id: {}", key_id); + + if let Some(n) = n_child{ + let extkey = self.extkey.derive(&self.secp, n)?; + return Ok(extkey.key); + }; + for i in 1..10000 { let extkey = self.extkey.derive(&self.secp, i)?; if extkey.identifier(&self.secp)? == *key_id { @@ -109,12 +117,26 @@ impl Keychain { )) } + fn derived_key(&self, key_id: &Identifier) -> Result { + self.derived_key_search(key_id, None) + } + + fn derived_key_from_index(&self, key_id: &Identifier, n_child:u32) -> Result { + self.derived_key_search(key_id, Some(n_child)) + } + pub fn commit(&self, amount: u64, key_id: &Identifier) -> Result { let skey = self.derived_key(key_id)?; let commit = self.secp.commit(amount, skey)?; Ok(commit) } + pub fn commit_with_key_index(&self, amount: u64, key_id: &Identifier, n_child: u32) -> Result { + let skey = self.derived_key_from_index(key_id, n_child)?; + let commit = self.secp.commit(amount, skey)?; + Ok(commit) + } + pub fn switch_commit(&self, key_id: &Identifier) -> Result { let skey = self.derived_key(key_id)?; let commit = self.secp.switch_commit(skey)?; diff --git a/keychain/src/lib.rs b/keychain/src/lib.rs index 3e9f73237..9e19d2a4c 100644 --- a/keychain/src/lib.rs +++ b/keychain/src/lib.rs @@ -22,6 +22,8 @@ extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; +#[macro_use] +extern crate slog; mod blind; mod extkey; diff --git a/util/Cargo.toml b/util/Cargo.toml index d7fd103e3..ccb91973c 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -10,6 +10,7 @@ slog = { version = "^2.0.12", features = ["max_level_trace", "release_max_level_ slog-term = "^2.2.0" slog-async = "^2.1.0" lazy_static = "~0.2.8" +rand = "0.3" serde = "~1.0.8" serde_derive = "~1.0.8" secp256k1zkp = { git = "https://github.com/mimblewimble/rust-secp256k1-zkp", tag="grin_integration_1" } diff --git a/util/src/lib.rs b/util/src/lib.rs index 5931a6c3b..905ad030b 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -26,6 +26,8 @@ extern crate slog; extern crate slog_async; extern crate slog_term; +extern crate rand; + #[macro_use] extern crate lazy_static; @@ -41,6 +43,10 @@ pub use secp_ as secp; pub mod logger; pub use logger::{init_logger, init_test_logger, LOGGER}; +// Static secp instance +pub mod secp_static; +pub use secp_static::static_secp_instance; + pub mod types; pub use types::LoggingConfig; diff --git a/util/src/secp_static.rs b/util/src/secp_static.rs new file mode 100644 index 000000000..c7922f797 --- /dev/null +++ b/util/src/secp_static.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Grin Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Globally accessible static instance of secp256k1, to avoid +//! initialisation overhead + +use std::sync::{Arc, Mutex}; +use rand::{thread_rng}; +use secp_ as secp; + +lazy_static! { + /// Static reference to secp instance + pub static ref SECP256K1:Arc> + = Arc::new(Mutex::new(secp::Secp256k1::with_caps(secp::ContextFlag::Commit))); +} + +/// Returns the static instance, but calls randomize on it as well +/// (Recommended to avoid side channel attacks +pub fn static_secp_instance()-> Arc>{ + let mut secp_inst=SECP256K1.lock().unwrap(); + secp_inst.randomize(&mut thread_rng()); + SECP256K1.clone() +} diff --git a/wallet/src/checker.rs b/wallet/src/checker.rs index eac4253c5..7a04d0967 100644 --- a/wallet/src/checker.rs +++ b/wallet/src/checker.rs @@ -67,7 +67,7 @@ pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(), .filter(|out| out.status != OutputStatus::Spent) { let key_id = keychain.derive_key_id(out.n_child).unwrap(); - let commit = keychain.commit(out.value, &key_id).unwrap(); + let commit = keychain.commit_with_key_index(out.value, &key_id, out.n_child).unwrap(); commits.push(commit); wallet_outputs.insert(commit, out.key_id.clone()); }