Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support new Bulletproof rewind scheme #122

Merged
merged 8 commits into from
Jun 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions impls/src/backends/lmdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use uuid::Uuid;

use crate::blake2::blake2b::Blake2b;

use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain, SwitchCommitmentType};
use crate::store::{self, option_to_not_found, to_key, to_key_u64};

use crate::core::core::Transaction;
Expand Down Expand Up @@ -68,7 +68,7 @@ fn private_ctx_xor_keys<K>(
where
K: Keychain,
{
let root_key = keychain.derive_key(0, &K::root_key_id())?;
let root_key = keychain.derive_key(0, &K::root_key_id(), &SwitchCommitmentType::Regular)?;

// derive XOR values for storing secret values in DB
// h(root_key|slate_id|"blind")
Expand Down Expand Up @@ -203,7 +203,10 @@ where
Ok(None)
} else {
Ok(Some(util::to_hex(
self.keychain().commit(amount, &id)?.0.to_vec(),
self.keychain()
.commit(amount, &id, &SwitchCommitmentType::Regular)?
.0
.to_vec(), // TODO: proper support for different switch commitment schemes
)))
}
}
Expand Down
35 changes: 22 additions & 13 deletions libwallet/src/internal/restore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
// limitations under the License.
//! Functions to restore a wallet's outputs from just the master seed

use crate::grin_core::consensus::valid_header_version;
use crate::grin_core::core::HeaderVersion;
use crate::grin_core::global;
use crate::grin_core::libtx::proof;
use crate::grin_keychain::{ExtKeychain, Identifier, Keychain};
use crate::grin_util::secp::{key::SecretKey, pedersen};
use crate::grin_keychain::{ExtKeychain, Identifier, Keychain, SwitchCommitmentType};
use crate::grin_util::secp::pedersen;
use crate::internal::{keys, updater};
use crate::types::*;
use crate::{Error, OutputCommitMapping};
Expand All @@ -41,8 +43,6 @@ struct OutputResult {
pub lock_height: u64,
///
pub is_coinbase: bool,
///
pub blinding: SecretKey,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -73,40 +73,49 @@ where
outputs.len(),
);

let keychain = wallet.keychain();
let legacy_builder = proof::LegacyProofBuilder::new(keychain);
let builder = proof::ProofBuilder::new(keychain);
let legacy_version = HeaderVersion(1);

for output in outputs.iter() {
let (commit, proof, is_coinbase, height, mmr_index) = output;
// attempt to unwind message from the RP and get a value
// will fail if it's not ours
let info = proof::rewind(wallet.keychain(), *commit, None, *proof)?;
let info = if valid_header_version(*height, legacy_version) {
proof::rewind(keychain.secp(), &legacy_builder, *commit, None, *proof)
} else {
proof::rewind(keychain.secp(), &builder, *commit, None, *proof)
}?;

if !info.success {
if info.is_none() {
continue;
}
let (amount, key_id, switch) = info.unwrap();

let lock_height = if *is_coinbase {
*height + global::coinbase_maturity()
} else {
*height
};

// TODO: Output paths are always going to be length 3 for now, but easy enough to grind
// through to find the right path if required later
let key_id = Identifier::from_serialized_path(3u8, &info.message.as_bytes());

info!(
"Output found: {:?}, amount: {:?}, key_id: {:?}, mmr_index: {},",
commit, info.value, key_id, mmr_index,
commit, amount, key_id, mmr_index,
);

if switch != SwitchCommitmentType::Regular {
warn!("Unexpected switch commitment type {:?}", switch);
}

wallet_outputs.push(OutputResult {
commit: *commit,
key_id: key_id.clone(),
n_child: key_id.to_path().last_path_index(),
value: info.value,
value: amount,
height: *height,
lock_height: lock_height,
is_coinbase: *is_coinbase,
blinding: info.blinding,
mmr_index: *mmr_index,
});
}
Expand Down
82 changes: 65 additions & 17 deletions libwallet/src/internal/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,45 @@

use crate::error::{Error, ErrorKind};
use crate::grin_core::core::amount_to_hr_string;
use crate::grin_core::libtx::{build, tx_fee};
use crate::grin_core::global;
use crate::grin_core::libtx::{
build,
proof::{LegacyProofBuilder, ProofBuild, ProofBuilder},
tx_fee,
};
use crate::grin_keychain::{Identifier, Keychain};
use crate::internal::keys;
use crate::slate::Slate;
use crate::types::*;
use std::collections::HashMap;

macro_rules! add_transaction_elements {
($a:expr, $b:ident) => {{
let slate = $a.1;
let (elems, inputs, change_amounts_derivations, fee) = select_send_tx(
$a.0,
slate.amount,
slate.height,
$a.2,
slate.lock_height,
$a.3,
$a.4,
$a.5,
$a.6,
)?;
let keychain = $a.0.keychain();
let blinding = slate.add_transaction_elements(keychain, &$b::new(keychain), elems)?;
(
$a.0,
slate,
inputs,
change_amounts_derivations,
fee,
blinding,
)
}};
}

/// Initialize a transaction on the sender side, returns a corresponding
/// libwallet transaction slate with the appropriate inputs selected,
/// and saves the private wallet identifiers of our selected outputs
Expand All @@ -43,26 +75,29 @@ where
C: NodeClient,
K: Keychain,
{
let (elems, inputs, change_amounts_derivations, fee) = select_send_tx(
let chain_type = global::CHAIN_TYPE.read().clone();
let args = (
wallet,
slate.amount,
slate.height,
slate,
minimum_confirmations,
slate.lock_height,
max_outputs,
change_outputs,
selection_strategy_is_use_all,
&parent_key_id,
)?;
);
let (wallet, mut slate, inputs, change_amounts_derivations, fee, blinding) =
if chain_type == global::ChainTypes::AutomatedTesting {
add_transaction_elements!(args, LegacyProofBuilder)
} else {
add_transaction_elements!(args, ProofBuilder)
};

let keychain = wallet.keychain();
slate.fee = fee;

let keychain = wallet.keychain().clone();
let blinding = slate.add_transaction_elements(&keychain, elems)?;

// Create our own private context
let mut context = Context::new(
wallet.keychain().secp(),
keychain.secp(),
blinding.secret_key(&keychain.secp()).unwrap(),
&parent_key_id,
use_test_nonce,
Expand Down Expand Up @@ -182,15 +217,26 @@ where
{
// Create a potential output for this transaction
let key_id = keys::next_available_key(wallet).unwrap();

let keychain = wallet.keychain().clone();
let key_id_inner = key_id.clone();
let amount = slate.amount;
let height = slate.height;

let slate_id = slate.id.clone();
let blinding =
slate.add_transaction_elements(&keychain, vec![build::output(amount, key_id.clone())])?;
let chain_type = global::CHAIN_TYPE.read().clone();
let blinding = if chain_type == global::ChainTypes::AutomatedTesting {
slate.add_transaction_elements(
&keychain,
&LegacyProofBuilder::new(&keychain),
vec![build::output(amount, key_id.clone())],
)
} else {
slate.add_transaction_elements(
&keychain,
&ProofBuilder::new(&keychain),
vec![build::output(amount, key_id.clone())],
)
}?;

// Add blinding sum to our context
let mut context = Context::new(
Expand Down Expand Up @@ -235,7 +281,7 @@ where
/// Builds a transaction to send to someone from the HD seed associated with the
/// wallet and the amount to send. Handles reading through the wallet data file,
/// selecting outputs to spend and building the change.
pub fn select_send_tx<T: ?Sized, C, K>(
pub fn select_send_tx<T: ?Sized, C, K, B>(
wallet: &mut T,
amount: u64,
current_height: u64,
Expand All @@ -247,7 +293,7 @@ pub fn select_send_tx<T: ?Sized, C, K>(
parent_key_id: &Identifier,
) -> Result<
(
Vec<Box<build::Append<K>>>,
Vec<Box<build::Append<K, B>>>,
Vec<OutputData>,
Vec<(u64, Identifier, Option<u64>)>, // change amounts and derivations
u64, // fee
Expand All @@ -258,6 +304,7 @@ where
T: WalletBackend<C, K>,
C: NodeClient,
K: Keychain,
B: ProofBuild,
{
let (coins, _total, amount, fee) = select_coins_and_fee(
wallet,
Expand Down Expand Up @@ -387,15 +434,15 @@ where
}

/// Selects inputs and change for a transaction
pub fn inputs_and_change<T: ?Sized, C, K>(
pub fn inputs_and_change<T: ?Sized, C, K, B>(
coins: &Vec<OutputData>,
wallet: &mut T,
amount: u64,
fee: u64,
num_change_outputs: usize,
) -> Result<
(
Vec<Box<build::Append<K>>>,
Vec<Box<build::Append<K, B>>>,
Vec<(u64, Identifier, Option<u64>)>,
),
Error,
Expand All @@ -404,6 +451,7 @@ where
T: WalletBackend<C, K>,
C: NodeClient,
K: Keychain,
B: ProofBuild,
{
let mut parts = vec![];

Expand Down
Loading