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)
|
.get_block_header_by_output_commit(&commit)
|
||||||
.map_err(|_| Error::NotFound)?;
|
.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() {
|
match *path_elems.last().unwrap() {
|
||||||
"roots" => json_response(&self.get_roots()),
|
"roots" => json_response_pretty(&self.get_roots()),
|
||||||
"lastutxos" => json_response(&self.get_last_n_utxo(last_n)),
|
"lastutxos" => json_response_pretty(&self.get_last_n_utxo(last_n)),
|
||||||
"lastrangeproofs" => json_response(&self.get_last_n_rangeproof(last_n)),
|
"lastrangeproofs" => json_response_pretty(&self.get_last_n_rangeproof(last_n)),
|
||||||
"lastkernels" => json_response(&self.get_last_n_kernel(last_n)),
|
"lastkernels" => json_response_pretty(&self.get_last_n_kernel(last_n)),
|
||||||
_ => Ok(Response::with((status::BadRequest, ""))),
|
_ => Ok(Response::with((status::BadRequest, ""))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ pub struct PeersAllHandler {
|
||||||
impl Handler for PeersAllHandler {
|
impl Handler for PeersAllHandler {
|
||||||
fn handle(&self, _req: &mut Request) -> IronResult<Response> {
|
fn handle(&self, _req: &mut Request) -> IronResult<Response> {
|
||||||
let peers = &self.peer_store.all_peers();
|
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
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
match serde_json::to_string_pretty(s) {
|
match serde_json::to_string(s) {
|
||||||
Ok(json) => Ok(Response::with((status::Ok, json))),
|
Ok(json) => Ok(Response::with((status::Ok, json))),
|
||||||
Err(_) => Ok(Response::with((status::InternalServerError, ""))),
|
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
|
/// Start all server HTTP handlers. Register all of them with Iron
|
||||||
/// and runs the corresponding HTTP server.
|
/// and runs the corresponding HTTP server.
|
||||||
pub fn start_rest_apis<T>(
|
pub fn start_rest_apis<T>(
|
||||||
|
|
|
@ -138,7 +138,7 @@ pub struct Output {
|
||||||
/// The homomorphic commitment representing the output's amount
|
/// The homomorphic commitment representing the output's amount
|
||||||
pub commit: pedersen::Commitment,
|
pub commit: pedersen::Commitment,
|
||||||
/// A proof that the commitment is in the right range
|
/// 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
|
/// The height of the block creating this output
|
||||||
pub height: u64,
|
pub height: u64,
|
||||||
/// The lock height (earliest block this output can be spent)
|
/// The lock height (earliest block this output can be spent)
|
||||||
|
@ -146,7 +146,7 @@ pub struct Output {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
let (output_type, lock_height) = match output.features {
|
||||||
x if x.contains(core::transaction::COINBASE_OUTPUT) => (
|
x if x.contains(core::transaction::COINBASE_OUTPUT) => (
|
||||||
OutputType::Coinbase,
|
OutputType::Coinbase,
|
||||||
|
@ -158,7 +158,10 @@ impl Output {
|
||||||
Output {
|
Output {
|
||||||
output_type: output_type,
|
output_type: output_type,
|
||||||
commit: output.commit,
|
commit: output.commit,
|
||||||
proof: output.proof,
|
proof: match include_proof {
|
||||||
|
true => Some(output.proof),
|
||||||
|
false => None,
|
||||||
|
},
|
||||||
height: block_header.height,
|
height: block_header.height,
|
||||||
lock_height: lock_height,
|
lock_height: lock_height,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use util::secp;
|
|
||||||
use util::secp::pedersen::{RangeProof, Commitment};
|
use util::secp::pedersen::{RangeProof, Commitment};
|
||||||
|
|
||||||
use core::core::{Block, Output, SumCommit, TxKernel};
|
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
|
/// applied in order of the provided Vec. If pruning is enabled, inputs also
|
||||||
/// prune MMR data.
|
/// prune MMR data.
|
||||||
pub fn apply_block(&mut self, b: &Block) -> Result<(), Error> {
|
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
|
// doing inputs first guarantees an input can't spend an output in the
|
||||||
// same block, enforcing block cut-through
|
// same block, enforcing block cut-through
|
||||||
|
@ -261,7 +259,6 @@ impl<'a> Extension<'a> {
|
||||||
.push(
|
.push(
|
||||||
SumCommit {
|
SumCommit {
|
||||||
commit: out.commitment(),
|
commit: out.commitment(),
|
||||||
secp: secp.clone(),
|
|
||||||
},
|
},
|
||||||
Some(out.switch_commit_hash()),
|
Some(out.switch_commit_hash()),
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use blake2::blake2b::blake2b;
|
use blake2::blake2b::blake2b;
|
||||||
use util::secp::{self, Message, Secp256k1, Signature};
|
use util::secp::{self, Message, Secp256k1, Signature};
|
||||||
|
use util::static_secp_instance;
|
||||||
use util::secp::pedersen::{Commitment, RangeProof};
|
use util::secp::pedersen::{Commitment, RangeProof};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
|
@ -322,6 +323,7 @@ impl Transaction {
|
||||||
Ok(rsum)
|
Ok(rsum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builds a transaction kernel
|
||||||
pub fn build_kernel(&self, excess: Commitment) -> TxKernel {
|
pub fn build_kernel(&self, excess: Commitment) -> TxKernel {
|
||||||
TxKernel {
|
TxKernel {
|
||||||
features: DEFAULT_KERNEL,
|
features: DEFAULT_KERNEL,
|
||||||
|
@ -533,8 +535,6 @@ impl Output {
|
||||||
pub struct SumCommit {
|
pub struct SumCommit {
|
||||||
/// Output commitment
|
/// Output commitment
|
||||||
pub commit: Commitment,
|
pub commit: Commitment,
|
||||||
/// Secp256k1 used to sum
|
|
||||||
pub secp: Secp256k1,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outputs get summed through their commitments.
|
/// Outputs get summed through their commitments.
|
||||||
|
@ -544,7 +544,6 @@ impl Summable for SumCommit {
|
||||||
fn sum(&self) -> SumCommit {
|
fn sum(&self) -> SumCommit {
|
||||||
SumCommit {
|
SumCommit {
|
||||||
commit: self.commit.clone(),
|
commit: self.commit.clone(),
|
||||||
secp: self.secp.clone(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,12 +561,10 @@ impl Writeable for SumCommit {
|
||||||
|
|
||||||
impl Readable for SumCommit {
|
impl Readable for SumCommit {
|
||||||
fn read(reader: &mut Reader) -> Result<SumCommit, ser::Error> {
|
fn read(reader: &mut Reader) -> Result<SumCommit, ser::Error> {
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
|
||||||
let commit = Commitment::read(reader)?;
|
let commit = Commitment::read(reader)?;
|
||||||
|
|
||||||
Ok(SumCommit {
|
Ok(SumCommit {
|
||||||
commit: commit,
|
commit: commit,
|
||||||
secp: secp,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,7 +573,8 @@ impl ops::Add for SumCommit {
|
||||||
type Output = SumCommit;
|
type Output = SumCommit;
|
||||||
|
|
||||||
fn add(self, other: SumCommit) -> 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![])
|
.commit_sum(vec![self.commit.clone(), other.commit.clone()], vec![])
|
||||||
{
|
{
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
|
@ -584,7 +582,6 @@ impl ops::Add for SumCommit {
|
||||||
};
|
};
|
||||||
SumCommit {
|
SumCommit {
|
||||||
commit: sum,
|
commit: sum,
|
||||||
secp: self.secp,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ authors = ["Antioch Peverell"]
|
||||||
byteorder = "~1"
|
byteorder = "~1"
|
||||||
blake2-rfc = "~0.2.17"
|
blake2-rfc = "~0.2.17"
|
||||||
rand = "~0.3"
|
rand = "~0.3"
|
||||||
|
slog = { version = "^2.0.12", features = ["max_level_trace", "release_max_level_trace"] }
|
||||||
serde = "~1.0.8"
|
serde = "~1.0.8"
|
||||||
serde_derive = "~1.0.8"
|
serde_derive = "~1.0.8"
|
||||||
serde_json = "~1.0.3"
|
serde_json = "~1.0.3"
|
||||||
|
|
|
@ -134,7 +134,7 @@ impl Identifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_hex(hex: &str) -> Result<Identifier, Error> {
|
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))
|
Ok(Identifier::from_bytes(&bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ use util::secp;
|
||||||
use util::secp::{Message, Secp256k1, Signature};
|
use util::secp::{Message, Secp256k1, Signature};
|
||||||
use util::secp::key::SecretKey;
|
use util::secp::key::SecretKey;
|
||||||
use util::secp::pedersen::{Commitment, ProofMessage, ProofInfo, RangeProof};
|
use util::secp::pedersen::{Commitment, ProofMessage, ProofInfo, RangeProof};
|
||||||
|
use util::logger::LOGGER;
|
||||||
use blake2;
|
use blake2;
|
||||||
use blind::{BlindSum, BlindingFactor};
|
use blind::{BlindSum, BlindingFactor};
|
||||||
use extkey::{self, Identifier};
|
use extkey::{self, Identifier};
|
||||||
|
@ -93,11 +94,18 @@ impl Keychain {
|
||||||
Ok(key_id)
|
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) {
|
if let Some(key) = self.key_overrides.get(key_id) {
|
||||||
return Ok(*key);
|
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 {
|
for i in 1..10000 {
|
||||||
let extkey = self.extkey.derive(&self.secp, i)?;
|
let extkey = self.extkey.derive(&self.secp, i)?;
|
||||||
if extkey.identifier(&self.secp)? == *key_id {
|
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> {
|
pub fn commit(&self, amount: u64, key_id: &Identifier) -> Result<Commitment, Error> {
|
||||||
let skey = self.derived_key(key_id)?;
|
let skey = self.derived_key(key_id)?;
|
||||||
let commit = self.secp.commit(amount, skey)?;
|
let commit = self.secp.commit(amount, skey)?;
|
||||||
Ok(commit)
|
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> {
|
pub fn switch_commit(&self, key_id: &Identifier) -> Result<Commitment, Error> {
|
||||||
let skey = self.derived_key(key_id)?;
|
let skey = self.derived_key(key_id)?;
|
||||||
let commit = self.secp.switch_commit(skey)?;
|
let commit = self.secp.switch_commit(skey)?;
|
||||||
|
|
|
@ -22,6 +22,8 @@ extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate slog;
|
||||||
|
|
||||||
mod blind;
|
mod blind;
|
||||||
mod extkey;
|
mod extkey;
|
||||||
|
|
|
@ -10,6 +10,7 @@ slog = { version = "^2.0.12", features = ["max_level_trace", "release_max_level_
|
||||||
slog-term = "^2.2.0"
|
slog-term = "^2.2.0"
|
||||||
slog-async = "^2.1.0"
|
slog-async = "^2.1.0"
|
||||||
lazy_static = "~0.2.8"
|
lazy_static = "~0.2.8"
|
||||||
|
rand = "0.3"
|
||||||
serde = "~1.0.8"
|
serde = "~1.0.8"
|
||||||
serde_derive = "~1.0.8"
|
serde_derive = "~1.0.8"
|
||||||
secp256k1zkp = { git = "https://github.com/mimblewimble/rust-secp256k1-zkp", tag="grin_integration_1" }
|
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_async;
|
||||||
extern crate slog_term;
|
extern crate slog_term;
|
||||||
|
|
||||||
|
extern crate rand;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
|
@ -41,6 +43,10 @@ pub use secp_ as secp;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub use logger::{init_logger, init_test_logger, 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 mod types;
|
||||||
pub use types::LoggingConfig;
|
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)
|
.filter(|out| out.status != OutputStatus::Spent)
|
||||||
{
|
{
|
||||||
let key_id = keychain.derive_key_id(out.n_child).unwrap();
|
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);
|
commits.push(commit);
|
||||||
wallet_outputs.insert(commit, out.key_id.clone());
|
wallet_outputs.insert(commit, out.key_id.clone());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue