From 86e6f511c39ed7ef1f4b4fb17754133eb1c8c002 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Wed, 4 Dec 2019 11:52:42 +0000 Subject: [PATCH] V2 Slate Compatibility (#272) * re-insert v2 slate * reinstate version conversions * rustfmt * add and test versioning checks against 2.0.0 wallets * rustfmt * fix to invoice file output * doctest fix * remove target slate version from command line options --- api/src/foreign_rpc.rs | 6 +- controller/src/command.rs | 4 +- controller/src/controller.rs | 7 +- impls/src/adapters/file.rs | 16 +- impls/src/adapters/http.rs | 35 +++- libwallet/src/slate.rs | 20 +- libwallet/src/slate_versions/mod.rs | 32 +-- libwallet/src/slate_versions/v2.rs | 214 ++++++++++++++++++++ libwallet/src/slate_versions/v3.rs | 301 ++++++++++++++++++++++++++++ src/bin/grin-wallet.yml | 10 - 10 files changed, 591 insertions(+), 54 deletions(-) create mode 100644 libwallet/src/slate_versions/v2.rs diff --git a/api/src/foreign_rpc.rs b/api/src/foreign_rpc.rs index 28e18241..790b53b1 100644 --- a/api/src/foreign_rpc.rs +++ b/api/src/foreign_rpc.rs @@ -53,7 +53,8 @@ pub trait ForeignRpc { "Ok": { "foreign_api_version": 2, "supported_slate_versions": [ - "V3" + "V3", + "V2" ] } } @@ -553,9 +554,10 @@ where message: Option, ) -> Result { let version = in_slate.version(); + let slate_from = Slate::from(in_slate); let out_slate = Foreign::receive_tx( self, - &Slate::from(in_slate), + &slate_from, dest_acct_name.as_ref().map(String::as_str), message, ) diff --git a/controller/src/command.rs b/controller/src/command.rs index afc848b4..d189b32a 100644 --- a/controller/src/command.rs +++ b/controller/src/command.rs @@ -513,9 +513,7 @@ where { controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| { let slate = api.issue_invoice_tx(m, 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()?; + PathToSlate((&args.dest).into()).put_tx(&slate)?; Ok(()) })?; Ok(()) diff --git a/controller/src/controller.rs b/controller/src/controller.rs index 153320bf..a57b18bb 100644 --- a/controller/src/controller.rs +++ b/controller/src/controller.rs @@ -19,7 +19,7 @@ use crate::config::TorConfig; use crate::keychain::Keychain; use crate::libwallet::{ address, Error, ErrorKind, NodeClient, NodeVersionInfo, Slate, WalletInst, WalletLCProvider, - CURRENT_SLATE_VERSION, GRIN_BLOCK_HEADER_VERSION, + GRIN_BLOCK_HEADER_VERSION, }; use crate::util::secp::key::SecretKey; use crate::util::{from_hex, static_secp_instance, to_base64, Mutex}; @@ -63,10 +63,7 @@ fn check_middleware( bhv = n.block_header_version; } if let Some(s) = slate { - if s.version_info.version < CURRENT_SLATE_VERSION -// || (bhv == 3 && s.version_info.block_header_version != 3) - || (bhv > 3 && s.version_info.block_header_version < GRIN_BLOCK_HEADER_VERSION) - { + if bhv > 3 && s.version_info.block_header_version < GRIN_BLOCK_HEADER_VERSION { Err(ErrorKind::Compatibility( "Incoming Slate is not compatible with this wallet. \ Please upgrade the node or use a different one." diff --git a/impls/src/adapters/file.rs b/impls/src/adapters/file.rs index 95a2861f..d7a0e343 100644 --- a/impls/src/adapters/file.rs +++ b/impls/src/adapters/file.rs @@ -16,7 +16,7 @@ use std::fs::File; use std::io::{Read, Write}; -use crate::libwallet::{Error, ErrorKind, Slate}; +use crate::libwallet::{Error, ErrorKind, Slate, SlateVersion, VersionedSlate}; use crate::{SlateGetter, SlatePutter}; use std::path::PathBuf; @@ -26,8 +26,20 @@ pub struct PathToSlate(pub PathBuf); impl SlatePutter for PathToSlate { fn put_tx(&self, slate: &Slate) -> Result<(), Error> { let mut pub_tx = File::create(&self.0)?; + let out_slate = { + if slate.payment_proof.is_some() || slate.ttl_cutoff_height.is_some() { + warn!("Transaction contains features that require grin-wallet 3.0.0 or later"); + warn!("Please ensure the other party is running grin-wallet v3.0.0 or later before sending"); + VersionedSlate::into_version(slate.clone(), SlateVersion::V3) + } else { + let mut s = slate.clone(); + s.version_info.version = 2; + s.version_info.orig_version = 2; + VersionedSlate::into_version(s, SlateVersion::V2) + } + }; pub_tx.write_all( - serde_json::to_string(slate) + serde_json::to_string(&out_slate) .map_err(|_| ErrorKind::SlateSer)? .as_bytes(), )?; diff --git a/impls/src/adapters/http.rs b/impls/src/adapters/http.rs index 15d9b837..e456ff0b 100644 --- a/impls/src/adapters/http.rs +++ b/impls/src/adapters/http.rs @@ -14,6 +14,7 @@ /// HTTP Wallet 'plugin' implementation use crate::client_utils::{Client, ClientError}; +use crate::libwallet::slate_versions::{SlateVersion, VersionedSlate}; use crate::libwallet::{Error, ErrorKind, Slate}; use crate::SlateSender; use serde::Serialize; @@ -64,7 +65,7 @@ impl HttpSlateSender { } /// Check version of the listening wallet - fn check_other_version(&self, url: &str) -> Result<(), Error> { + fn check_other_version(&self, url: &str) -> Result { let req = json!({ "jsonrpc": "2.0", "method": "check_version", @@ -111,13 +112,16 @@ impl HttpSlateSender { return Err(ErrorKind::ClientCallback(report).into()); } - if !supported_slate_versions.contains(&"V3".to_owned()) { - let report = format!("Unable to negotiate slate format with other wallet."); - error!("{}", report); - return Err(ErrorKind::ClientCallback(report).into()); + if supported_slate_versions.contains(&"V3".to_owned()) { + return Ok(SlateVersion::V3); + } + if supported_slate_versions.contains(&"V2".to_owned()) { + return Ok(SlateVersion::V2); } - Ok(()) + let report = format!("Unable to negotiate slate format with other wallet."); + error!("{}", report); + Err(ErrorKind::ClientCallback(report).into()) } fn post( @@ -173,15 +177,28 @@ impl SlateSender for HttpSlateSender { .map_err(|e| ErrorKind::TorProcess(format!("{:?}", e).into()))?; } - self.check_other_version(&url_str)?; - + let slate_send = match self.check_other_version(&url_str)? { + SlateVersion::V3 => VersionedSlate::into_version(slate.clone(), SlateVersion::V3), + SlateVersion::V2 => { + let mut slate = slate.clone(); + if let Some(_) = slate.payment_proof { + return Err(ErrorKind::ClientCallback("Payment proof requested, but other wallet does not support payment proofs. Please urge other user to upgrade, or re-send tx without a payment proof".into()).into()); + } + if let Some(_) = slate.ttl_cutoff_height { + warn!("Slate TTL value will be ignored and removed by other wallet, as other wallet does not support this feature. Please urge other user to upgrade"); + } + slate.version_info.version = 2; + slate.version_info.orig_version = 2; + VersionedSlate::into_version(slate, SlateVersion::V2) + } + }; // Note: not using easy-jsonrpc as don't want the dependencies in this crate let req = json!({ "jsonrpc": "2.0", "method": "receive_tx", "id": 1, "params": [ - slate, + slate_send, null, null ] diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index c5a08373..1e62457a 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -42,6 +42,7 @@ use std::fmt; use std::sync::Arc; use uuid::Uuid; +use crate::slate_versions::v2::SlateV2; use crate::slate_versions::v3::{ CoinbaseV3, InputV3, OutputV3, ParticipantDataV3, PaymentInfoV3, SlateV3, TransactionBodyV3, TransactionV3, TxKernelV3, VersionCompatInfoV3, @@ -232,13 +233,11 @@ impl Slate { let version = Slate::parse_slate_version(slate_json)?; let v3: SlateV3 = match version { 3 => serde_json::from_str(slate_json).context(ErrorKind::SlateDeser)?, - // left as a reminder - /*0 => { - let v0: SlateV0 = + 2 => { + let v2: SlateV2 = serde_json::from_str(slate_json).context(ErrorKind::SlateDeser)?; - let v1 = SlateV1::from(v0); - SlateV3::from(v1) - }*/ + SlateV3::from(v2) + } _ => return Err(ErrorKind::SlateVersion(version).into()), }; Ok(v3.into()) @@ -728,11 +727,10 @@ impl Serialize for Slate { match self.version_info.orig_version { 3 => v3.serialize(serializer), // left as a reminder - /*0 => { - let v1 = SlateV1::from(v2); - let v0 = SlateV0::from(v1); - v0.serialize(serializer) - }*/ + 2 => { + let v2 = SlateV2::from(&v3); + v2.serialize(serializer) + } v => Err(S::Error::custom(format!("Unknown slate version {}", v))), } } diff --git a/libwallet/src/slate_versions/mod.rs b/libwallet/src/slate_versions/mod.rs index 89f2857f..aa2a5068 100644 --- a/libwallet/src/slate_versions/mod.rs +++ b/libwallet/src/slate_versions/mod.rs @@ -18,11 +18,14 @@ //! remains for future needs use crate::slate::Slate; +use crate::slate_versions::v2::{CoinbaseV2, SlateV2}; use crate::slate_versions::v3::{CoinbaseV3, SlateV3}; use crate::types::CbData; pub mod ser; +#[allow(missing_docs)] +pub mod v2; #[allow(missing_docs)] pub mod v3; @@ -37,6 +40,8 @@ pub const GRIN_BLOCK_HEADER_VERSION: u16 = 3; pub enum SlateVersion { /// V3 (most current) V3, + /// V2 (2.0.0 - Onwards) + V2, } #[derive(Debug, Serialize, Deserialize)] @@ -46,6 +51,8 @@ pub enum SlateVersion { pub enum VersionedSlate { /// Current (3.0.0 Onwards ) V3(SlateV3), + /// V2 (2.0.0 - Onwards) + V2(SlateV2), } impl VersionedSlate { @@ -53,6 +60,7 @@ impl VersionedSlate { pub fn version(&self) -> SlateVersion { match *self { VersionedSlate::V3(_) => SlateVersion::V3, + VersionedSlate::V2(_) => SlateVersion::V2, } } @@ -62,12 +70,11 @@ impl VersionedSlate { SlateVersion::V3 => VersionedSlate::V3(slate.into()), // Left here as a reminder of what needs to be inserted on // the release of a new slate - /*SlateVersion::V0 => { + SlateVersion::V2 => { let s = SlateV3::from(slate); - let s = SlateV1::from(s); - let s = SlateV0::from(s); - VersionedSlate::V0(s) - }*/ + let s = SlateV2::from(&s); + VersionedSlate::V2(s) + } } } } @@ -78,13 +85,11 @@ impl From for Slate { VersionedSlate::V3(s) => { let s = SlateV3::from(s); Slate::from(s) - } // Again, left in as a reminder - /*VersionedSlate::V0(s) => { - let s = SlateV0::from(s); - let s = SlateV1::from(s); - let s = SlateV2::from(s); - Slate::from(s) - }*/ + } + VersionedSlate::V2(s) => { + let s = SlateV3::from(s); + Slate::from(s) + } } } } @@ -96,6 +101,8 @@ impl From for Slate { pub enum VersionedCoinbase { /// Current supported coinbase version. V3(CoinbaseV3), + /// Previous + V2(CoinbaseV2), } impl VersionedCoinbase { @@ -103,6 +110,7 @@ impl VersionedCoinbase { pub fn into_version(cb: CbData, version: SlateVersion) -> VersionedCoinbase { match version { SlateVersion::V3 => VersionedCoinbase::V3(cb.into()), + SlateVersion::V2 => VersionedCoinbase::V2(cb.into()), } } } diff --git a/libwallet/src/slate_versions/v2.rs b/libwallet/src/slate_versions/v2.rs new file mode 100644 index 00000000..e62939b1 --- /dev/null +++ b/libwallet/src/slate_versions/v2.rs @@ -0,0 +1,214 @@ +// Copyright 2019 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. + +//! Contains V2 of the slate (grin-wallet 1.1.0) +//! Changes from V1: +//! * ParticipantData struct fields serialized as hex strings instead of arrays: +//! * public_blind_excess +//! * public_nonce +//! * part_sig +//! * message_sig +//! * Transaction fields serialized as hex strings instead of arrays: +//! * offset +//! * Input field serialized as hex strings instead of arrays: +//! commit +//! * Output fields serialized as hex strings instead of arrays: +//! commit +//! proof +//! * TxKernel fields serialized as hex strings instead of arrays: +//! commit +//! signature +//! * version field removed +//! * VersionCompatInfo struct created with fields and added to beginning of struct +//! version: u16 +//! orig_version: u16, +//! block_header_version: u16, + +use crate::grin_core::core::transaction::OutputFeatures; +use crate::grin_core::libtx::secp_ser; +use crate::grin_keychain::{BlindingFactor, Identifier}; +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 crate::slate::CompatKernelFeatures; +use crate::slate_versions::v3::{OutputV3, TxKernelV3}; +use crate::types::CbData; +use uuid::Uuid; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct SlateV2 { + /// Versioning info + pub version_info: VersionCompatInfoV2, + /// The number of participants intended to take part in this transaction + pub num_participants: usize, + /// Unique transaction ID, selected by sender + pub id: Uuid, + /// The core transaction data: + /// inputs, outputs, kernels, kernel offset + pub tx: TransactionV2, + /// base amount (excluding fee) + #[serde(with = "secp_ser::string_or_u64")] + pub amount: u64, + /// fee amount + #[serde(with = "secp_ser::string_or_u64")] + pub fee: u64, + /// Block height for the transaction + #[serde(with = "secp_ser::string_or_u64")] + pub height: u64, + /// Lock height + #[serde(with = "secp_ser::string_or_u64")] + pub lock_height: u64, + /// Participant data, each participant in the transaction will + /// insert their public data here. For now, 0 is sender and 1 + /// is receiver, though this will change for multi-party + pub participant_data: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VersionCompatInfoV2 { + /// The current version of the slate format + pub version: u16, + /// Original version this slate was converted from + pub orig_version: u16, + /// Version of grin block header this slate is compatible with + pub block_header_version: u16, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ParticipantDataV2 { + /// Id of participant in the transaction. (For now, 0=sender, 1=rec) + #[serde(with = "secp_ser::string_or_u64")] + pub id: u64, + /// Public key corresponding to private blinding factor + #[serde(with = "secp_ser::pubkey_serde")] + pub public_blind_excess: PublicKey, + /// Public key corresponding to private nonce + #[serde(with = "secp_ser::pubkey_serde")] + pub public_nonce: PublicKey, + /// Public partial signature + #[serde(with = "secp_ser::option_sig_serde")] + pub part_sig: Option, + /// A message for other participants + pub message: Option, + /// Signature, created with private key corresponding to 'public_blind_excess' + #[serde(with = "secp_ser::option_sig_serde")] + pub message_sig: Option, +} + +/// A transaction +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct TransactionV2 { + /// The kernel "offset" k2 + /// excess is k1G after splitting the key k = k1 + k2 + #[serde( + serialize_with = "secp_ser::as_hex", + deserialize_with = "secp_ser::blind_from_hex" + )] + pub offset: BlindingFactor, + /// The transaction body - inputs/outputs/kernels + pub body: TransactionBodyV2, +} + +/// TransactionBody is a common abstraction for transaction and block +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct TransactionBodyV2 { + /// List of inputs spent by the transaction. + pub inputs: Vec, + /// List of outputs the transaction produces. + pub outputs: Vec, + /// List of kernels that make up this transaction (usually a single kernel). + pub kernels: Vec, +} +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct InputV2 { + /// The features of the output being spent. + /// We will check maturity for coinbase output. + pub features: OutputFeatures, + /// The commit referencing the output being spent. + #[serde( + serialize_with = "secp_ser::as_hex", + deserialize_with = "secp_ser::commitment_from_hex" + )] + pub commit: Commitment, +} + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub struct OutputV2 { + /// Options for an output's structure or use + pub features: OutputFeatures, + /// The homomorphic commitment representing the output amount + #[serde( + serialize_with = "secp_ser::as_hex", + deserialize_with = "secp_ser::commitment_from_hex" + )] + pub commit: Commitment, + /// A proof that the commitment is in the right range + #[serde( + serialize_with = "secp_ser::as_hex", + deserialize_with = "secp_ser::rangeproof_from_hex" + )] + pub proof: RangeProof, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct TxKernelV2 { + /// Options for a kernel's structure or use + pub features: CompatKernelFeatures, + /// Fee originally included in the transaction this proof is for. + #[serde(with = "secp_ser::string_or_u64")] + pub fee: u64, + /// This kernel is not valid earlier than lock_height blocks + /// The max lock_height of all *inputs* to this transaction + #[serde(with = "secp_ser::string_or_u64")] + pub lock_height: u64, + /// Remainder of the sum of all transaction commitments. If the transaction + /// is well formed, amounts components should sum to zero and the excess + /// is hence a valid public key. + #[serde( + serialize_with = "secp_ser::as_hex", + deserialize_with = "secp_ser::commitment_from_hex" + )] + pub excess: Commitment, + /// The signature proving the excess is a valid public key, which signs + /// the transaction fee. + #[serde(with = "secp_ser::sig_serde")] + pub excess_sig: secp::Signature, +} + +/// A mining node requests new coinbase via the foreign api every time a new candidate block is built. +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct CoinbaseV2 { + /// Output + pub output: OutputV2, + /// Kernel + pub kernel: TxKernelV2, + /// Key Id + pub key_id: Option, +} + +// Coinbase data to versioned. +impl From for CoinbaseV2 { + fn from(cb: CbData) -> CoinbaseV2 { + let output = OutputV3::from(&cb.output); + let output = OutputV2::from(&output); + let kernel = TxKernelV3::from(&cb.kernel); + let kernel = TxKernelV2::from(&kernel); + CoinbaseV2 { + output, + kernel, + key_id: cb.key_id, + } + } +} diff --git a/libwallet/src/slate_versions/v3.rs b/libwallet/src/slate_versions/v3.rs index 7a0c557e..4deaf657 100644 --- a/libwallet/src/slate_versions/v3.rs +++ b/libwallet/src/slate_versions/v3.rs @@ -19,6 +19,7 @@ use crate::grin_core::core::transaction::OutputFeatures; use crate::grin_core::libtx::secp_ser; +use crate::grin_core::map_vec; use crate::grin_keychain::{BlindingFactor, Identifier}; use crate::grin_util::secp; use crate::grin_util::secp::key::PublicKey; @@ -30,6 +31,11 @@ use ed25519_dalek::PublicKey as DalekPublicKey; use ed25519_dalek::Signature as DalekSignature; use uuid::Uuid; +use crate::slate_versions::v2::{ + InputV2, OutputV2, ParticipantDataV2, SlateV2, TransactionBodyV2, TransactionV2, TxKernelV2, + VersionCompatInfoV2, +}; + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SlateV3 { /// Versioning info @@ -202,3 +208,298 @@ pub struct CoinbaseV3 { /// Key Id pub key_id: Option, } + +// V2 to V3 For Slate +impl From for SlateV3 { + fn from(slate: SlateV2) -> SlateV3 { + let SlateV2 { + num_participants, + id, + tx, + amount, + fee, + height, + lock_height, + participant_data, + version_info, + } = slate; + let participant_data = map_vec!(participant_data, |data| ParticipantDataV3::from(data)); + let version_info = VersionCompatInfoV3::from(&version_info); + let tx = TransactionV3::from(tx); + SlateV3 { + num_participants, + id, + tx, + amount, + fee, + height, + lock_height, + ttl_cutoff_height: None, + participant_data, + version_info, + payment_proof: None, + } + } +} + +impl From<&ParticipantDataV2> for ParticipantDataV3 { + fn from(data: &ParticipantDataV2) -> ParticipantDataV3 { + let ParticipantDataV2 { + id, + public_blind_excess, + public_nonce, + part_sig, + message, + message_sig, + } = data; + let id = *id; + let public_blind_excess = *public_blind_excess; + let public_nonce = *public_nonce; + let part_sig = *part_sig; + let message: Option = message.as_ref().map(|t| String::from(&**t)); + let message_sig = *message_sig; + ParticipantDataV3 { + id, + public_blind_excess, + public_nonce, + part_sig, + message, + message_sig, + } + } +} + +impl From<&VersionCompatInfoV2> for VersionCompatInfoV3 { + fn from(data: &VersionCompatInfoV2) -> VersionCompatInfoV3 { + let VersionCompatInfoV2 { + version, + orig_version, + block_header_version, + } = data; + let version = *version; + let orig_version = *orig_version; + let block_header_version = *block_header_version; + VersionCompatInfoV3 { + version, + orig_version, + block_header_version, + } + } +} + +impl From for TransactionV3 { + fn from(tx: TransactionV2) -> TransactionV3 { + let TransactionV2 { offset, body } = tx; + let body = TransactionBodyV3::from(&body); + TransactionV3 { offset, body } + } +} + +impl From<&TransactionBodyV2> for TransactionBodyV3 { + fn from(body: &TransactionBodyV2) -> TransactionBodyV3 { + let TransactionBodyV2 { + inputs, + outputs, + kernels, + } = body; + + let inputs = map_vec!(inputs, |inp| InputV3::from(inp)); + let outputs = map_vec!(outputs, |out| OutputV3::from(out)); + let kernels = map_vec!(kernels, |kern| TxKernelV3::from(kern)); + TransactionBodyV3 { + inputs, + outputs, + kernels, + } + } +} + +impl From<&InputV2> for InputV3 { + fn from(input: &InputV2) -> InputV3 { + let InputV2 { features, commit } = *input; + InputV3 { features, commit } + } +} + +impl From<&OutputV2> for OutputV3 { + fn from(output: &OutputV2) -> OutputV3 { + let OutputV2 { + features, + commit, + proof, + } = *output; + OutputV3 { + features, + commit, + proof, + } + } +} + +impl From<&TxKernelV2> for TxKernelV3 { + fn from(kernel: &TxKernelV2) -> TxKernelV3 { + let (fee, lock_height) = (kernel.fee, kernel.lock_height); + TxKernelV3 { + features: kernel.features, + fee, + lock_height, + excess: kernel.excess, + excess_sig: kernel.excess_sig, + } + } +} + +// V3 to V2 +#[allow(unused_variables)] +impl From<&SlateV3> for SlateV2 { + fn from(slate: &SlateV3) -> SlateV2 { + let SlateV3 { + num_participants, + id, + tx, + amount, + fee, + height, + lock_height, + ttl_cutoff_height, + participant_data, + version_info, + payment_proof, + } = slate; + let num_participants = *num_participants; + let id = *id; + let tx = TransactionV2::from(tx); + let amount = *amount; + let fee = *fee; + let height = *height; + let lock_height = *lock_height; + let participant_data = map_vec!(participant_data, |data| ParticipantDataV2::from(data)); + let version_info = VersionCompatInfoV2::from(version_info); + SlateV2 { + num_participants, + id, + tx, + amount, + fee, + height, + lock_height, + participant_data, + version_info, + } + } +} + +impl From<&ParticipantDataV3> for ParticipantDataV2 { + fn from(data: &ParticipantDataV3) -> ParticipantDataV2 { + let ParticipantDataV3 { + id, + public_blind_excess, + public_nonce, + part_sig, + message, + message_sig, + } = data; + let id = *id; + let public_blind_excess = *public_blind_excess; + let public_nonce = *public_nonce; + let part_sig = *part_sig; + let message: Option = message.as_ref().map(|t| String::from(&**t)); + let message_sig = *message_sig; + ParticipantDataV2 { + id, + public_blind_excess, + public_nonce, + part_sig, + message, + message_sig, + } + } +} + +impl From<&VersionCompatInfoV3> for VersionCompatInfoV2 { + fn from(data: &VersionCompatInfoV3) -> VersionCompatInfoV2 { + let VersionCompatInfoV3 { + version, + orig_version, + block_header_version, + } = data; + let version = *version; + let orig_version = *orig_version; + let block_header_version = *block_header_version; + VersionCompatInfoV2 { + version, + orig_version, + block_header_version, + } + } +} + +impl From for TransactionV2 { + fn from(tx: TransactionV3) -> TransactionV2 { + let TransactionV3 { offset, body } = tx; + let body = TransactionBodyV2::from(&body); + TransactionV2 { offset, body } + } +} + +impl From<&TransactionV3> for TransactionV2 { + fn from(tx: &TransactionV3) -> TransactionV2 { + let TransactionV3 { offset, body } = tx; + let offset = offset.clone(); + let body = TransactionBodyV2::from(body); + TransactionV2 { offset, body } + } +} + +impl From<&TransactionBodyV3> for TransactionBodyV2 { + fn from(body: &TransactionBodyV3) -> TransactionBodyV2 { + let TransactionBodyV3 { + inputs, + outputs, + kernels, + } = body; + + let inputs = map_vec!(inputs, |inp| InputV2::from(inp)); + let outputs = map_vec!(outputs, |out| OutputV2::from(out)); + let kernels = map_vec!(kernels, |kern| TxKernelV2::from(kern)); + TransactionBodyV2 { + inputs, + outputs, + kernels, + } + } +} + +impl From<&InputV3> for InputV2 { + fn from(input: &InputV3) -> InputV2 { + let InputV3 { features, commit } = *input; + InputV2 { features, commit } + } +} + +impl From<&OutputV3> for OutputV2 { + fn from(output: &OutputV3) -> OutputV2 { + let OutputV3 { + features, + commit, + proof, + } = *output; + OutputV2 { + features, + commit, + proof, + } + } +} + +impl From<&TxKernelV3> for TxKernelV2 { + fn from(kernel: &TxKernelV3) -> TxKernelV2 { + TxKernelV2 { + features: kernel.features, + fee: kernel.fee, + lock_height: kernel.lock_height, + excess: kernel.excess, + excess_sig: kernel.excess_sig, + } + } +} diff --git a/src/bin/grin-wallet.yml b/src/bin/grin-wallet.yml index 039b2341..be565ac6 100644 --- a/src/bin/grin-wallet.yml +++ b/src/bin/grin-wallet.yml @@ -155,11 +155,6 @@ subcommands: short: t long: stored_tx takes_value: true - - slate_version: - help: Target slate version to output/send to receiver - short: v - long: slate_version - takes_value: true - receive: about: Processes a transaction file to accept a transfer from a sender args: @@ -205,11 +200,6 @@ subcommands: short: g long: message takes_value: true - - slate_version: - help: Target slate version to output/send to receiver - short: v - long: slate_version - takes_value: true - dest: help: Name of destination slate output file short: d