mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
Wallet output selection performance (#238)
* allow selecting a commit while providing a key index * added static reference to libsecp that can be called throughout * don't serialise rangeproof to json if it's not desired
This commit is contained in:
parent
8f0373b81e
commit
48a60858ba
12 changed files with 96 additions and 23 deletions
|
@ -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<Response> {
|
||||
let peers = &self.peer_store.all_peers();
|
||||
json_response(&peers)
|
||||
json_response_pretty(&peers)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,12 +266,22 @@ fn json_response<T>(s: &T) -> IronResult<Response>
|
|||
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<T>(s: &T) -> IronResult<Response>
|
||||
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<T>(
|
||||
|
|
|
@ -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<pedersen::RangeProof>,
|
||||
/// 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,
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
)
|
||||
|
|
|
@ -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<SumCommit, ser::Error> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -134,7 +134,7 @@ impl Identifier {
|
|||
}
|
||||
|
||||
fn from_hex(hex: &str) -> Result<Identifier, Error> {
|
||||
let bytes = util::from_hex(hex.to_string())?;
|
||||
let bytes = util::from_hex(hex.to_string()).unwrap();
|
||||
Ok(Identifier::from_bytes(&bytes))
|
||||
}
|
||||
|
||||
|
|
|
@ -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<SecretKey, Error> {
|
||||
fn derived_key_search(&self, key_id: &Identifier, n_child: Option<u32>) -> Result<SecretKey, Error> {
|
||||
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<SecretKey, Error> {
|
||||
self.derived_key_search(key_id, None)
|
||||
}
|
||||
|
||||
fn derived_key_from_index(&self, key_id: &Identifier, n_child:u32) -> Result<SecretKey, Error> {
|
||||
self.derived_key_search(key_id, Some(n_child))
|
||||
}
|
||||
|
||||
pub fn commit(&self, amount: u64, key_id: &Identifier) -> Result<Commitment, Error> {
|
||||
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<Commitment, Error> {
|
||||
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<Commitment, Error> {
|
||||
let skey = self.derived_key(key_id)?;
|
||||
let commit = self.secp.switch_commit(skey)?;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
34
util/src/secp_static.rs
Normal file
34
util/src/secp_static.rs
Normal file
|
@ -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<Mutex<secp::Secp256k1>>
|
||||
= 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<Mutex<secp::Secp256k1>>{
|
||||
let mut secp_inst=SECP256K1.lock().unwrap();
|
||||
secp_inst.randomize(&mut thread_rng());
|
||||
SECP256K1.clone()
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue