mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 11:31:08 +03:00
Improve file-based tx send to not use private file (#1421)
Instead of generating a private file on send that needs to be provided again in finalize, the private context information is saved in the wallet db. Also move internal Context to bona fide libwallet type
This commit is contained in:
parent
a58558b38e
commit
4048a3011a
14 changed files with 190 additions and 159 deletions
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
/// Grin client commands processing
|
||||
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use clap::ArgMatches;
|
||||
|
|
|
@ -247,12 +247,7 @@ pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
|
|||
let tx_file = send_args
|
||||
.value_of("input")
|
||||
.expect("Receiver's transaction file required");
|
||||
let priv_file = send_args
|
||||
.value_of("private")
|
||||
.expect("Private transaction file required");
|
||||
let slate = api
|
||||
.file_finalize_tx(priv_file, tx_file)
|
||||
.expect("Finalize failed");
|
||||
let slate = api.file_finalize_tx(tx_file).expect("Finalize failed");
|
||||
|
||||
let result = api.post_tx(&slate, fluff);
|
||||
match result {
|
||||
|
|
|
@ -208,7 +208,7 @@ fn main() {
|
|||
.default_value("1")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("dest")
|
||||
.help("Send the transaction to the provided server")
|
||||
.help("Send the transaction to the provided server (start with http://) or save as file.")
|
||||
.short("d")
|
||||
.long("dest")
|
||||
.takes_value(true))
|
||||
|
@ -232,11 +232,6 @@ fn main() {
|
|||
.short("i")
|
||||
.long("input")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("private")
|
||||
.help("Private transaction file previously generated by send.")
|
||||
.short("p")
|
||||
.long("private")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("fluff")
|
||||
.help("Fluff the transaction (ignore Dandelion relay protocol)")
|
||||
.short("f")
|
||||
|
|
|
@ -80,15 +80,14 @@ pub struct TUIPeerView;
|
|||
|
||||
impl TUIStatusListener for TUIPeerView {
|
||||
fn create() -> Box<View> {
|
||||
let table_view =
|
||||
TableView::<PeerStats, PeerColumn>::new()
|
||||
.column(PeerColumn::Address, "Address", |c| c.width_percent(20))
|
||||
.column(PeerColumn::State, "State", |c| c.width_percent(20))
|
||||
.column(PeerColumn::Direction, "Direction", |c| c.width_percent(20))
|
||||
.column(PeerColumn::TotalDifficulty, "Total Difficulty", |c| {
|
||||
c.width_percent(20)
|
||||
})
|
||||
.column(PeerColumn::Version, "Version", |c| c.width_percent(20));
|
||||
let table_view = TableView::<PeerStats, PeerColumn>::new()
|
||||
.column(PeerColumn::Address, "Address", |c| c.width_percent(20))
|
||||
.column(PeerColumn::State, "State", |c| c.width_percent(20))
|
||||
.column(PeerColumn::Direction, "Direction", |c| c.width_percent(20))
|
||||
.column(PeerColumn::TotalDifficulty, "Total Difficulty", |c| {
|
||||
c.width_percent(20)
|
||||
})
|
||||
.column(PeerColumn::Version, "Version", |c| c.width_percent(20));
|
||||
let peer_status_view = BoxView::with_full_screen(
|
||||
LinearLayout::new(Orientation::Vertical)
|
||||
.child(
|
||||
|
|
|
@ -664,7 +664,8 @@ impl<T: TableViewItem<H>, H: Eq + Hash + Copy + Clone + 'static> TableView<T, H>
|
|||
fn column_select(&mut self) {
|
||||
let next = self.active_column();
|
||||
let column = self.columns[next].column;
|
||||
let current = self.columns
|
||||
let current = self
|
||||
.columns
|
||||
.iter()
|
||||
.position(|c| c.order != Ordering::Equal)
|
||||
.unwrap_or(0);
|
||||
|
@ -736,10 +737,10 @@ impl<T: TableViewItem<H> + 'static, H: Eq + Hash + Copy + Clone + 'static> View
|
|||
let column_count = self.columns.len();
|
||||
|
||||
// Split up all columns into sized / unsized groups
|
||||
let (mut sized, mut usized): (Vec<&mut TableColumn<H>>, Vec<&mut TableColumn<H>>) =
|
||||
self.columns
|
||||
.iter_mut()
|
||||
.partition(|c| c.requested_width.is_some());
|
||||
let (mut sized, mut usized): (Vec<&mut TableColumn<H>>, Vec<&mut TableColumn<H>>) = self
|
||||
.columns
|
||||
.iter_mut()
|
||||
.partition(|c| c.requested_width.is_some());
|
||||
|
||||
// Subtract one for the separators between our columns (that's column_count - 1)
|
||||
let mut available_width = size.x.saturating_sub(column_count.saturating_sub(1) * 3);
|
||||
|
|
|
@ -35,7 +35,7 @@ use error::{Error, ErrorKind};
|
|||
use libwallet;
|
||||
|
||||
use libwallet::types::{
|
||||
OutputData, TxLogEntry, WalletBackend, WalletClient, WalletDetails, WalletOutputBatch,
|
||||
Context, OutputData, TxLogEntry, WalletBackend, WalletClient, WalletDetails, WalletOutputBatch,
|
||||
};
|
||||
|
||||
use types::{WalletConfig, WalletSeed};
|
||||
|
@ -121,6 +121,18 @@ where
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn save_private_context(
|
||||
&mut self,
|
||||
_slate_id: &[u8],
|
||||
_ctx: &Context,
|
||||
) -> Result<(), libwallet::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn delete_private_context(&mut self, _slate_id: &[u8]) -> Result<(), libwallet::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn commit(&self) -> Result<(), libwallet::Error> {
|
||||
let mut data_file = File::create(self.data_file_path.clone())
|
||||
.context(libwallet::ErrorKind::CallbackImpl("Could not create"))?;
|
||||
|
@ -239,6 +251,10 @@ where
|
|||
Box::new(self.tx_log.iter().cloned())
|
||||
}
|
||||
|
||||
fn get_private_context(&mut self, _slate_id: &[u8]) -> Result<Context, libwallet::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get(&self, id: &Identifier) -> Result<OutputData, libwallet::Error> {
|
||||
self.outputs
|
||||
.get(&id.to_hex())
|
||||
|
|
|
@ -28,7 +28,7 @@ use core::core::hash::Hashed;
|
|||
use core::ser;
|
||||
use keychain::Keychain;
|
||||
use libtx::slate::Slate;
|
||||
use libwallet::internal::{selection, sigcontext, tx, updater};
|
||||
use libwallet::internal::{selection, tx, updater};
|
||||
use libwallet::types::{
|
||||
BlockFees, CbData, OutputData, TxLogEntry, TxWrapper, WalletBackend, WalletClient, WalletInfo,
|
||||
};
|
||||
|
@ -207,9 +207,12 @@ where
|
|||
let mut pub_tx = File::create(dest)?;
|
||||
pub_tx.write_all(json::to_string(&slate).unwrap().as_bytes())?;
|
||||
pub_tx.sync_all()?;
|
||||
let mut priv_tx = File::create(dest.to_owned() + ".private")?;
|
||||
priv_tx.write_all(json::to_string(&context).unwrap().as_bytes())?;
|
||||
priv_tx.sync_all()?;
|
||||
|
||||
{
|
||||
let mut batch = w.batch()?;
|
||||
batch.save_private_context(slate.id.as_bytes(), &context)?;
|
||||
batch.commit()?;
|
||||
}
|
||||
|
||||
// lock our inputs
|
||||
lock_fn(&mut **w)?;
|
||||
|
@ -259,23 +262,24 @@ where
|
|||
/// propagation.
|
||||
pub fn file_finalize_tx(
|
||||
&mut self,
|
||||
private_tx_file: &str,
|
||||
receiver_file: &str,
|
||||
) -> Result<Slate, Error> {
|
||||
|
||||
let mut pub_tx_f = File::open(receiver_file)?;
|
||||
let mut content = String::new();
|
||||
pub_tx_f.read_to_string(&mut content)?;
|
||||
let mut slate: Slate = json::from_str(&content).map_err(|_| ErrorKind::Format)?;
|
||||
|
||||
let mut priv_tx_f = File::open(private_tx_file)?;
|
||||
let mut content = String::new();
|
||||
priv_tx_f.read_to_string(&mut content)?;
|
||||
let context: sigcontext::Context = json::from_str(&content).map_err(|_| ErrorKind::Format)?;
|
||||
|
||||
let mut w = self.wallet.lock().unwrap();
|
||||
w.open_with_credentials()?;
|
||||
|
||||
let context = w.get_private_context(slate.id.as_bytes())?;
|
||||
tx::complete_tx(&mut **w, &mut slate, &context)?;
|
||||
{
|
||||
let mut batch = w.batch()?;
|
||||
batch.delete_private_context(slate.id.as_bytes())?;
|
||||
batch.commit()?;
|
||||
}
|
||||
|
||||
w.close()?;
|
||||
Ok(slate)
|
||||
|
|
|
@ -24,6 +24,5 @@
|
|||
pub mod keys;
|
||||
pub mod restore;
|
||||
pub mod selection;
|
||||
pub mod sigcontext;
|
||||
pub mod tx;
|
||||
pub mod updater;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
use keychain::{Identifier, Keychain};
|
||||
use libtx::{build, slate::Slate, tx_fee};
|
||||
use libwallet::error::{Error, ErrorKind};
|
||||
use libwallet::internal::{keys, sigcontext};
|
||||
use libwallet::internal::keys;
|
||||
use libwallet::types::*;
|
||||
|
||||
use util::LOGGER;
|
||||
|
@ -37,14 +37,7 @@ pub fn build_send_tx_slate<T: ?Sized, C, K>(
|
|||
max_outputs: usize,
|
||||
change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<
|
||||
(
|
||||
Slate,
|
||||
sigcontext::Context,
|
||||
impl FnOnce(&mut T) -> Result<(), Error>,
|
||||
),
|
||||
Error,
|
||||
>
|
||||
) -> Result<(Slate, Context, impl FnOnce(&mut T) -> Result<(), Error>), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
|
@ -74,7 +67,7 @@ where
|
|||
let blinding = slate.add_transaction_elements(&keychain, elems)?;
|
||||
|
||||
// Create our own private context
|
||||
let mut context = sigcontext::Context::new(
|
||||
let mut context = Context::new(
|
||||
wallet.keychain().secp(),
|
||||
blinding.secret_key(&keychain.secp()).unwrap(),
|
||||
);
|
||||
|
@ -149,7 +142,7 @@ pub fn build_recipient_output_with_slate<T: ?Sized, C, K>(
|
|||
) -> Result<
|
||||
(
|
||||
Identifier,
|
||||
sigcontext::Context,
|
||||
Context,
|
||||
impl FnOnce(&mut T) -> Result<(), Error>,
|
||||
),
|
||||
Error,
|
||||
|
@ -173,7 +166,7 @@ where
|
|||
slate.add_transaction_elements(&keychain, vec![build::output(amount, key_id.clone())])?;
|
||||
|
||||
// Add blinding sum to our context
|
||||
let mut context = sigcontext::Context::new(
|
||||
let mut context = Context::new(
|
||||
keychain.secp(),
|
||||
blinding
|
||||
.secret_key(wallet.keychain().clone().secp())
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
// 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.
|
||||
//! Signature context holder helper (may be removed or replaced eventually)
|
||||
use keychain::Identifier;
|
||||
use libtx::aggsig;
|
||||
use util::secp::key::{PublicKey, SecretKey};
|
||||
use util::secp::{self, Secp256k1};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
/// Holds the context for a single aggsig transaction
|
||||
pub struct Context {
|
||||
/// Secret key (of which public is shared)
|
||||
pub sec_key: SecretKey,
|
||||
/// Secret nonce (of which public is shared)
|
||||
/// (basically a SecretKey)
|
||||
pub sec_nonce: SecretKey,
|
||||
/// store my outputs between invocations
|
||||
pub output_ids: Vec<Identifier>,
|
||||
/// store my inputs
|
||||
pub input_ids: Vec<Identifier>,
|
||||
/// store the calculated fee
|
||||
pub fee: u64,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Create a new context with defaults
|
||||
pub fn new(secp: &secp::Secp256k1, sec_key: SecretKey) -> Context {
|
||||
Context {
|
||||
sec_key: sec_key,
|
||||
sec_nonce: aggsig::create_secnonce(secp).unwrap(),
|
||||
input_ids: vec![],
|
||||
output_ids: vec![],
|
||||
fee: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Tracks an output contributing to my excess value (if it needs to
|
||||
/// be kept between invocations
|
||||
pub fn add_output(&mut self, output_id: &Identifier) {
|
||||
self.output_ids.push(output_id.clone());
|
||||
}
|
||||
|
||||
/// Returns all stored outputs
|
||||
pub fn get_outputs(&self) -> Vec<Identifier> {
|
||||
self.output_ids.clone()
|
||||
}
|
||||
|
||||
/// Tracks IDs of my inputs into the transaction
|
||||
/// be kept between invocations
|
||||
pub fn add_input(&mut self, input_id: &Identifier) {
|
||||
self.input_ids.push(input_id.clone());
|
||||
}
|
||||
|
||||
/// Returns all stored input identifiers
|
||||
pub fn get_inputs(&self) -> Vec<Identifier> {
|
||||
self.input_ids.clone()
|
||||
}
|
||||
|
||||
/// Returns private key, private nonce
|
||||
pub fn get_private_keys(&self) -> (SecretKey, SecretKey) {
|
||||
(self.sec_key.clone(), self.sec_nonce.clone())
|
||||
}
|
||||
|
||||
/// Returns public key, public nonce
|
||||
pub fn get_public_keys(&self, secp: &Secp256k1) -> (PublicKey, PublicKey) {
|
||||
(
|
||||
PublicKey::from_secret_key(secp, &self.sec_key).unwrap(),
|
||||
PublicKey::from_secret_key(secp, &self.sec_nonce).unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@ use core::core::Transaction;
|
|||
use keychain::{Identifier, Keychain};
|
||||
use libtx::slate::Slate;
|
||||
use libtx::{build, tx_fee};
|
||||
use libwallet::internal::{selection, sigcontext, updater};
|
||||
use libwallet::types::{TxLogEntryType, WalletBackend, WalletClient};
|
||||
use libwallet::internal::{selection, updater};
|
||||
use libwallet::types::{Context, TxLogEntryType, WalletBackend, WalletClient};
|
||||
use libwallet::{Error, ErrorKind};
|
||||
use util::LOGGER;
|
||||
|
||||
|
@ -61,14 +61,7 @@ pub fn create_send_tx<T: ?Sized, C, K>(
|
|||
max_outputs: usize,
|
||||
num_change_outputs: usize,
|
||||
selection_strategy_is_use_all: bool,
|
||||
) -> Result<
|
||||
(
|
||||
Slate,
|
||||
sigcontext::Context,
|
||||
impl FnOnce(&mut T) -> Result<(), Error>,
|
||||
),
|
||||
Error,
|
||||
>
|
||||
) -> Result<(Slate, Context, impl FnOnce(&mut T) -> Result<(), Error>), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
C: WalletClient,
|
||||
|
@ -117,7 +110,7 @@ where
|
|||
pub fn complete_tx<T: ?Sized, C, K>(
|
||||
wallet: &mut T,
|
||||
slate: &mut Slate,
|
||||
context: &sigcontext::Context,
|
||||
context: &Context,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, K>,
|
||||
|
|
|
@ -30,10 +30,12 @@ use core::ser;
|
|||
|
||||
use keychain::{Identifier, Keychain};
|
||||
|
||||
use libtx::aggsig;
|
||||
use libtx::slate::Slate;
|
||||
use libwallet::error::{Error, ErrorKind};
|
||||
|
||||
use util::secp::pedersen;
|
||||
use util::secp::key::{PublicKey, SecretKey};
|
||||
use util::secp::{self, pedersen, Secp256k1};
|
||||
|
||||
/// Combined trait to allow dynamic wallet dispatch
|
||||
pub trait WalletInst<C, K>: WalletBackend<C, K> + Send + Sync + 'static
|
||||
|
@ -82,6 +84,9 @@ where
|
|||
/// Get an (Optional) tx log entry by uuid
|
||||
fn get_tx_log_entry(&self, uuid: &Uuid) -> Result<Option<TxLogEntry>, Error>;
|
||||
|
||||
/// Retrieves the private context associated with a given slate id
|
||||
fn get_private_context(&mut self, slate_id: &[u8]) -> Result<Context, Error>;
|
||||
|
||||
/// Iterate over all output data stored by the backend
|
||||
fn tx_log_iter<'a>(&'a self) -> Box<Iterator<Item = TxLogEntry> + 'a>;
|
||||
|
||||
|
@ -137,6 +142,12 @@ where
|
|||
/// Save an output as locked in the backend
|
||||
fn lock_output(&mut self, out: &mut OutputData) -> Result<(), Error>;
|
||||
|
||||
/// Saves the private context associated with a slate id
|
||||
fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error>;
|
||||
|
||||
/// Delete the private context associated with the slate id
|
||||
fn delete_private_context(&mut self, slate_id: &[u8]) -> Result<(), Error>;
|
||||
|
||||
/// Write the wallet data to backend file
|
||||
fn commit(&self) -> Result<(), Error>;
|
||||
}
|
||||
|
@ -315,6 +326,85 @@ impl fmt::Display for OutputStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
/// Holds the context for a single aggsig transaction
|
||||
pub struct Context {
|
||||
/// Secret key (of which public is shared)
|
||||
pub sec_key: SecretKey,
|
||||
/// Secret nonce (of which public is shared)
|
||||
/// (basically a SecretKey)
|
||||
pub sec_nonce: SecretKey,
|
||||
/// store my outputs between invocations
|
||||
pub output_ids: Vec<Identifier>,
|
||||
/// store my inputs
|
||||
pub input_ids: Vec<Identifier>,
|
||||
/// store the calculated fee
|
||||
pub fee: u64,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Create a new context with defaults
|
||||
pub fn new(secp: &secp::Secp256k1, sec_key: SecretKey) -> Context {
|
||||
Context {
|
||||
sec_key: sec_key,
|
||||
sec_nonce: aggsig::create_secnonce(secp).unwrap(),
|
||||
input_ids: vec![],
|
||||
output_ids: vec![],
|
||||
fee: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Tracks an output contributing to my excess value (if it needs to
|
||||
/// be kept between invocations
|
||||
pub fn add_output(&mut self, output_id: &Identifier) {
|
||||
self.output_ids.push(output_id.clone());
|
||||
}
|
||||
|
||||
/// Returns all stored outputs
|
||||
pub fn get_outputs(&self) -> Vec<Identifier> {
|
||||
self.output_ids.clone()
|
||||
}
|
||||
|
||||
/// Tracks IDs of my inputs into the transaction
|
||||
/// be kept between invocations
|
||||
pub fn add_input(&mut self, input_id: &Identifier) {
|
||||
self.input_ids.push(input_id.clone());
|
||||
}
|
||||
|
||||
/// Returns all stored input identifiers
|
||||
pub fn get_inputs(&self) -> Vec<Identifier> {
|
||||
self.input_ids.clone()
|
||||
}
|
||||
|
||||
/// Returns private key, private nonce
|
||||
pub fn get_private_keys(&self) -> (SecretKey, SecretKey) {
|
||||
(self.sec_key.clone(), self.sec_nonce.clone())
|
||||
}
|
||||
|
||||
/// Returns public key, public nonce
|
||||
pub fn get_public_keys(&self, secp: &Secp256k1) -> (PublicKey, PublicKey) {
|
||||
(
|
||||
PublicKey::from_secret_key(secp, &self.sec_key).unwrap(),
|
||||
PublicKey::from_secret_key(secp, &self.sec_nonce).unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Writeable for Context {
|
||||
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||
writer.write_bytes(&serde_json::to_vec(self).map_err(|_| ser::Error::CorruptedData)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Readable for Context {
|
||||
fn read(reader: &mut ser::Reader) -> Result<Context, ser::Error> {
|
||||
let data = reader.read_vec()?;
|
||||
serde_json::from_slice(&data[..]).map_err(|_| ser::Error::CorruptedData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Block Identifier
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub struct BlockIdentifier(pub Hash);
|
||||
|
|
|
@ -33,6 +33,7 @@ const COMMITMENT_PREFIX: u8 = 'C' as u8;
|
|||
const OUTPUT_PREFIX: u8 = 'o' as u8;
|
||||
const DERIV_PREFIX: u8 = 'd' as u8;
|
||||
const CONFIRMED_HEIGHT_PREFIX: u8 = 'c' as u8;
|
||||
const PRIVATE_TX_CONTEXT_PREFIX: u8 = 'p' as u8;
|
||||
const TX_LOG_ENTRY_PREFIX: u8 = 't' as u8;
|
||||
const TX_LOG_ID_PREFIX: u8 = 'i' as u8;
|
||||
|
||||
|
@ -161,6 +162,14 @@ where
|
|||
Box::new(self.db.iter(&[TX_LOG_ENTRY_PREFIX]).unwrap())
|
||||
}
|
||||
|
||||
fn get_private_context(&mut self, slate_id: &[u8]) -> Result<Context, Error> {
|
||||
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
||||
option_to_not_found(
|
||||
self.db.get_ser(&ctx_key),
|
||||
&format!("Slate id: {:x?}", slate_id.to_vec()),
|
||||
).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn batch<'a>(&'a mut self) -> Result<Box<WalletOutputBatch<K> + 'a>, Error> {
|
||||
Ok(Box::new(Batch {
|
||||
_store: self,
|
||||
|
@ -336,6 +345,22 @@ where
|
|||
self.save(out.clone())
|
||||
}
|
||||
|
||||
fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> {
|
||||
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
||||
self.db.borrow().as_ref().unwrap().put_ser(&ctx_key, &ctx)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete_private_context(&mut self, slate_id: &[u8]) -> Result<(), Error> {
|
||||
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
||||
self.db
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.delete(&ctx_key)
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn commit(&self) -> Result<(), Error> {
|
||||
let db = self.db.replace(None);
|
||||
db.unwrap().commit()?;
|
||||
|
|
|
@ -24,7 +24,7 @@ use keychain::{BlindSum, BlindingFactor, ExtKeychain, Keychain};
|
|||
use util::secp::key::{PublicKey, SecretKey};
|
||||
use util::{kernel_sig_msg, secp};
|
||||
use wallet::libtx::{aggsig, proof};
|
||||
use wallet::libwallet::internal::sigcontext;
|
||||
use wallet::libwallet::types::Context;
|
||||
|
||||
use rand::thread_rng;
|
||||
|
||||
|
@ -46,9 +46,11 @@ fn aggsig_sender_receiver_interaction() {
|
|||
|
||||
let keychain = ExtKeychain::from_random_seed().unwrap();
|
||||
let blinding_factor = keychain
|
||||
.blind_sum(&BlindSum::new()
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(skey1))
|
||||
.add_blinding_factor(BlindingFactor::from_secret_key(skey2)))
|
||||
.blind_sum(
|
||||
&BlindSum::new()
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(skey1))
|
||||
.add_blinding_factor(BlindingFactor::from_secret_key(skey2)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
keychain
|
||||
|
@ -76,7 +78,7 @@ fn aggsig_sender_receiver_interaction() {
|
|||
|
||||
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
||||
|
||||
s_cx = sigcontext::Context::new(&keychain.secp(), blind);
|
||||
s_cx = Context::new(&keychain.secp(), blind);
|
||||
s_cx.get_public_keys(&keychain.secp())
|
||||
};
|
||||
|
||||
|
@ -89,7 +91,7 @@ fn aggsig_sender_receiver_interaction() {
|
|||
// let blind = blind_sum.secret_key(&keychain.secp())?;
|
||||
let blind = keychain.derived_key(&key_id).unwrap();
|
||||
|
||||
rx_cx = sigcontext::Context::new(&keychain.secp(), blind);
|
||||
rx_cx = Context::new(&keychain.secp(), blind);
|
||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
||||
rx_cx.add_output(&key_id);
|
||||
|
||||
|
@ -234,12 +236,14 @@ fn aggsig_sender_receiver_interaction_offset() {
|
|||
|
||||
let keychain = ExtKeychain::from_random_seed().unwrap();
|
||||
let blinding_factor = keychain
|
||||
.blind_sum(&BlindSum::new()
|
||||
.blind_sum(
|
||||
&BlindSum::new()
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(skey1))
|
||||
.add_blinding_factor(BlindingFactor::from_secret_key(skey2))
|
||||
// subtract the kernel offset here like as would when
|
||||
// verifying a kernel signature
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(kernel_offset)))
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(kernel_offset)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
keychain
|
||||
|
@ -261,16 +265,18 @@ fn aggsig_sender_receiver_interaction_offset() {
|
|||
// dealing with an input here so we need to negate the blinding_factor
|
||||
// rather than use it as is
|
||||
let blinding_factor = keychain
|
||||
.blind_sum(&BlindSum::new()
|
||||
.blind_sum(
|
||||
&BlindSum::new()
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(skey))
|
||||
// subtract the kernel offset to create an aggsig context
|
||||
// with our "split" key
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(kernel_offset)))
|
||||
.sub_blinding_factor(BlindingFactor::from_secret_key(kernel_offset)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
||||
|
||||
s_cx = sigcontext::Context::new(&keychain.secp(), blind);
|
||||
s_cx = Context::new(&keychain.secp(), blind);
|
||||
s_cx.get_public_keys(&keychain.secp())
|
||||
};
|
||||
|
||||
|
@ -282,7 +288,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
|||
|
||||
let blind = keychain.derived_key(&key_id).unwrap();
|
||||
|
||||
rx_cx = sigcontext::Context::new(&keychain.secp(), blind);
|
||||
rx_cx = Context::new(&keychain.secp(), blind);
|
||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
||||
rx_cx.add_output(&key_id);
|
||||
|
||||
|
|
Loading…
Reference in a new issue