From 1d360e87e5135d7b7ff436b132c36d703ea1555f Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sat, 18 May 2019 16:02:42 +0100 Subject: [PATCH 01/16] Add encode() method to VersionedSlate --- libwallet/src/slate_versions/mod.rs | 99 +++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index 76484cf99..773ea4434 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -19,6 +19,10 @@ use crate::slate::Slate; use crate::slate_versions::v2::SlateV2; +use crate::error::{ErrorKind, Error}; + +use byteorder::{WriteBytesExt, BigEndian}; +use crate::grin_util::secp; #[allow(missing_docs)] pub mod v2; @@ -67,6 +71,101 @@ impl VersionedSlate { }*/ } } + + /// Encodes a slate into a vec of bytes by serializing the fields in order + /// and prepending variable length fields with their length + pub fn encode(&self) -> Result, Error> { + + let slate: &SlateV2 = match self { + VersionedSlate::V2(s) => s, + VersionedSlate::V1(_) => { return Err(ErrorKind::SlateSer)?; }, + VersionedSlate::V0(_) => { return Err(ErrorKind::SlateSer)?; } + }; + let mut buf: Vec = Vec::new(); + + // Save 3 bytes by casting u16 to u8 (should be fine up to slate v255) + buf.push(slate.version_info.version as u8); + buf.push(slate.version_info.orig_version as u8); + buf.push(slate.version_info.min_compat_version as u8); + + buf.write_u16::(slate.num_participants as u16)?; + + let txid = slate.id.to_hyphenated().to_string().into_bytes(); + buf.push(txid.len() as u8); // max 255 bytes long txid + buf.extend(txid); + + buf.extend(slate.tx.offset.as_ref()); + buf.write_u16::(slate.tx.body.inputs.len() as u16)?; + + for input in slate.tx.body.inputs.iter() { + buf.push(input.features as u8); + buf.extend(input.commit.0.iter()) + } + + buf.write_u16::(slate.tx.body.outputs.len() as u16)?; + + for output in slate.tx.body.outputs.iter() { + buf.push(output.features as u8); + + buf.extend(output.commit.0.iter()); + + buf.write_u16::(output.proof.len() as u16)?; + buf.extend(output.proof.bytes().iter()) + } + + buf.write_u16::(slate.tx.body.kernels.len() as u16)?; + + for kernel in slate.tx.body.kernels.iter() { + buf.push(kernel.features as u8); + + buf.write_u64::(kernel.fee)?; + + buf.write_u64::(kernel.lock_height)?; + buf.extend(kernel.excess.0.iter()); + buf.extend(kernel.excess_sig.as_ref()); + } + + buf.write_u64::(slate.amount)?; + buf.write_u64::(slate.fee)?; + buf.write_u64::(slate.height)?; + buf.write_u64::(slate.lock_height)?; + + buf.write_u16::(slate.participant_data.len() as u16)?; + + let s = secp::Secp256k1::new(); + + for pd in slate.participant_data.iter() { + // Save 7 bytes by casting u64 to u8, we only use 1 bit anyway + buf.push(pd.id as u8); + buf.extend(pd.public_blind_excess.serialize_vec(&s, true)); + buf.extend(pd.public_nonce.serialize_vec(&s, true)); + + match pd.part_sig { + None => buf.push(0), + Some(n) => { + buf.push(n.as_ref().len() as u8); + buf.extend(n.as_ref().iter()); + } + }; + + match &pd.message { + None => buf.push(0), + Some(n) => { + let msg = n.clone().into_bytes(); + buf.push(msg.len() as u8); // maximum message size 255 bytes + buf.extend(msg); + } + } + match pd.message_sig { + None => buf.push(0), + Some(n) => { + buf.push(n.as_ref().len() as u8); + buf.extend(n.as_ref().iter()); + } + } + } + Ok(buf) + } } impl From for Slate { From 5d5befb51ea8bde9f95918bd394f6b87e815e8d4 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sat, 18 May 2019 16:03:46 +0100 Subject: [PATCH 02/16] rustfmt --- libwallet/src/slate_versions/mod.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index 773ea4434..1cf706386 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -17,12 +17,12 @@ //! Versions earlier than V2 are removed for the 2.0.0 release, but versioning code //! remains for future needs +use crate::error::{Error, ErrorKind}; use crate::slate::Slate; use crate::slate_versions::v2::SlateV2; -use crate::error::{ErrorKind, Error}; -use byteorder::{WriteBytesExt, BigEndian}; use crate::grin_util::secp; +use byteorder::{BigEndian, WriteBytesExt}; #[allow(missing_docs)] pub mod v2; @@ -75,13 +75,16 @@ impl VersionedSlate { /// Encodes a slate into a vec of bytes by serializing the fields in order /// and prepending variable length fields with their length pub fn encode(&self) -> Result, Error> { - let slate: &SlateV2 = match self { VersionedSlate::V2(s) => s, - VersionedSlate::V1(_) => { return Err(ErrorKind::SlateSer)?; }, - VersionedSlate::V0(_) => { return Err(ErrorKind::SlateSer)?; } + VersionedSlate::V1(_) => { + return Err(ErrorKind::SlateSer)?; + } + VersionedSlate::V0(_) => { + return Err(ErrorKind::SlateSer)?; + } }; - let mut buf: Vec = Vec::new(); + let mut buf: Vec = Vec::new(); // Save 3 bytes by casting u16 to u8 (should be fine up to slate v255) buf.push(slate.version_info.version as u8); @@ -91,7 +94,7 @@ impl VersionedSlate { buf.write_u16::(slate.num_participants as u16)?; let txid = slate.id.to_hyphenated().to_string().into_bytes(); - buf.push(txid.len() as u8); // max 255 bytes long txid + buf.push(txid.len() as u8); // max 255 bytes long txid buf.extend(txid); buf.extend(slate.tx.offset.as_ref()); @@ -131,12 +134,12 @@ impl VersionedSlate { buf.write_u64::(slate.lock_height)?; buf.write_u16::(slate.participant_data.len() as u16)?; - + let s = secp::Secp256k1::new(); for pd in slate.participant_data.iter() { // Save 7 bytes by casting u64 to u8, we only use 1 bit anyway - buf.push(pd.id as u8); + buf.push(pd.id as u8); buf.extend(pd.public_blind_excess.serialize_vec(&s, true)); buf.extend(pd.public_nonce.serialize_vec(&s, true)); @@ -152,7 +155,7 @@ impl VersionedSlate { None => buf.push(0), Some(n) => { let msg = n.clone().into_bytes(); - buf.push(msg.len() as u8); // maximum message size 255 bytes + buf.push(msg.len() as u8); // maximum message size 255 bytes buf.extend(msg); } } From 2a8882d5afc26ea9a6275689db2e42e468a2de46 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sat, 18 May 2019 16:18:40 +0100 Subject: [PATCH 03/16] add StdioWalletCommAdapter --- impls/Cargo.toml | 1 + impls/src/adapters/mod.rs | 3 ++ impls/src/adapters/stdio.rs | 74 +++++++++++++++++++++++++++++++++++++ impls/src/lib.rs | 3 +- 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 impls/src/adapters/stdio.rs diff --git a/impls/Cargo.toml b/impls/Cargo.toml index 2c85d56cb..be8ea0e22 100644 --- a/impls/Cargo.toml +++ b/impls/Cargo.toml @@ -25,6 +25,7 @@ tokio-core = "0.1" tokio-retry = "0.1" uuid = { version = "0.7", features = ["serde", "v4"] } chrono = { version = "0.4.4", features = ["serde"] } +base64 = "0.9" grin_wallet_util = { path = "../util", version = "2.0.0-beta.1" } diff --git a/impls/src/adapters/mod.rs b/impls/src/adapters/mod.rs index fa4ce0fd7..fb4e95a2f 100644 --- a/impls/src/adapters/mod.rs +++ b/impls/src/adapters/mod.rs @@ -16,15 +16,18 @@ mod file; mod http; mod keybase; mod null; +mod stdio; pub use self::file::FileWalletCommAdapter; pub use self::http::HTTPWalletCommAdapter; pub use self::keybase::KeybaseWalletCommAdapter; pub use self::null::NullWalletCommAdapter; +pub use self::stdio::StdioWalletCommAdapter; use crate::config::WalletConfig; use crate::libwallet::{Error, Slate}; use std::collections::HashMap; +extern crate base64; /// Encapsulate wallet to wallet communication functions pub trait WalletCommAdapter { diff --git a/impls/src/adapters/stdio.rs b/impls/src/adapters/stdio.rs new file mode 100644 index 000000000..ca27fee0c --- /dev/null +++ b/impls/src/adapters/stdio.rs @@ -0,0 +1,74 @@ +// 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. + +/// Standard Input/Output 'plugin' implementation +use std::io::{stdin, stdout, Read, Write}; + +use crate::config::WalletConfig; +use crate::libwallet::{Error, Slate}; +use crate::libwallet::slate_versions::VersionedSlate; +use crate::WalletCommAdapter; +use std::collections::HashMap; +use crate::base64; + +#[derive(Clone)] +pub struct StdioWalletCommAdapter {} + +impl StdioWalletCommAdapter { + /// Create + pub fn new() -> Box { + Box::new(StdioWalletCommAdapter {}) + } +} + +impl WalletCommAdapter for StdioWalletCommAdapter { + fn supports_sync(&self) -> bool { + false + } + + fn send_tx_sync(&self, _dest: &str, _slate: &Slate) -> Result { + unimplemented!(); + } + + fn send_tx_async(&self, _dest: &str, slate: &Slate) -> Result<(), Error> { + let mut stream = stdout(); + let v2 = VersionedSlate::V2(slate.into()); + let bytes = v2.encode()?; + + stream.write_all( + base64::encode(&bytes).as_bytes() + )?; + stream.flush()?; + Ok(()) + } + + fn receive_tx_async(&self, params: &str) -> Result { + let mut stream = stdin(); + let mut content = String::new(); + stream.read_to_string(&mut content)?; + let bytes = base64::decode(content.as_bytes()); + Ok(Slate::deserialize_upgrade(&content)?) // TODO replace with slate.decode() + } + + fn listen( + &self, + _params: HashMap, + _config: WalletConfig, + _passphrase: &str, + _account: &str, + _node_api_secret: Option, + ) -> Result<(), Error> { + unimplemented!(); + } +} diff --git a/impls/src/lib.rs b/impls/src/lib.rs index ee846562a..74b6bea27 100644 --- a/impls/src/lib.rs +++ b/impls/src/lib.rs @@ -30,6 +30,7 @@ use grin_wallet_util::grin_keychain as keychain; use grin_wallet_util::grin_store as store; use grin_wallet_util::grin_util as util; extern crate grin_wallet_config as config; +extern crate base64; mod adapters; mod backends; @@ -40,7 +41,7 @@ pub mod test_framework; pub use crate::adapters::{ FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter, NullWalletCommAdapter, - WalletCommAdapter, + WalletCommAdapter, StdioWalletCommAdapter }; pub use crate::backends::{wallet_db_exists, LMDBBackend}; pub use crate::error::{Error, ErrorKind}; From 3bedd125090beffb8ec8a9ba7784e45526283d36 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sat, 18 May 2019 16:19:27 +0100 Subject: [PATCH 04/16] rustfmt --- impls/src/adapters/stdio.rs | 8 +++----- impls/src/lib.rs | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/impls/src/adapters/stdio.rs b/impls/src/adapters/stdio.rs index ca27fee0c..ab743d652 100644 --- a/impls/src/adapters/stdio.rs +++ b/impls/src/adapters/stdio.rs @@ -15,12 +15,12 @@ /// Standard Input/Output 'plugin' implementation use std::io::{stdin, stdout, Read, Write}; +use crate::base64; use crate::config::WalletConfig; -use crate::libwallet::{Error, Slate}; use crate::libwallet::slate_versions::VersionedSlate; +use crate::libwallet::{Error, Slate}; use crate::WalletCommAdapter; use std::collections::HashMap; -use crate::base64; #[derive(Clone)] pub struct StdioWalletCommAdapter {} @@ -46,9 +46,7 @@ impl WalletCommAdapter for StdioWalletCommAdapter { let v2 = VersionedSlate::V2(slate.into()); let bytes = v2.encode()?; - stream.write_all( - base64::encode(&bytes).as_bytes() - )?; + stream.write_all(base64::encode(&bytes).as_bytes())?; stream.flush()?; Ok(()) } diff --git a/impls/src/lib.rs b/impls/src/lib.rs index 74b6bea27..84086f304 100644 --- a/impls/src/lib.rs +++ b/impls/src/lib.rs @@ -29,8 +29,8 @@ use grin_wallet_util::grin_core as core; use grin_wallet_util::grin_keychain as keychain; use grin_wallet_util::grin_store as store; use grin_wallet_util::grin_util as util; -extern crate grin_wallet_config as config; extern crate base64; +extern crate grin_wallet_config as config; mod adapters; mod backends; @@ -41,7 +41,7 @@ pub mod test_framework; pub use crate::adapters::{ FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter, NullWalletCommAdapter, - WalletCommAdapter, StdioWalletCommAdapter + StdioWalletCommAdapter, WalletCommAdapter, }; pub use crate::backends::{wallet_db_exists, LMDBBackend}; pub use crate::error::{Error, ErrorKind}; From ea7759805182fa9c944f2f84ec0b38f5079b0976 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sun, 19 May 2019 15:20:28 +0100 Subject: [PATCH 05/16] add Slate.from_bytes() --- Cargo.lock | 23 +--- controller/src/command.rs | 25 +++-- impls/src/adapters/stdio.rs | 31 ++++-- libwallet/Cargo.toml | 4 +- libwallet/src/lib.rs | 1 + libwallet/src/slate_versions/mod.rs | 165 +++++++++++++++++++++++++++- libwallet/src/slate_versions/v2.rs | 13 ++- src/bin/cmd/wallet_args.rs | 61 +++++++--- src/bin/grin-wallet.yml | 13 ++- 9 files changed, 273 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5c4ae7a8..e608492de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -839,6 +839,7 @@ dependencies = [ name = "grin_wallet_impls" version = "2.0.0-beta.1" dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -864,7 +865,9 @@ name = "grin_wallet_libwallet" version = "2.0.0-beta.1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "grin_wallet_config 2.0.0-beta.1", @@ -875,8 +878,6 @@ dependencies = [ "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2101,22 +2102,6 @@ name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "strum" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strum_macros" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "supercow" version = "0.1.0" @@ -2941,8 +2926,6 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0bbfb8937e38e34c3444ff00afb28b0811d9554f15c5ad64d12b0308d1d1995" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1c33039533f051704951680f1adfd468fd37ac46816ded0d9ee068e60f05f" -"checksum strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47cd23f5c7dee395a00fa20135e2ec0fffcdfa151c56182966d7a3261343432e" "checksum supercow 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63" "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" diff --git a/controller/src/command.rs b/controller/src/command.rs index 9a13731c0..e974f9a95 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -32,10 +32,10 @@ use crate::config::WalletConfig; use crate::error::{Error, ErrorKind}; use crate::impls::{ instantiate_wallet, FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter, - LMDBBackend, NullWalletCommAdapter, + LMDBBackend, NullWalletCommAdapter, StdioWalletCommAdapter }; use crate::impls::{HTTPNodeClient, WalletSeed}; -use crate::libwallet::{InitTxArgs, IssueInvoiceTxArgs, NodeClient, WalletInst}; +use crate::libwallet::{InitTxArgs, IssueInvoiceTxArgs, NodeClient, WalletInst, Slate}; use crate::{controller, display}; /// Arguments common to all wallet commands @@ -436,6 +436,7 @@ pub fn finalize( pub struct IssueInvoiceArgs { /// output file pub dest: String, + pub method: String, /// issue invoice tx args pub issue_args: IssueInvoiceTxArgs, } @@ -446,9 +447,14 @@ pub fn issue_invoice_tx( ) -> Result<(), Error> { controller::owner_single_use(wallet.clone(), |api| { let slate = api.issue_invoice_tx(args.issue_args)?; - let mut tx_file = File::create(args.dest.clone())?; - tx_file.write_all(json::to_string(&slate).unwrap().as_bytes())?; - tx_file.sync_all()?; + let adapter = match args.method.as_str() { + "file" => FileWalletCommAdapter::new(), + "string" => StdioWalletCommAdapter::new(), + _ => NullWalletCommAdapter::new(), + }; + + adapter.send_tx_async(args.dest.as_str(), &slate)?; + Ok(()) })?; Ok(()) @@ -462,7 +468,8 @@ pub struct ProcessInvoiceArgs { pub method: String, pub dest: String, pub max_outputs: usize, - pub input: String, + pub target_slate_version: Option, + pub slate: Slate, pub estimate_selection_strategies: bool, } @@ -472,8 +479,9 @@ pub fn process_invoice( args: ProcessInvoiceArgs, dark_scheme: bool, ) -> Result<(), Error> { - let adapter = FileWalletCommAdapter::new(); - let slate = adapter.receive_tx_async(&args.input)?; + // let adapter = FileWalletCommAdapter::new(); + // let slate = adapter.receive_tx_async(&args.input)?; + let slate = args.slate.clone(); controller::owner_single_use(wallet.clone(), |api| { if args.estimate_selection_strategies { let strategies = vec!["smallest", "all"] @@ -530,6 +538,7 @@ pub fn process_invoice( "http" => HTTPWalletCommAdapter::new(), "file" => FileWalletCommAdapter::new(), "self" => NullWalletCommAdapter::new(), + "string" => StdioWalletCommAdapter::new(), _ => NullWalletCommAdapter::new(), }; if adapter.supports_sync() { diff --git a/impls/src/adapters/stdio.rs b/impls/src/adapters/stdio.rs index ab743d652..6960e7fa4 100644 --- a/impls/src/adapters/stdio.rs +++ b/impls/src/adapters/stdio.rs @@ -18,7 +18,7 @@ use std::io::{stdin, stdout, Read, Write}; use crate::base64; use crate::config::WalletConfig; use crate::libwallet::slate_versions::VersionedSlate; -use crate::libwallet::{Error, Slate}; +use crate::libwallet::{Error, ErrorKind, Slate}; use crate::WalletCommAdapter; use std::collections::HashMap; @@ -42,21 +42,34 @@ impl WalletCommAdapter for StdioWalletCommAdapter { } fn send_tx_async(&self, _dest: &str, slate: &Slate) -> Result<(), Error> { - let mut stream = stdout(); + + // let mut stream = stdout(); let v2 = VersionedSlate::V2(slate.into()); let bytes = v2.encode()?; + println!("{}", base64::encode(&bytes)); - stream.write_all(base64::encode(&bytes).as_bytes())?; - stream.flush()?; + // stream.write_all(base64::encode(&bytes).as_bytes())?; + // stream.flush()?; Ok(()) } fn receive_tx_async(&self, params: &str) -> Result { - let mut stream = stdin(); - let mut content = String::new(); - stream.read_to_string(&mut content)?; - let bytes = base64::decode(content.as_bytes()); - Ok(Slate::deserialize_upgrade(&content)?) // TODO replace with slate.decode() + // if user passed the string as input decode that, else + // read from stdin + let b64string = match params { + "" => { + let mut stream = stdin(); + let mut content = String::new(); + println!("Paste your base64 slate here."); + stream.read_to_string(&mut content)?; + content + } + _ => params.to_owned() + }; + + let bytes = base64::decode(b64string.as_bytes()).map_err(|_| ErrorKind::SlateDeser)?; + let v2 = VersionedSlate::from_bytes(bytes)?; + Ok(v2.into()) } fn listen( diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index 18ac86ae8..e155c0114 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -22,8 +22,8 @@ log = "0.4" uuid = { version = "0.7", features = ["serde", "v4"] } chrono = { version = "0.4.4", features = ["serde"] } lazy_static = "1" -strum = "0.15" -strum_macros = "0.15" +byteorder = "1" +enum_primitive = "*" grin_wallet_util = { path = "../util", version = "2.0.0-beta.1" } diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index b5a747b80..a4406fe73 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -49,6 +49,7 @@ mod internal; mod slate; pub mod slate_versions; mod types; +extern crate enum_primitive; pub use crate::error::{Error, ErrorKind}; pub use crate::slate::{ParticipantData, ParticipantMessageData, Slate}; diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index 1cf706386..5fc2722a2 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -22,7 +22,10 @@ use crate::slate::Slate; use crate::slate_versions::v2::SlateV2; use crate::grin_util::secp; -use byteorder::{BigEndian, WriteBytesExt}; +use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; +use std::io::{Cursor, Read}; +use std::str; +use crate::enum_primitive::FromPrimitive; #[allow(missing_docs)] pub mod v2; @@ -169,6 +172,166 @@ impl VersionedSlate { } Ok(buf) } + + /// Deserialize raw bytes to a v2 VersionedSlate + pub fn from_bytes(data: Vec) -> Result { + let mut rdr = Cursor::new(data); + + let version_info = v2::VersionCompatInfoV2{ + version: rdr.read_u8()? as u16, + orig_version: rdr.read_u8()? as u16, + min_compat_version: rdr.read_u8()? as u16 + }; + + let num_participants = rdr.read_u16::()? as usize; + let txid_len = rdr.read_u8()? as usize; + let mut id = [0u8; 255]; + rdr.read_exact(&mut id[..txid_len])?; + let id = str::from_utf8(&id[..txid_len]).map_err(|_| ErrorKind::SlateDeser)?; + let id = v2::Uuid::parse_str(id).map_err(|_| ErrorKind::SlateDeser)?; + + let mut offset = [0u8; 32]; + rdr.read_exact(&mut offset)?; + let offset = v2::BlindingFactor::from_slice(&offset); + + let n_inputs = rdr.read_u16::()? as usize; + let mut inputs: Vec = Vec::with_capacity(n_inputs); + + for _ in 0..n_inputs { + let features = v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; + let mut commit = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; + rdr.read_exact(&mut commit)?; + let commit = v2::Commitment(commit); + inputs.push(v2::InputV2{features, commit}); + } + + let n_outputs = rdr.read_u16::()? as usize; + let mut outputs: Vec = Vec::with_capacity(n_outputs); + + for _ in 0..n_outputs { + let features = v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; + let mut commit = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; + rdr.read_exact(&mut commit)?; + let commit = v2::Commitment(commit); + let mut proof = [0u8; secp::constants::MAX_PROOF_SIZE]; + let plen = rdr.read_u16::()? as usize; + rdr.read_exact(&mut proof[..plen])?; + + let output = v2::OutputV2{ + features, + commit, + proof: v2::RangeProof { + proof, + plen + } + }; + outputs.push(output); + } + + let n_kernels = rdr.read_u16::()? as usize; + let mut kernels: Vec = Vec::with_capacity(n_kernels); + + for _ in 0..n_kernels { + let features = v2::KernelFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; + let fee = rdr.read_u64::()?; + let lock_height = rdr.read_u64::()?; + + let mut excess = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; + rdr.read_exact(&mut excess)?; + let excess = v2::Commitment(excess); + + let mut excess_sig = [0u8; secp::constants::COMPACT_SIGNATURE_SIZE]; + rdr.read_exact(&mut excess_sig)?; + let excess_sig = v2::Signature::from_raw_data(&excess_sig)?; + + kernels.push(v2::TxKernelV2{features, fee, lock_height, excess, excess_sig}); + } + + let tx = v2::TransactionV2{ + offset, + body: v2::TransactionBodyV2{ + inputs, + outputs, + kernels + } + }; + + let amount = rdr.read_u64::()?; + let fee = rdr.read_u64::()?; + let height = rdr.read_u64::()?; + let lock_height = rdr.read_u64::()?; + + let pdata_len = rdr.read_u16::()? as usize; + let mut participant_data: Vec = Vec::with_capacity(pdata_len); + + + + let s = secp::Secp256k1::new(); + + for _ in 0..pdata_len { + let id = rdr.read_u8()? as u64; + + let mut public_blind_excess = [0u8; secp::constants::COMPRESSED_PUBLIC_KEY_SIZE]; + rdr.read_exact(&mut public_blind_excess)?; + let public_blind_excess = v2::PublicKey::from_slice(&s, &public_blind_excess)?; + + let mut public_nonce = [0u8; secp::constants::COMPRESSED_PUBLIC_KEY_SIZE]; + rdr.read_exact(&mut public_nonce)?; + let public_nonce = v2::PublicKey::from_slice(&s, &public_nonce)?; + + let part_sig: Option = match rdr.read_u8()? { + 0 => None, + _ => { + let mut sig = [0u8; 64]; + rdr.read_exact(&mut sig)?; + Some(v2::Signature::from_raw_data(&sig)?) + } + }; + + let message: Option = match rdr.read_u8()? { + 0 => None, + n => { + let n = n as usize; + let mut msg = [0u8; 255]; + rdr.read_exact(&mut msg[..n])?; + let string = String::from_utf8(msg[..n].to_vec()).map_err(|_| ErrorKind::SlateDeser)?; + Some(string) + } + }; + + let message_sig: Option = match rdr.read_u8()? { + 0 => None, + _ => { + let mut sig = [0u8; 64]; + rdr.read_exact(&mut sig)?; + Some(v2::Signature::from_raw_data(&sig)?) + } + }; + + participant_data.push(v2::ParticipantDataV2{ + id, + public_blind_excess, + public_nonce, + part_sig, + message, + message_sig + }); + } + + let slate = v2::SlateV2{ + version_info, + num_participants, + id, + tx, + amount, + fee, + height, + lock_height, + participant_data + }; + + Ok(VersionedSlate::V2(slate)) + } } impl From for Slate { diff --git a/libwallet/src/slate_versions/v2.rs b/libwallet/src/slate_versions/v2.rs index 336fb896d..f200a1df1 100644 --- a/libwallet/src/slate_versions/v2.rs +++ b/libwallet/src/slate_versions/v2.rs @@ -35,14 +35,15 @@ //! orig_version: u16, //! block_header_version: u16, -use crate::grin_core::core::transaction::{KernelFeatures, OutputFeatures}; +pub use crate::grin_core::core::transaction::{KernelFeatures, OutputFeatures}; use crate::grin_core::libtx::secp_ser; -use crate::grin_keychain::BlindingFactor; +use crate::grin_core::map_vec; +pub use crate::grin_keychain::BlindingFactor; use crate::grin_util::secp; -use crate::grin_util::secp::key::PublicKey; -use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; -use crate::grin_util::secp::Signature; -use uuid::Uuid; +pub use crate::grin_util::secp::key::PublicKey; +pub use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; +pub use crate::grin_util::secp::Signature; +pub use uuid::Uuid; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SlateV2 { diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index 3a12f6e90..541147c65 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -21,8 +21,8 @@ use failure::Fail; use grin_wallet_config::WalletConfig; use grin_wallet_controller::command; use grin_wallet_controller::{Error, ErrorKind}; -use grin_wallet_impls::{instantiate_wallet, WalletSeed}; -use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, WalletInst}; +use grin_wallet_impls::{instantiate_wallet, FileWalletCommAdapter, StdioWalletCommAdapter, WalletSeed}; +use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, Slate, WalletInst}; use grin_wallet_util::grin_core as core; use grin_wallet_util::grin_keychain as keychain; use linefeed::terminal::Signal; @@ -151,7 +151,7 @@ fn prompt_recovery_phrase() -> Result { #[cfg(not(test))] fn prompt_pay_invoice(slate: &Slate, method: &str, dest: &str) -> Result { let interface = Arc::new(Interface::new("pay")?); - let amount = amount_to_hr_string(slate.amount, false); + let amount = amount_to_hr_string(slate.amount, true); interface.set_report_signal(Signal::Interrupt, true); interface.set_prompt( "To proceed, type the exact amount of the invoice as displayed above (or Q/q to quit) > ", @@ -168,8 +168,10 @@ fn prompt_pay_invoice(slate: &Slate, method: &str, dest: &str) -> Result "", + _ => parse_required(args, "dest")? + }; + Ok(command::IssueInvoiceArgs { dest: dest.into(), + method: method.to_string(), issue_args: IssueInvoiceTxArgs { dest_acct_name: None, amount, @@ -596,7 +604,7 @@ pub fn parse_process_invoice_args( None => "default", } } else { - if !estimate_selection_strategies { + if !estimate_selection_strategies && method != "string" { parse_required(args, "dest")? } else { "" @@ -618,18 +626,38 @@ pub fn parse_process_invoice_args( // max_outputs let max_outputs = 500; - // file input only - let tx_file = parse_required(args, "input")?; + // target slate version to create/send + let target_slate_version = { + match args.is_present("slate_version") { + true => { + let v = parse_required(args, "slate_version")?; + Some(parse_u64(v, "slate_version")? as u16) + } + false => None, + } + }; + + let params = match method { + // tx_file location + "file" => parse_required(args, "input")?, + // if user provided the string as input use that or else wait + // for input from stdin (the adapter does that if string is empty) + "string" => args.value_of("input").unwrap_or(""), // b64 string + _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())) + }; + + let adapter = match method { + "file" => FileWalletCommAdapter::new(), + "string" => StdioWalletCommAdapter::new(), + _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())) + }; // Now we need to prompt the user whether they want to do this, // which requires reading the slate - #[cfg(not(test))] - let adapter = FileWalletCommAdapter::new(); - #[cfg(not(test))] - let slate = match adapter.receive_tx_async(&tx_file) { + let slate = match adapter.receive_tx_async(¶ms) { Ok(s) => s, Err(e) => return Err(ParseError::ArgumentError(format!("{}", e))), - }; + }; #[cfg(not(test))] // don't prompt during automated testing prompt_pay_invoice(&slate, method, dest)?; @@ -642,9 +670,10 @@ pub fn parse_process_invoice_args( method: method.to_owned(), dest: dest.to_owned(), max_outputs: max_outputs, - input: tx_file.to_owned(), - }) -} + target_slate_version: target_slate_version, + slate: slate, + }) + } pub fn parse_info_args(args: &ArgMatches) -> Result { // minimum_confirmations diff --git a/src/bin/grin-wallet.yml b/src/bin/grin-wallet.yml index 87d270cce..7f32ecf67 100644 --- a/src/bin/grin-wallet.yml +++ b/src/bin/grin-wallet.yml @@ -111,6 +111,7 @@ subcommands: - file - self - keybase + - string default_value: http takes_value: true - dest: @@ -183,6 +184,15 @@ subcommands: short: d long: dest takes_value: true + - method: + help: Method for sending this invoice + short: m + long: method + possible_values: + - file + - string + default_value: string + takes_value: true - pay: about: Spend coins to pay the provided invoice transaction args: @@ -213,7 +223,8 @@ subcommands: - file - http - self - default_value: file + - string + default_value: string takes_value: true - dest: help: Send the transaction to the provided server (start with http://) or save as file. From 3264ccc62549cf6ff333891e9276a701a347b873 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sun, 19 May 2019 15:21:19 +0100 Subject: [PATCH 06/16] rustfmt --- controller/src/command.rs | 4 +- impls/src/adapters/stdio.rs | 3 +- libwallet/src/slate_versions/mod.rs | 61 ++++++++++++++++------------- src/bin/cmd/wallet_args.rs | 20 +++++----- 4 files changed, 47 insertions(+), 41 deletions(-) diff --git a/controller/src/command.rs b/controller/src/command.rs index e974f9a95..6e9636699 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -32,10 +32,10 @@ use crate::config::WalletConfig; use crate::error::{Error, ErrorKind}; use crate::impls::{ instantiate_wallet, FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter, - LMDBBackend, NullWalletCommAdapter, StdioWalletCommAdapter + LMDBBackend, NullWalletCommAdapter, StdioWalletCommAdapter, }; use crate::impls::{HTTPNodeClient, WalletSeed}; -use crate::libwallet::{InitTxArgs, IssueInvoiceTxArgs, NodeClient, WalletInst, Slate}; +use crate::libwallet::{InitTxArgs, IssueInvoiceTxArgs, NodeClient, Slate, WalletInst}; use crate::{controller, display}; /// Arguments common to all wallet commands diff --git a/impls/src/adapters/stdio.rs b/impls/src/adapters/stdio.rs index 6960e7fa4..51e231e6b 100644 --- a/impls/src/adapters/stdio.rs +++ b/impls/src/adapters/stdio.rs @@ -42,7 +42,6 @@ impl WalletCommAdapter for StdioWalletCommAdapter { } fn send_tx_async(&self, _dest: &str, slate: &Slate) -> Result<(), Error> { - // let mut stream = stdout(); let v2 = VersionedSlate::V2(slate.into()); let bytes = v2.encode()?; @@ -64,7 +63,7 @@ impl WalletCommAdapter for StdioWalletCommAdapter { stream.read_to_string(&mut content)?; content } - _ => params.to_owned() + _ => params.to_owned(), }; let bytes = base64::decode(b64string.as_bytes()).map_err(|_| ErrorKind::SlateDeser)?; diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index 5fc2722a2..fc2aa3b5b 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -21,11 +21,11 @@ use crate::error::{Error, ErrorKind}; use crate::slate::Slate; use crate::slate_versions::v2::SlateV2; +use crate::enum_primitive::FromPrimitive; use crate::grin_util::secp; -use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; +use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use std::io::{Cursor, Read}; use std::str; -use crate::enum_primitive::FromPrimitive; #[allow(missing_docs)] pub mod v2; @@ -177,10 +177,10 @@ impl VersionedSlate { pub fn from_bytes(data: Vec) -> Result { let mut rdr = Cursor::new(data); - let version_info = v2::VersionCompatInfoV2{ - version: rdr.read_u8()? as u16, - orig_version: rdr.read_u8()? as u16, - min_compat_version: rdr.read_u8()? as u16 + let version_info = v2::VersionCompatInfoV2 { + version: rdr.read_u8()? as u16, + orig_version: rdr.read_u8()? as u16, + min_compat_version: rdr.read_u8()? as u16, }; let num_participants = rdr.read_u16::()? as usize; @@ -198,18 +198,20 @@ impl VersionedSlate { let mut inputs: Vec = Vec::with_capacity(n_inputs); for _ in 0..n_inputs { - let features = v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; + let features = + v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; let mut commit = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; rdr.read_exact(&mut commit)?; let commit = v2::Commitment(commit); - inputs.push(v2::InputV2{features, commit}); + inputs.push(v2::InputV2 { features, commit }); } let n_outputs = rdr.read_u16::()? as usize; let mut outputs: Vec = Vec::with_capacity(n_outputs); for _ in 0..n_outputs { - let features = v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; + let features = + v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; let mut commit = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; rdr.read_exact(&mut commit)?; let commit = v2::Commitment(commit); @@ -217,13 +219,10 @@ impl VersionedSlate { let plen = rdr.read_u16::()? as usize; rdr.read_exact(&mut proof[..plen])?; - let output = v2::OutputV2{ + let output = v2::OutputV2 { features, commit, - proof: v2::RangeProof { - proof, - plen - } + proof: v2::RangeProof { proof, plen }, }; outputs.push(output); } @@ -232,10 +231,11 @@ impl VersionedSlate { let mut kernels: Vec = Vec::with_capacity(n_kernels); for _ in 0..n_kernels { - let features = v2::KernelFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; + let features = + v2::KernelFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; let fee = rdr.read_u64::()?; let lock_height = rdr.read_u64::()?; - + let mut excess = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; rdr.read_exact(&mut excess)?; let excess = v2::Commitment(excess); @@ -244,16 +244,22 @@ impl VersionedSlate { rdr.read_exact(&mut excess_sig)?; let excess_sig = v2::Signature::from_raw_data(&excess_sig)?; - kernels.push(v2::TxKernelV2{features, fee, lock_height, excess, excess_sig}); + kernels.push(v2::TxKernelV2 { + features, + fee, + lock_height, + excess, + excess_sig, + }); } - let tx = v2::TransactionV2{ + let tx = v2::TransactionV2 { offset, - body: v2::TransactionBodyV2{ + body: v2::TransactionBodyV2 { inputs, outputs, - kernels - } + kernels, + }, }; let amount = rdr.read_u64::()?; @@ -264,8 +270,6 @@ impl VersionedSlate { let pdata_len = rdr.read_u16::()? as usize; let mut participant_data: Vec = Vec::with_capacity(pdata_len); - - let s = secp::Secp256k1::new(); for _ in 0..pdata_len { @@ -294,7 +298,8 @@ impl VersionedSlate { let n = n as usize; let mut msg = [0u8; 255]; rdr.read_exact(&mut msg[..n])?; - let string = String::from_utf8(msg[..n].to_vec()).map_err(|_| ErrorKind::SlateDeser)?; + let string = + String::from_utf8(msg[..n].to_vec()).map_err(|_| ErrorKind::SlateDeser)?; Some(string) } }; @@ -308,17 +313,17 @@ impl VersionedSlate { } }; - participant_data.push(v2::ParticipantDataV2{ + participant_data.push(v2::ParticipantDataV2 { id, public_blind_excess, public_nonce, part_sig, message, - message_sig + message_sig, }); } - let slate = v2::SlateV2{ + let slate = v2::SlateV2 { version_info, num_participants, id, @@ -327,7 +332,7 @@ impl VersionedSlate { fee, height, lock_height, - participant_data + participant_data, }; Ok(VersionedSlate::V2(slate)) diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index 541147c65..d7679c4c7 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -21,7 +21,9 @@ use failure::Fail; use grin_wallet_config::WalletConfig; use grin_wallet_controller::command; use grin_wallet_controller::{Error, ErrorKind}; -use grin_wallet_impls::{instantiate_wallet, FileWalletCommAdapter, StdioWalletCommAdapter, WalletSeed}; +use grin_wallet_impls::{ + instantiate_wallet, FileWalletCommAdapter, StdioWalletCommAdapter, WalletSeed, +}; use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, Slate, WalletInst}; use grin_wallet_util::grin_core as core; use grin_wallet_util::grin_keychain as keychain; @@ -558,7 +560,7 @@ pub fn parse_issue_invoice_args( let method = parse_required(args, "method")?; let dest = match method { "string" => "", - _ => parse_required(args, "dest")? + _ => parse_required(args, "dest")?, }; Ok(command::IssueInvoiceArgs { @@ -639,17 +641,17 @@ pub fn parse_process_invoice_args( let params = match method { // tx_file location - "file" => parse_required(args, "input")?, + "file" => parse_required(args, "input")?, // if user provided the string as input use that or else wait // for input from stdin (the adapter does that if string is empty) - "string" => args.value_of("input").unwrap_or(""), // b64 string - _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())) + "string" => args.value_of("input").unwrap_or(""), // b64 string + _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())), }; let adapter = match method { "file" => FileWalletCommAdapter::new(), "string" => StdioWalletCommAdapter::new(), - _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())) + _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())), }; // Now we need to prompt the user whether they want to do this, @@ -657,7 +659,7 @@ pub fn parse_process_invoice_args( let slate = match adapter.receive_tx_async(¶ms) { Ok(s) => s, Err(e) => return Err(ParseError::ArgumentError(format!("{}", e))), - }; + }; #[cfg(not(test))] // don't prompt during automated testing prompt_pay_invoice(&slate, method, dest)?; @@ -672,8 +674,8 @@ pub fn parse_process_invoice_args( max_outputs: max_outputs, target_slate_version: target_slate_version, slate: slate, - }) - } + }) +} pub fn parse_info_args(args: &ArgMatches) -> Result { // minimum_confirmations From 92fafa36147a2a6c97877868953abdc005456f21 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sun, 19 May 2019 16:01:12 +0100 Subject: [PATCH 07/16] add "string" method to grin-wallet finalize --- controller/src/command.rs | 9 ++++++--- impls/src/adapters/stdio.rs | 8 ++------ src/bin/cmd/wallet_args.rs | 18 ++++++++++++++---- src/bin/grin-wallet.yml | 12 +++++++++++- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/controller/src/command.rs b/controller/src/command.rs index 6e9636699..957faab2e 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -367,6 +367,7 @@ pub fn receive( /// Finalize command args pub struct FinalizeArgs { + pub method: String, pub input: String, pub fluff: bool, } @@ -375,7 +376,11 @@ pub fn finalize( wallet: Arc>>, args: FinalizeArgs, ) -> Result<(), Error> { - let adapter = FileWalletCommAdapter::new(); + let adapter = match &args.method[..] { + "file" => FileWalletCommAdapter::new(), + "string" => StdioWalletCommAdapter::new(), + _ => NullWalletCommAdapter::new(), + }; let mut slate = adapter.receive_tx_async(&args.input)?; // Rather than duplicating the entire command, we'll just // try to determine what kind of finalization this is @@ -479,8 +484,6 @@ pub fn process_invoice( args: ProcessInvoiceArgs, dark_scheme: bool, ) -> Result<(), Error> { - // let adapter = FileWalletCommAdapter::new(); - // let slate = adapter.receive_tx_async(&args.input)?; let slate = args.slate.clone(); controller::owner_single_use(wallet.clone(), |api| { if args.estimate_selection_strategies { diff --git a/impls/src/adapters/stdio.rs b/impls/src/adapters/stdio.rs index 51e231e6b..a90043a62 100644 --- a/impls/src/adapters/stdio.rs +++ b/impls/src/adapters/stdio.rs @@ -13,7 +13,7 @@ // limitations under the License. /// Standard Input/Output 'plugin' implementation -use std::io::{stdin, stdout, Read, Write}; +use std::io::{stdin, Read}; use crate::base64; use crate::config::WalletConfig; @@ -42,24 +42,20 @@ impl WalletCommAdapter for StdioWalletCommAdapter { } fn send_tx_async(&self, _dest: &str, slate: &Slate) -> Result<(), Error> { - // let mut stream = stdout(); let v2 = VersionedSlate::V2(slate.into()); let bytes = v2.encode()?; println!("{}", base64::encode(&bytes)); - - // stream.write_all(base64::encode(&bytes).as_bytes())?; - // stream.flush()?; Ok(()) } fn receive_tx_async(&self, params: &str) -> Result { + let params = params.trim(); // if user passed the string as input decode that, else // read from stdin let b64string = match params { "" => { let mut stream = stdin(); let mut content = String::new(); - println!("Paste your base64 slate here."); stream.read_to_string(&mut content)?; content } diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index d7679c4c7..e647b79e9 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -513,15 +513,25 @@ pub fn parse_receive_args(receive_args: &ArgMatches) -> Result Result { + let method = parse_required(args, "method")?; let fluff = args.is_present("fluff"); - let tx_file = parse_required(args, "input")?; - if !Path::new(&tx_file).is_file() { - let msg = format!("File {} not found.", tx_file); + let params = match method { + // tx_file location + "file" => parse_required(args, "input")?, + // if user provided the string as input use that or else wait + // for input from stdin (the adapter does that if string is empty) + "string" => args.value_of("input").unwrap_or(""), // b64 string + _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())), + }; + + if method == "file" && !Path::new(¶ms).is_file() { + let msg = format!("File {} not found.", params); return Err(ParseError::ArgumentError(msg)); } Ok(command::FinalizeArgs { - input: tx_file.to_owned(), + method: method.to_owned(), + input: params.to_owned(), fluff: fluff, }) } diff --git a/src/bin/grin-wallet.yml b/src/bin/grin-wallet.yml index 7f32ecf67..08610f41a 100644 --- a/src/bin/grin-wallet.yml +++ b/src/bin/grin-wallet.yml @@ -155,7 +155,7 @@ subcommands: about: Processes a receiver's transaction file to finalize a transfer. args: - input: - help: Partial transaction to process, expects the receiver's transaction file. + help: Partial transaction to process, expects the receiver's transaction file or a base64 string. short: i long: input takes_value: true @@ -163,6 +163,16 @@ subcommands: help: Fluff the transaction (ignore Dandelion relay protocol) short: f long: fluff + - method: + help: Method of input for the slate + short: m + long: method + possible_values: + - file + - string + default_value: file + takes_value: true + - invoice: about: Initialize an invoice transction. args: From 2786fb8c64948fe53d73b5d917c6ac15b311c768 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sun, 19 May 2019 20:54:14 +0100 Subject: [PATCH 08/16] add 'string' method to 'send' and 'receive' --- controller/src/command.rs | 21 +++++++++++++++------ src/bin/cmd/wallet_args.rs | 20 ++++++++++++++------ src/bin/grin-wallet.yml | 9 +++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/controller/src/command.rs b/controller/src/command.rs index 957faab2e..e0f120cc9 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -296,6 +296,7 @@ pub fn send( "file" => FileWalletCommAdapter::new(), "keybase" => KeybaseWalletCommAdapter::new(), "self" => NullWalletCommAdapter::new(), + "string" => StdioWalletCommAdapter::new(), _ => NullWalletCommAdapter::new(), }; if adapter.supports_sync() { @@ -337,6 +338,7 @@ pub fn send( /// Receive command argument pub struct ReceiveArgs { + pub method: String, pub input: String, pub message: Option, } @@ -346,7 +348,12 @@ pub fn receive( g_args: &GlobalArgs, args: ReceiveArgs, ) -> Result<(), Error> { - let adapter = FileWalletCommAdapter::new(); + + let adapter = match args.method.as_str() { + "file" => FileWalletCommAdapter::new(), + "string" => StdioWalletCommAdapter::new(), + _ => NullWalletCommAdapter::new(), + }; let mut slate = adapter.receive_tx_async(&args.input)?; controller::foreign_single_use(wallet, |api| { if let Err(e) = api.verify_slate_messages(&slate) { @@ -358,10 +365,12 @@ pub fn receive( })?; let send_tx = format!("{}.response", args.input); adapter.send_tx_async(&send_tx, &slate)?; - info!( - "Response file {}.response generated, and can be sent back to the transaction originator.", - args.input - ); + if args.method.as_str() == "file" { + info!( + "Response file {}.response generated, sending it back to the transaction originator.", + args.input + ); + } Ok(()) } @@ -376,7 +385,7 @@ pub fn finalize( wallet: Arc>>, args: FinalizeArgs, ) -> Result<(), Error> { - let adapter = match &args.method[..] { + let adapter = match args.method.as_str() { "file" => FileWalletCommAdapter::new(), "string" => StdioWalletCommAdapter::new(), _ => NullWalletCommAdapter::new(), diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index e647b79e9..28d6d1cf8 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -435,7 +435,7 @@ pub fn parse_send_args(args: &ArgMatches) -> Result "default", } } else { - if !estimate_selection_strategies { + if !estimate_selection_strategies && method != "string" { parse_required(args, "dest")? } else { "" @@ -496,18 +496,26 @@ pub fn parse_receive_args(receive_args: &ArgMatches) -> Result Some(receive_args.value_of("message").unwrap().to_owned()), false => None, }; + let method = parse_required(receive_args, "method")?; - // input - let tx_file = parse_required(receive_args, "input")?; + let params = match method { + // tx_file location + "file" => parse_required(receive_args, "input")?, + // if user provided the string as input use that or else wait + // for input from stdin (the adapter does that if string is empty) + "string" => receive_args.value_of("input").unwrap_or(""), // b64 string + _ => return Err(ParseError::ArgumentError("Unknown method".to_owned())), + }; // validate input - if !Path::new(&tx_file).is_file() { - let msg = format!("File {} not found.", &tx_file); + if method == "file" && !Path::new(¶ms).is_file() { + let msg = format!("File {} not found.", ¶ms); return Err(ParseError::ArgumentError(msg)); } Ok(command::ReceiveArgs { - input: tx_file.to_owned(), + method: method.to_owned(), + input: params.to_owned(), message: message, }) } diff --git a/src/bin/grin-wallet.yml b/src/bin/grin-wallet.yml index 08610f41a..0a86da3da 100644 --- a/src/bin/grin-wallet.yml +++ b/src/bin/grin-wallet.yml @@ -151,6 +151,15 @@ subcommands: short: i long: input takes_value: true + - method: + help: Method for sending this transaction + short: m + long: method + possible_values: + - file + - string + default_value: file + takes_value: true - finalize: about: Processes a receiver's transaction file to finalize a transfer. args: From a73549b65eecb2a3de0ac00ff2437b2024a28ee4 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Sun, 19 May 2019 20:54:30 +0100 Subject: [PATCH 09/16] rustfmt --- controller/src/command.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/controller/src/command.rs b/controller/src/command.rs index e0f120cc9..b817243c7 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -348,7 +348,6 @@ pub fn receive( g_args: &GlobalArgs, args: ReceiveArgs, ) -> Result<(), Error> { - let adapter = match args.method.as_str() { "file" => FileWalletCommAdapter::new(), "string" => StdioWalletCommAdapter::new(), From b6560edcb40bd5046856419218803a68b6f23750 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Fri, 24 May 2019 17:53:40 +0100 Subject: [PATCH 10/16] Move encoding to a trait of Slate --- Cargo.lock | 2 - impls/src/adapters/stdio.rs | 8 +- libwallet/Cargo.toml | 2 - libwallet/src/lib.rs | 1 - libwallet/src/slate.rs | 257 +++++++++++++++++++++++++- libwallet/src/slate_versions/mod.rs | 269 ---------------------------- libwallet/src/slate_versions/v2.rs | 12 +- 7 files changed, 265 insertions(+), 286 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e608492de..3efa9f310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -865,9 +865,7 @@ name = "grin_wallet_libwallet" version = "2.0.0-beta.1" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "grin_wallet_config 2.0.0-beta.1", diff --git a/impls/src/adapters/stdio.rs b/impls/src/adapters/stdio.rs index a90043a62..47ec3e509 100644 --- a/impls/src/adapters/stdio.rs +++ b/impls/src/adapters/stdio.rs @@ -17,7 +17,6 @@ use std::io::{stdin, Read}; use crate::base64; use crate::config::WalletConfig; -use crate::libwallet::slate_versions::VersionedSlate; use crate::libwallet::{Error, ErrorKind, Slate}; use crate::WalletCommAdapter; use std::collections::HashMap; @@ -42,8 +41,7 @@ impl WalletCommAdapter for StdioWalletCommAdapter { } fn send_tx_async(&self, _dest: &str, slate: &Slate) -> Result<(), Error> { - let v2 = VersionedSlate::V2(slate.into()); - let bytes = v2.encode()?; + let bytes = slate.to_bytes()?; println!("{}", base64::encode(&bytes)); Ok(()) } @@ -63,8 +61,8 @@ impl WalletCommAdapter for StdioWalletCommAdapter { }; let bytes = base64::decode(b64string.as_bytes()).map_err(|_| ErrorKind::SlateDeser)?; - let v2 = VersionedSlate::from_bytes(bytes)?; - Ok(v2.into()) + let slate = Slate::from_bytes(&bytes)?; + Ok(slate) } fn listen( diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index e155c0114..bb7759850 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -22,8 +22,6 @@ log = "0.4" uuid = { version = "0.7", features = ["serde", "v4"] } chrono = { version = "0.4.4", features = ["serde"] } lazy_static = "1" -byteorder = "1" -enum_primitive = "*" grin_wallet_util = { path = "../util", version = "2.0.0-beta.1" } diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index a4406fe73..b5a747b80 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -49,7 +49,6 @@ mod internal; mod slate; pub mod slate_versions; mod types; -extern crate enum_primitive; pub use crate::error::{Error, ErrorKind}; pub use crate::slate::{ParticipantData, ParticipantMessageData, Slate}; diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index 0965b44a1..29e76c94f 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -21,13 +21,17 @@ use crate::grin_core::core::amount_to_hr_string; use crate::grin_core::core::committed::Committed; use crate::grin_core::core::transaction::{ kernel_features, kernel_sig_msg, Input, Output, Transaction, TransactionBody, TxKernel, - Weighting, + Weighting, OutputFeatures, KernelFeatures }; +use crate::grin_core::ser; +use crate::grin_core::ser::{Readable, Writeable, Writer, Reader}; use crate::grin_core::core::verifier_cache::LruVerifierCache; use crate::grin_core::libtx::{aggsig, build, secp_ser, tx_fee}; use crate::grin_core::map_vec; use crate::grin_keychain::{BlindSum, BlindingFactor, Keychain}; use crate::grin_util::secp::key::{PublicKey, SecretKey}; +use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; + use crate::grin_util::secp::Signature; use crate::grin_util::{self, secp, RwLock}; use failure::ResultExt; @@ -36,6 +40,7 @@ use rand::thread_rng; use serde::ser::{Serialize, Serializer}; use serde_json; use std::fmt; +use std::str; use std::sync::Arc; use uuid::Uuid; @@ -662,6 +667,19 @@ impl Slate { self.tx = final_tx; Ok(()) } + + /// Encodes a slate into a vec of bytes by serializing the fields in order + /// and prepending variable length fields with their length + pub fn to_bytes(&self) -> Result, Error> { + let vec = ser::ser_vec(self).map_err(|_| ErrorKind::SlateSer)?; + Ok(vec) + } + + /// Deserialize raw bytes into a slate + pub fn from_bytes(bytes: &Vec) -> Result { + let slate = ser::deserialize(&mut &bytes[..]).map_err(|_| ErrorKind::SlateDeser)?; + Ok(slate) + } } impl Serialize for Slate { @@ -685,6 +703,243 @@ impl Serialize for Slate { } } +impl Writeable for Slate { + + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { + + // Save 3 bytes by casting u16 to u8 (should be fine up to slate v255) + writer.write_u8(self.version_info.version as u8)?; + writer.write_u8(self.version_info.orig_version as u8)?; + writer.write_u8(self.version_info.min_compat_version as u8)?; + + writer.write_u16(self.num_participants as u16)?; + + let txid = self.id.to_hyphenated().to_string().into_bytes(); + writer.write_u8(txid.len() as u8)?; // max 255 bytes long txid + writer.write_fixed_bytes(&txid)?; + + writer.write_fixed_bytes(&self.tx.offset)?; + + writer.write_u16(self.tx.body.inputs.len() as u16)?; + + for input in self.tx.body.inputs.iter() { + writer.write_u8(input.features as u8)?; + input.commit.write(writer)?; + } + + writer.write_u16(self.tx.body.outputs.len() as u16)?; + + for output in self.tx.body.outputs.iter() { + writer.write_u8(output.features as u8)?; + writer.write_fixed_bytes(&output.commit)?; + + // Don't use RangeProof::write() because it encodes length as u64 + writer.write_u16(output.proof.len() as u16)?; + writer.write_fixed_bytes(&output.proof)?; + } + + writer.write_u16(self.tx.body.kernels.len() as u16)?; + + for kernel in self.tx.body.kernels.iter() { + kernel.features.write(writer)?; + writer.write_u64(kernel.fee)?; + writer.write_u64(kernel.lock_height)?; + kernel.excess.write(writer)?; + kernel.excess_sig.write(writer)?; + + } + + writer.write_u64(self.amount)?; + writer.write_u64(self.fee)?; + writer.write_u64(self.height)?; + writer.write_u64(self.lock_height)?; + + writer.write_u16(self.participant_data.len() as u16)?; + + let s = secp::Secp256k1::new(); + + for pd in self.participant_data.iter() { + // Save 7 bytes by casting u64 to u8, we only use 1 bit anyway + writer.write_u8(pd.id as u8)?; + writer.write_fixed_bytes(&pd.public_blind_excess.serialize_vec(&s, true).as_ref())?; + writer.write_fixed_bytes(&pd.public_nonce.serialize_vec(&s, true).as_ref())?; + + match pd.part_sig { + None => writer.write_u8(0)?, + Some(n) => { + writer.write_u8(n.as_ref().len() as u8)?; + n.write(writer)?; + } + }; + + match &pd.message { + None => writer.write_u8(0)?, + Some(n) => { + let msg = n.clone().into_bytes(); + writer.write_u8(msg.len() as u8)?; // maximum message size 255 bytes + msg.write(writer)?; + } + }; + + match pd.message_sig { + None => writer.write_u8(0)?, + Some(n) => { + writer.write_u8(n.as_ref().len() as u8)?; + n.write(writer)?; + } + }; + } + + Ok(()) + } +} + +impl Readable for Slate { + + fn read(reader: &mut dyn Reader) -> Result { + + let version_info = VersionCompatInfo { + version: reader.read_u8()? as u16, + orig_version: reader.read_u8()? as u16, + min_compat_version: reader.read_u8()? as u16, + }; + + let num_participants = reader.read_u16()? as usize; + let txid_len = reader.read_u8()? as usize; + let id = reader.read_fixed_bytes(txid_len)?; + let id = str::from_utf8(&id).map_err(|_| ser::Error::CorruptedData)?; + let id = Uuid::parse_str(id).map_err(|_| ser::Error::CorruptedData)?; + + let offset = BlindingFactor::read(reader)?; + + let n_inputs = reader.read_u16()? as usize; + let mut inputs: Vec = Vec::with_capacity(n_inputs); + + for _ in 0..n_inputs { + let features = OutputFeatures::read(reader)?; + let commit = Commitment::read(reader)?; + inputs.push(Input { features, commit }); + } + + let n_outputs = reader.read_u16()? as usize; + let mut outputs: Vec = Vec::with_capacity(n_outputs); + + for _ in 0..n_outputs { + let features = OutputFeatures::read(reader)?; + let commit = Commitment::read(reader)?; + + // Don't use RangeProof::read() because it expects the length as u64 + let mut proof = [0u8; secp::constants::MAX_PROOF_SIZE]; + let plen = reader.read_u16()? as usize; + let p = reader.read_fixed_bytes(plen)?; + proof[..plen].clone_from_slice(&p[..]); + + let output = Output { + features, + commit, + proof: RangeProof { proof, plen }, + }; + outputs.push(output); + } + + let n_kernels = reader.read_u16()? as usize; + let mut kernels: Vec = Vec::with_capacity(n_kernels); + + for _ in 0..n_kernels { + let features = KernelFeatures::read(reader)?; + let fee = reader.read_u64()?; + let lock_height = reader.read_u64()?; + let excess = Commitment::read(reader)?; + let excess_sig = Signature::read(reader)?; + kernels.push(TxKernel { + features, + fee, + lock_height, + excess, + excess_sig, + }); + } + + let tx = Transaction { + offset, + body: TransactionBody { + inputs, + outputs, + kernels, + }, + }; + + let amount = reader.read_u64()?; + let fee = reader.read_u64()?; + let height = reader.read_u64()?; + let lock_height = reader.read_u64()?; + + let n_pdata = reader.read_u16()? as usize; + let mut participant_data: Vec = Vec::with_capacity(n_pdata); + + let s = secp::Secp256k1::with_caps(secp::ContextFlag::None); + + for _ in 0..n_pdata { + let id = reader.read_u8()? as u64; + + let buf = reader.read_fixed_bytes(secp::constants::COMPRESSED_PUBLIC_KEY_SIZE)?; + let public_blind_excess = PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; + + let buf = reader.read_fixed_bytes(secp::constants::COMPRESSED_PUBLIC_KEY_SIZE)?; + let public_nonce = PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; + + // The next u8 should be either 0 for no signature or the size of the signature (should be 64) + let part_sig: Option = match reader.read_u8()? as usize { + 0 => None, + secp::constants::AGG_SIGNATURE_SIZE => Some(Signature::read(reader)?), + _ => return Err(ser::Error::CountError) + }; + + let message: Option = match reader.read_u8()? { + 0 => None, + n => { + let msg = reader.read_fixed_bytes(n as usize)?; + let string = String::from_utf8(msg).map_err(|_| ser::Error::CorruptedData)?; + Some(string) + } + }; + + // The next u8 should be either 0 for no signature or the size of the signature (should be 64) + let message_sig: Option = match reader.read_u8()? as usize { + 0 => None, + secp::constants::AGG_SIGNATURE_SIZE => Some(Signature::read(reader)?), + _ => return Err(ser::Error::CountError) + }; + + participant_data.push(ParticipantData { + id, + public_blind_excess, + public_nonce, + part_sig, + message, + message_sig, + }); + + + } + + Ok(Slate { + version_info, + num_participants, + id, + tx, + amount, + fee, + height, + lock_height, + participant_data, + }) + + + } +} + + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SlateVersionProbe { #[serde(default)] diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index fc2aa3b5b..91daca82b 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -17,15 +17,9 @@ //! Versions earlier than V2 are removed for the 2.0.0 release, but versioning code //! remains for future needs -use crate::error::{Error, ErrorKind}; use crate::slate::Slate; use crate::slate_versions::v2::SlateV2; -use crate::enum_primitive::FromPrimitive; -use crate::grin_util::secp; -use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; -use std::io::{Cursor, Read}; -use std::str; #[allow(missing_docs)] pub mod v2; @@ -74,269 +68,6 @@ impl VersionedSlate { }*/ } } - - /// Encodes a slate into a vec of bytes by serializing the fields in order - /// and prepending variable length fields with their length - pub fn encode(&self) -> Result, Error> { - let slate: &SlateV2 = match self { - VersionedSlate::V2(s) => s, - VersionedSlate::V1(_) => { - return Err(ErrorKind::SlateSer)?; - } - VersionedSlate::V0(_) => { - return Err(ErrorKind::SlateSer)?; - } - }; - let mut buf: Vec = Vec::new(); - - // Save 3 bytes by casting u16 to u8 (should be fine up to slate v255) - buf.push(slate.version_info.version as u8); - buf.push(slate.version_info.orig_version as u8); - buf.push(slate.version_info.min_compat_version as u8); - - buf.write_u16::(slate.num_participants as u16)?; - - let txid = slate.id.to_hyphenated().to_string().into_bytes(); - buf.push(txid.len() as u8); // max 255 bytes long txid - buf.extend(txid); - - buf.extend(slate.tx.offset.as_ref()); - buf.write_u16::(slate.tx.body.inputs.len() as u16)?; - - for input in slate.tx.body.inputs.iter() { - buf.push(input.features as u8); - buf.extend(input.commit.0.iter()) - } - - buf.write_u16::(slate.tx.body.outputs.len() as u16)?; - - for output in slate.tx.body.outputs.iter() { - buf.push(output.features as u8); - - buf.extend(output.commit.0.iter()); - - buf.write_u16::(output.proof.len() as u16)?; - buf.extend(output.proof.bytes().iter()) - } - - buf.write_u16::(slate.tx.body.kernels.len() as u16)?; - - for kernel in slate.tx.body.kernels.iter() { - buf.push(kernel.features as u8); - - buf.write_u64::(kernel.fee)?; - - buf.write_u64::(kernel.lock_height)?; - buf.extend(kernel.excess.0.iter()); - buf.extend(kernel.excess_sig.as_ref()); - } - - buf.write_u64::(slate.amount)?; - buf.write_u64::(slate.fee)?; - buf.write_u64::(slate.height)?; - buf.write_u64::(slate.lock_height)?; - - buf.write_u16::(slate.participant_data.len() as u16)?; - - let s = secp::Secp256k1::new(); - - for pd in slate.participant_data.iter() { - // Save 7 bytes by casting u64 to u8, we only use 1 bit anyway - buf.push(pd.id as u8); - buf.extend(pd.public_blind_excess.serialize_vec(&s, true)); - buf.extend(pd.public_nonce.serialize_vec(&s, true)); - - match pd.part_sig { - None => buf.push(0), - Some(n) => { - buf.push(n.as_ref().len() as u8); - buf.extend(n.as_ref().iter()); - } - }; - - match &pd.message { - None => buf.push(0), - Some(n) => { - let msg = n.clone().into_bytes(); - buf.push(msg.len() as u8); // maximum message size 255 bytes - buf.extend(msg); - } - } - match pd.message_sig { - None => buf.push(0), - Some(n) => { - buf.push(n.as_ref().len() as u8); - buf.extend(n.as_ref().iter()); - } - } - } - Ok(buf) - } - - /// Deserialize raw bytes to a v2 VersionedSlate - pub fn from_bytes(data: Vec) -> Result { - let mut rdr = Cursor::new(data); - - let version_info = v2::VersionCompatInfoV2 { - version: rdr.read_u8()? as u16, - orig_version: rdr.read_u8()? as u16, - min_compat_version: rdr.read_u8()? as u16, - }; - - let num_participants = rdr.read_u16::()? as usize; - let txid_len = rdr.read_u8()? as usize; - let mut id = [0u8; 255]; - rdr.read_exact(&mut id[..txid_len])?; - let id = str::from_utf8(&id[..txid_len]).map_err(|_| ErrorKind::SlateDeser)?; - let id = v2::Uuid::parse_str(id).map_err(|_| ErrorKind::SlateDeser)?; - - let mut offset = [0u8; 32]; - rdr.read_exact(&mut offset)?; - let offset = v2::BlindingFactor::from_slice(&offset); - - let n_inputs = rdr.read_u16::()? as usize; - let mut inputs: Vec = Vec::with_capacity(n_inputs); - - for _ in 0..n_inputs { - let features = - v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; - let mut commit = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; - rdr.read_exact(&mut commit)?; - let commit = v2::Commitment(commit); - inputs.push(v2::InputV2 { features, commit }); - } - - let n_outputs = rdr.read_u16::()? as usize; - let mut outputs: Vec = Vec::with_capacity(n_outputs); - - for _ in 0..n_outputs { - let features = - v2::OutputFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; - let mut commit = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; - rdr.read_exact(&mut commit)?; - let commit = v2::Commitment(commit); - let mut proof = [0u8; secp::constants::MAX_PROOF_SIZE]; - let plen = rdr.read_u16::()? as usize; - rdr.read_exact(&mut proof[..plen])?; - - let output = v2::OutputV2 { - features, - commit, - proof: v2::RangeProof { proof, plen }, - }; - outputs.push(output); - } - - let n_kernels = rdr.read_u16::()? as usize; - let mut kernels: Vec = Vec::with_capacity(n_kernels); - - for _ in 0..n_kernels { - let features = - v2::KernelFeatures::from_u8(rdr.read_u8()?).ok_or_else(|| ErrorKind::SlateDeser)?; - let fee = rdr.read_u64::()?; - let lock_height = rdr.read_u64::()?; - - let mut excess = [0u8; secp::constants::PEDERSEN_COMMITMENT_SIZE]; - rdr.read_exact(&mut excess)?; - let excess = v2::Commitment(excess); - - let mut excess_sig = [0u8; secp::constants::COMPACT_SIGNATURE_SIZE]; - rdr.read_exact(&mut excess_sig)?; - let excess_sig = v2::Signature::from_raw_data(&excess_sig)?; - - kernels.push(v2::TxKernelV2 { - features, - fee, - lock_height, - excess, - excess_sig, - }); - } - - let tx = v2::TransactionV2 { - offset, - body: v2::TransactionBodyV2 { - inputs, - outputs, - kernels, - }, - }; - - let amount = rdr.read_u64::()?; - let fee = rdr.read_u64::()?; - let height = rdr.read_u64::()?; - let lock_height = rdr.read_u64::()?; - - let pdata_len = rdr.read_u16::()? as usize; - let mut participant_data: Vec = Vec::with_capacity(pdata_len); - - let s = secp::Secp256k1::new(); - - for _ in 0..pdata_len { - let id = rdr.read_u8()? as u64; - - let mut public_blind_excess = [0u8; secp::constants::COMPRESSED_PUBLIC_KEY_SIZE]; - rdr.read_exact(&mut public_blind_excess)?; - let public_blind_excess = v2::PublicKey::from_slice(&s, &public_blind_excess)?; - - let mut public_nonce = [0u8; secp::constants::COMPRESSED_PUBLIC_KEY_SIZE]; - rdr.read_exact(&mut public_nonce)?; - let public_nonce = v2::PublicKey::from_slice(&s, &public_nonce)?; - - let part_sig: Option = match rdr.read_u8()? { - 0 => None, - _ => { - let mut sig = [0u8; 64]; - rdr.read_exact(&mut sig)?; - Some(v2::Signature::from_raw_data(&sig)?) - } - }; - - let message: Option = match rdr.read_u8()? { - 0 => None, - n => { - let n = n as usize; - let mut msg = [0u8; 255]; - rdr.read_exact(&mut msg[..n])?; - let string = - String::from_utf8(msg[..n].to_vec()).map_err(|_| ErrorKind::SlateDeser)?; - Some(string) - } - }; - - let message_sig: Option = match rdr.read_u8()? { - 0 => None, - _ => { - let mut sig = [0u8; 64]; - rdr.read_exact(&mut sig)?; - Some(v2::Signature::from_raw_data(&sig)?) - } - }; - - participant_data.push(v2::ParticipantDataV2 { - id, - public_blind_excess, - public_nonce, - part_sig, - message, - message_sig, - }); - } - - let slate = v2::SlateV2 { - version_info, - num_participants, - id, - tx, - amount, - fee, - height, - lock_height, - participant_data, - }; - - Ok(VersionedSlate::V2(slate)) - } } impl From for Slate { diff --git a/libwallet/src/slate_versions/v2.rs b/libwallet/src/slate_versions/v2.rs index f200a1df1..b339c4943 100644 --- a/libwallet/src/slate_versions/v2.rs +++ b/libwallet/src/slate_versions/v2.rs @@ -35,15 +35,15 @@ //! orig_version: u16, //! block_header_version: u16, -pub use crate::grin_core::core::transaction::{KernelFeatures, OutputFeatures}; +use crate::grin_core::core::transaction::{KernelFeatures, OutputFeatures}; use crate::grin_core::libtx::secp_ser; use crate::grin_core::map_vec; -pub use crate::grin_keychain::BlindingFactor; +use crate::grin_keychain::BlindingFactor; use crate::grin_util::secp; -pub use crate::grin_util::secp::key::PublicKey; -pub use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; -pub use crate::grin_util::secp::Signature; -pub use uuid::Uuid; +use crate::grin_util::secp::key::PublicKey; +use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; +use crate::grin_util::secp::Signature; +use uuid::Uuid; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SlateV2 { From 2a78450354204cf51f0b8012e41a252b2590e434 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Fri, 24 May 2019 17:54:13 +0100 Subject: [PATCH 11/16] rustfmt --- libwallet/src/slate.rs | 52 ++++++++++++----------------- libwallet/src/slate_versions/mod.rs | 1 - 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index 29e76c94f..b6c88b2f6 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -20,14 +20,14 @@ use crate::error::{Error, ErrorKind}; use crate::grin_core::core::amount_to_hr_string; use crate::grin_core::core::committed::Committed; use crate::grin_core::core::transaction::{ - kernel_features, kernel_sig_msg, Input, Output, Transaction, TransactionBody, TxKernel, - Weighting, OutputFeatures, KernelFeatures + kernel_features, kernel_sig_msg, Input, KernelFeatures, Output, OutputFeatures, Transaction, + TransactionBody, TxKernel, Weighting, }; -use crate::grin_core::ser; -use crate::grin_core::ser::{Readable, Writeable, Writer, Reader}; use crate::grin_core::core::verifier_cache::LruVerifierCache; use crate::grin_core::libtx::{aggsig, build, secp_ser, tx_fee}; use crate::grin_core::map_vec; +use crate::grin_core::ser; +use crate::grin_core::ser::{Readable, Reader, Writeable, Writer}; use crate::grin_keychain::{BlindSum, BlindingFactor, Keychain}; use crate::grin_util::secp::key::{PublicKey, SecretKey}; use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; @@ -704,9 +704,7 @@ impl Serialize for Slate { } impl Writeable for Slate { - fn write(&self, writer: &mut W) -> Result<(), ser::Error> { - // Save 3 bytes by casting u16 to u8 (should be fine up to slate v255) writer.write_u8(self.version_info.version as u8)?; writer.write_u8(self.version_info.orig_version as u8)?; @@ -715,24 +713,24 @@ impl Writeable for Slate { writer.write_u16(self.num_participants as u16)?; let txid = self.id.to_hyphenated().to_string().into_bytes(); - writer.write_u8(txid.len() as u8)?; // max 255 bytes long txid + writer.write_u8(txid.len() as u8)?; // max 255 bytes long txid writer.write_fixed_bytes(&txid)?; writer.write_fixed_bytes(&self.tx.offset)?; - + writer.write_u16(self.tx.body.inputs.len() as u16)?; - + for input in self.tx.body.inputs.iter() { writer.write_u8(input.features as u8)?; input.commit.write(writer)?; - } + } writer.write_u16(self.tx.body.outputs.len() as u16)?; for output in self.tx.body.outputs.iter() { writer.write_u8(output.features as u8)?; writer.write_fixed_bytes(&output.commit)?; - + // Don't use RangeProof::write() because it encodes length as u64 writer.write_u16(output.proof.len() as u16)?; writer.write_fixed_bytes(&output.proof)?; @@ -746,8 +744,7 @@ impl Writeable for Slate { writer.write_u64(kernel.lock_height)?; kernel.excess.write(writer)?; kernel.excess_sig.write(writer)?; - - } + } writer.write_u64(self.amount)?; writer.write_u64(self.fee)?; @@ -776,7 +773,7 @@ impl Writeable for Slate { None => writer.write_u8(0)?, Some(n) => { let msg = n.clone().into_bytes(); - writer.write_u8(msg.len() as u8)?; // maximum message size 255 bytes + writer.write_u8(msg.len() as u8)?; // maximum message size 255 bytes msg.write(writer)?; } }; @@ -788,21 +785,19 @@ impl Writeable for Slate { n.write(writer)?; } }; - } + } Ok(()) - } + } } impl Readable for Slate { - fn read(reader: &mut dyn Reader) -> Result { - let version_info = VersionCompatInfo { version: reader.read_u8()? as u16, orig_version: reader.read_u8()? as u16, min_compat_version: reader.read_u8()? as u16, - }; + }; let num_participants = reader.read_u16()? as usize; let txid_len = reader.read_u8()? as usize; @@ -845,7 +840,7 @@ impl Readable for Slate { let n_kernels = reader.read_u16()? as usize; let mut kernels: Vec = Vec::with_capacity(n_kernels); - for _ in 0..n_kernels { + for _ in 0..n_kernels { let features = KernelFeatures::read(reader)?; let fee = reader.read_u64()?; let lock_height = reader.read_u64()?; @@ -883,16 +878,18 @@ impl Readable for Slate { let id = reader.read_u8()? as u64; let buf = reader.read_fixed_bytes(secp::constants::COMPRESSED_PUBLIC_KEY_SIZE)?; - let public_blind_excess = PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; + let public_blind_excess = + PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; let buf = reader.read_fixed_bytes(secp::constants::COMPRESSED_PUBLIC_KEY_SIZE)?; - let public_nonce = PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; + let public_nonce = + PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; // The next u8 should be either 0 for no signature or the size of the signature (should be 64) let part_sig: Option = match reader.read_u8()? as usize { 0 => None, secp::constants::AGG_SIGNATURE_SIZE => Some(Signature::read(reader)?), - _ => return Err(ser::Error::CountError) + _ => return Err(ser::Error::CountError), }; let message: Option = match reader.read_u8()? { @@ -908,7 +905,7 @@ impl Readable for Slate { let message_sig: Option = match reader.read_u8()? as usize { 0 => None, secp::constants::AGG_SIGNATURE_SIZE => Some(Signature::read(reader)?), - _ => return Err(ser::Error::CountError) + _ => return Err(ser::Error::CountError), }; participant_data.push(ParticipantData { @@ -918,9 +915,7 @@ impl Readable for Slate { part_sig, message, message_sig, - }); - - + }); } Ok(Slate { @@ -934,12 +929,9 @@ impl Readable for Slate { lock_height, participant_data, }) - - } } - #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SlateVersionProbe { #[serde(default)] diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index 91daca82b..76484cf99 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -20,7 +20,6 @@ use crate::slate::Slate; use crate::slate_versions::v2::SlateV2; - #[allow(missing_docs)] pub mod v2; From 4e5d6f947a0999d60876d0e7fb6565265e624b20 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Fri, 24 May 2019 18:42:02 +0100 Subject: [PATCH 12/16] fix tests --- src/bin/cmd/wallet_tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bin/cmd/wallet_tests.rs b/src/bin/cmd/wallet_tests.rs index 69aa3460a..59359471a 100644 --- a/src/bin/cmd/wallet_tests.rs +++ b/src/bin/cmd/wallet_tests.rs @@ -487,6 +487,8 @@ mod wallet_tests { "-p", "password", "invoice", + "-m", + "file", "-d", &file_name, "-g", @@ -504,6 +506,8 @@ mod wallet_tests { "-p", "password", "pay", + "-m", + "file", "-i", &file_name, "-d", From 46ec60f51a6ea93a9654d3ef9f2024051579b860 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Wed, 12 Jun 2019 16:39:23 +0100 Subject: [PATCH 13/16] rebase on milestone/2.0.0 and fix conflicts --- Cargo.lock | 20 ++++++++++++++++++++ libwallet/Cargo.toml | 2 ++ libwallet/src/lib.rs | 2 +- libwallet/src/slate.rs | 4 ++-- libwallet/src/slate_versions/v2.rs | 1 - src/bin/cmd/wallet_args.rs | 4 +--- 6 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3efa9f310..9f817ae16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -876,6 +876,8 @@ dependencies = [ "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2100,6 +2102,22 @@ name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strum" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum_macros" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "supercow" version = "0.1.0" @@ -2924,6 +2942,8 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0bbfb8937e38e34c3444ff00afb28b0811d9554f15c5ad64d12b0308d1d1995" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1c33039533f051704951680f1adfd468fd37ac46816ded0d9ee068e60f05f" +"checksum strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47cd23f5c7dee395a00fa20135e2ec0fffcdfa151c56182966d7a3261343432e" "checksum supercow 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63" "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index bb7759850..18ac86ae8 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -22,6 +22,8 @@ log = "0.4" uuid = { version = "0.7", features = ["serde", "v4"] } chrono = { version = "0.4.4", features = ["serde"] } lazy_static = "1" +strum = "0.15" +strum_macros = "0.15" grin_wallet_util = { path = "../util", version = "2.0.0-beta.1" } diff --git a/libwallet/src/lib.rs b/libwallet/src/lib.rs index b5a747b80..291737f28 100644 --- a/libwallet/src/lib.rs +++ b/libwallet/src/lib.rs @@ -38,8 +38,8 @@ extern crate serde_derive; extern crate log; #[macro_use] extern crate lazy_static; - extern crate strum; + #[macro_use] extern crate strum_macros; diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index b6c88b2f6..83d53d0e1 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -708,7 +708,7 @@ impl Writeable for Slate { // Save 3 bytes by casting u16 to u8 (should be fine up to slate v255) writer.write_u8(self.version_info.version as u8)?; writer.write_u8(self.version_info.orig_version as u8)?; - writer.write_u8(self.version_info.min_compat_version as u8)?; + writer.write_u8(self.version_info.block_header_version as u8)?; writer.write_u16(self.num_participants as u16)?; @@ -796,7 +796,7 @@ impl Readable for Slate { let version_info = VersionCompatInfo { version: reader.read_u8()? as u16, orig_version: reader.read_u8()? as u16, - min_compat_version: reader.read_u8()? as u16, + block_header_version: reader.read_u8()? as u16, }; let num_participants = reader.read_u16()? as usize; diff --git a/libwallet/src/slate_versions/v2.rs b/libwallet/src/slate_versions/v2.rs index b339c4943..336fb896d 100644 --- a/libwallet/src/slate_versions/v2.rs +++ b/libwallet/src/slate_versions/v2.rs @@ -37,7 +37,6 @@ use crate::grin_core::core::transaction::{KernelFeatures, OutputFeatures}; use crate::grin_core::libtx::secp_ser; -use crate::grin_core::map_vec; use crate::grin_keychain::BlindingFactor; use crate::grin_util::secp; use crate::grin_util::secp::key::PublicKey; diff --git a/src/bin/cmd/wallet_args.rs b/src/bin/cmd/wallet_args.rs index 28d6d1cf8..81e1fa967 100644 --- a/src/bin/cmd/wallet_args.rs +++ b/src/bin/cmd/wallet_args.rs @@ -24,7 +24,7 @@ use grin_wallet_controller::{Error, ErrorKind}; use grin_wallet_impls::{ instantiate_wallet, FileWalletCommAdapter, StdioWalletCommAdapter, WalletSeed, }; -use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, Slate, WalletInst}; +use grin_wallet_libwallet::{IssueInvoiceTxArgs, NodeClient, WalletInst}; use grin_wallet_util::grin_core as core; use grin_wallet_util::grin_keychain as keychain; use linefeed::terminal::Signal; @@ -35,8 +35,6 @@ use std::sync::Arc; // shut up test compilation warnings #[cfg(not(test))] -use grin_wallet_impls::FileWalletCommAdapter; -#[cfg(not(test))] use grin_wallet_libwallet::Slate; #[cfg(not(test))] use grin_wallet_util::grin_core::core::amount_to_hr_string; From f47e6ee01d95f46b3990d204344fdafbdeaf2ebc Mon Sep 17 00:00:00 2001 From: mcdallas Date: Thu, 13 Jun 2019 15:49:55 +0100 Subject: [PATCH 14/16] use PublicKey::read/write --- libwallet/src/slate.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index 83d53d0e1..c5c79fef0 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -753,13 +753,11 @@ impl Writeable for Slate { writer.write_u16(self.participant_data.len() as u16)?; - let s = secp::Secp256k1::new(); - for pd in self.participant_data.iter() { // Save 7 bytes by casting u64 to u8, we only use 1 bit anyway writer.write_u8(pd.id as u8)?; - writer.write_fixed_bytes(&pd.public_blind_excess.serialize_vec(&s, true).as_ref())?; - writer.write_fixed_bytes(&pd.public_nonce.serialize_vec(&s, true).as_ref())?; + pd.public_blind_excess.write(writer)?; + pd.public_nonce.write(writer)?; match pd.part_sig { None => writer.write_u8(0)?, @@ -872,18 +870,12 @@ impl Readable for Slate { let n_pdata = reader.read_u16()? as usize; let mut participant_data: Vec = Vec::with_capacity(n_pdata); - let s = secp::Secp256k1::with_caps(secp::ContextFlag::None); for _ in 0..n_pdata { let id = reader.read_u8()? as u64; - let buf = reader.read_fixed_bytes(secp::constants::COMPRESSED_PUBLIC_KEY_SIZE)?; - let public_blind_excess = - PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; - - let buf = reader.read_fixed_bytes(secp::constants::COMPRESSED_PUBLIC_KEY_SIZE)?; - let public_nonce = - PublicKey::from_slice(&s, &buf).map_err(|_| ser::Error::CorruptedData)?; + let public_blind_excess = PublicKey::read(reader)?; + let public_nonce = PublicKey::read(reader)?; // The next u8 should be either 0 for no signature or the size of the signature (should be 64) let part_sig: Option = match reader.read_u8()? as usize { From c81baf132755678db5973b23168e525103bfb503 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Thu, 13 Jun 2019 17:14:28 +0100 Subject: [PATCH 15/16] use compact encoding for signatures instead of raw bytes --- libwallet/src/slate.rs | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index c5c79fef0..c17e435cf 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -753,17 +753,21 @@ impl Writeable for Slate { writer.write_u16(self.participant_data.len() as u16)?; + let s = secp::Secp256k1::with_caps(secp::ContextFlag::None); + for pd in self.participant_data.iter() { // Save 7 bytes by casting u64 to u8, we only use 1 bit anyway writer.write_u8(pd.id as u8)?; pd.public_blind_excess.write(writer)?; pd.public_nonce.write(writer)?; + match pd.part_sig { None => writer.write_u8(0)?, - Some(n) => { - writer.write_u8(n.as_ref().len() as u8)?; - n.write(writer)?; + Some(sig) => { + let serialized_sig = sig.serialize_compact(&s); + writer.write_u8(serialized_sig.len() as u8)?; + writer.write_fixed_bytes(&serialized_sig.as_ref())?; } }; @@ -778,9 +782,10 @@ impl Writeable for Slate { match pd.message_sig { None => writer.write_u8(0)?, - Some(n) => { - writer.write_u8(n.as_ref().len() as u8)?; - n.write(writer)?; + Some(sig) => { + let serialized_sig = sig.serialize_compact(&s); + writer.write_u8(serialized_sig.len() as u8)?; + writer.write_fixed_bytes(&serialized_sig.as_ref())?; } }; } @@ -870,6 +875,7 @@ impl Readable for Slate { let n_pdata = reader.read_u16()? as usize; let mut participant_data: Vec = Vec::with_capacity(n_pdata); + let s = secp::Secp256k1::with_caps(secp::ContextFlag::None); for _ in 0..n_pdata { let id = reader.read_u8()? as u64; @@ -880,7 +886,11 @@ impl Readable for Slate { // The next u8 should be either 0 for no signature or the size of the signature (should be 64) let part_sig: Option = match reader.read_u8()? as usize { 0 => None, - secp::constants::AGG_SIGNATURE_SIZE => Some(Signature::read(reader)?), + secp::constants::AGG_SIGNATURE_SIZE => { + let bytes = reader.read_fixed_bytes(secp::constants::AGG_SIGNATURE_SIZE as usize)?; + let sig = Signature::from_compact(&s, &bytes).map_err(|_| ser::Error::CorruptedData)?; + Some(sig) + }, _ => return Err(ser::Error::CountError), }; @@ -896,7 +906,11 @@ impl Readable for Slate { // The next u8 should be either 0 for no signature or the size of the signature (should be 64) let message_sig: Option = match reader.read_u8()? as usize { 0 => None, - secp::constants::AGG_SIGNATURE_SIZE => Some(Signature::read(reader)?), + secp::constants::AGG_SIGNATURE_SIZE => { + let bytes = reader.read_fixed_bytes(secp::constants::AGG_SIGNATURE_SIZE as usize)?; + let sig = Signature::from_compact(&s, &bytes).map_err(|_| ser::Error::CorruptedData)?; + Some(sig) + }, _ => return Err(ser::Error::CountError), }; From 92c361f4f0d9ad29243879af606fd6e97327ffa7 Mon Sep 17 00:00:00 2001 From: mcdallas Date: Thu, 13 Jun 2019 17:15:02 +0100 Subject: [PATCH 16/16] rustfmt --- libwallet/src/slate.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index c17e435cf..f187c955c 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -761,7 +761,6 @@ impl Writeable for Slate { pd.public_blind_excess.write(writer)?; pd.public_nonce.write(writer)?; - match pd.part_sig { None => writer.write_u8(0)?, Some(sig) => { @@ -887,10 +886,12 @@ impl Readable for Slate { let part_sig: Option = match reader.read_u8()? as usize { 0 => None, secp::constants::AGG_SIGNATURE_SIZE => { - let bytes = reader.read_fixed_bytes(secp::constants::AGG_SIGNATURE_SIZE as usize)?; - let sig = Signature::from_compact(&s, &bytes).map_err(|_| ser::Error::CorruptedData)?; - Some(sig) - }, + let bytes = + reader.read_fixed_bytes(secp::constants::AGG_SIGNATURE_SIZE as usize)?; + let sig = Signature::from_compact(&s, &bytes) + .map_err(|_| ser::Error::CorruptedData)?; + Some(sig) + } _ => return Err(ser::Error::CountError), }; @@ -907,10 +908,12 @@ impl Readable for Slate { let message_sig: Option = match reader.read_u8()? as usize { 0 => None, secp::constants::AGG_SIGNATURE_SIZE => { - let bytes = reader.read_fixed_bytes(secp::constants::AGG_SIGNATURE_SIZE as usize)?; - let sig = Signature::from_compact(&s, &bytes).map_err(|_| ser::Error::CorruptedData)?; + let bytes = + reader.read_fixed_bytes(secp::constants::AGG_SIGNATURE_SIZE as usize)?; + let sig = Signature::from_compact(&s, &bytes) + .map_err(|_| ser::Error::CorruptedData)?; Some(sig) - }, + } _ => return Err(ser::Error::CountError), };