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
This commit is contained in:
Yeastplume 2019-12-04 11:52:42 +00:00 committed by GitHub
parent 7db55592d0
commit 86e6f511c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 591 additions and 54 deletions

View file

@ -53,7 +53,8 @@ pub trait ForeignRpc {
"Ok": { "Ok": {
"foreign_api_version": 2, "foreign_api_version": 2,
"supported_slate_versions": [ "supported_slate_versions": [
"V3" "V3",
"V2"
] ]
} }
} }
@ -553,9 +554,10 @@ where
message: Option<String>, message: Option<String>,
) -> Result<VersionedSlate, ErrorKind> { ) -> Result<VersionedSlate, ErrorKind> {
let version = in_slate.version(); let version = in_slate.version();
let slate_from = Slate::from(in_slate);
let out_slate = Foreign::receive_tx( let out_slate = Foreign::receive_tx(
self, self,
&Slate::from(in_slate), &slate_from,
dest_acct_name.as_ref().map(String::as_str), dest_acct_name.as_ref().map(String::as_str),
message, message,
) )

View file

@ -513,9 +513,7 @@ where
{ {
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| { controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
let slate = api.issue_invoice_tx(m, args.issue_args)?; let slate = api.issue_invoice_tx(m, args.issue_args)?;
let mut tx_file = File::create(args.dest.clone())?; PathToSlate((&args.dest).into()).put_tx(&slate)?;
tx_file.write_all(json::to_string(&slate).unwrap().as_bytes())?;
tx_file.sync_all()?;
Ok(()) Ok(())
})?; })?;
Ok(()) Ok(())

View file

@ -19,7 +19,7 @@ use crate::config::TorConfig;
use crate::keychain::Keychain; use crate::keychain::Keychain;
use crate::libwallet::{ use crate::libwallet::{
address, Error, ErrorKind, NodeClient, NodeVersionInfo, Slate, WalletInst, WalletLCProvider, 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::secp::key::SecretKey;
use crate::util::{from_hex, static_secp_instance, to_base64, Mutex}; use crate::util::{from_hex, static_secp_instance, to_base64, Mutex};
@ -63,10 +63,7 @@ fn check_middleware(
bhv = n.block_header_version; bhv = n.block_header_version;
} }
if let Some(s) = slate { if let Some(s) = slate {
if s.version_info.version < CURRENT_SLATE_VERSION if bhv > 3 && s.version_info.block_header_version < GRIN_BLOCK_HEADER_VERSION {
// || (bhv == 3 && s.version_info.block_header_version != 3)
|| (bhv > 3 && s.version_info.block_header_version < GRIN_BLOCK_HEADER_VERSION)
{
Err(ErrorKind::Compatibility( Err(ErrorKind::Compatibility(
"Incoming Slate is not compatible with this wallet. \ "Incoming Slate is not compatible with this wallet. \
Please upgrade the node or use a different one." Please upgrade the node or use a different one."

View file

@ -16,7 +16,7 @@
use std::fs::File; use std::fs::File;
use std::io::{Read, Write}; use std::io::{Read, Write};
use crate::libwallet::{Error, ErrorKind, Slate}; use crate::libwallet::{Error, ErrorKind, Slate, SlateVersion, VersionedSlate};
use crate::{SlateGetter, SlatePutter}; use crate::{SlateGetter, SlatePutter};
use std::path::PathBuf; use std::path::PathBuf;
@ -26,8 +26,20 @@ pub struct PathToSlate(pub PathBuf);
impl SlatePutter for PathToSlate { impl SlatePutter for PathToSlate {
fn put_tx(&self, slate: &Slate) -> Result<(), Error> { fn put_tx(&self, slate: &Slate) -> Result<(), Error> {
let mut pub_tx = File::create(&self.0)?; 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( pub_tx.write_all(
serde_json::to_string(slate) serde_json::to_string(&out_slate)
.map_err(|_| ErrorKind::SlateSer)? .map_err(|_| ErrorKind::SlateSer)?
.as_bytes(), .as_bytes(),
)?; )?;

View file

@ -14,6 +14,7 @@
/// HTTP Wallet 'plugin' implementation /// HTTP Wallet 'plugin' implementation
use crate::client_utils::{Client, ClientError}; use crate::client_utils::{Client, ClientError};
use crate::libwallet::slate_versions::{SlateVersion, VersionedSlate};
use crate::libwallet::{Error, ErrorKind, Slate}; use crate::libwallet::{Error, ErrorKind, Slate};
use crate::SlateSender; use crate::SlateSender;
use serde::Serialize; use serde::Serialize;
@ -64,7 +65,7 @@ impl HttpSlateSender {
} }
/// Check version of the listening wallet /// Check version of the listening wallet
fn check_other_version(&self, url: &str) -> Result<(), Error> { fn check_other_version(&self, url: &str) -> Result<SlateVersion, Error> {
let req = json!({ let req = json!({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "check_version", "method": "check_version",
@ -111,13 +112,16 @@ impl HttpSlateSender {
return Err(ErrorKind::ClientCallback(report).into()); return Err(ErrorKind::ClientCallback(report).into());
} }
if !supported_slate_versions.contains(&"V3".to_owned()) { if supported_slate_versions.contains(&"V3".to_owned()) {
let report = format!("Unable to negotiate slate format with other wallet."); return Ok(SlateVersion::V3);
error!("{}", report); }
return Err(ErrorKind::ClientCallback(report).into()); 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<IN>( fn post<IN>(
@ -173,15 +177,28 @@ impl SlateSender for HttpSlateSender {
.map_err(|e| ErrorKind::TorProcess(format!("{:?}", e).into()))?; .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 // Note: not using easy-jsonrpc as don't want the dependencies in this crate
let req = json!({ let req = json!({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "receive_tx", "method": "receive_tx",
"id": 1, "id": 1,
"params": [ "params": [
slate, slate_send,
null, null,
null null
] ]

View file

@ -42,6 +42,7 @@ use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use uuid::Uuid; use uuid::Uuid;
use crate::slate_versions::v2::SlateV2;
use crate::slate_versions::v3::{ use crate::slate_versions::v3::{
CoinbaseV3, InputV3, OutputV3, ParticipantDataV3, PaymentInfoV3, SlateV3, TransactionBodyV3, CoinbaseV3, InputV3, OutputV3, ParticipantDataV3, PaymentInfoV3, SlateV3, TransactionBodyV3,
TransactionV3, TxKernelV3, VersionCompatInfoV3, TransactionV3, TxKernelV3, VersionCompatInfoV3,
@ -232,13 +233,11 @@ impl Slate {
let version = Slate::parse_slate_version(slate_json)?; let version = Slate::parse_slate_version(slate_json)?;
let v3: SlateV3 = match version { let v3: SlateV3 = match version {
3 => serde_json::from_str(slate_json).context(ErrorKind::SlateDeser)?, 3 => serde_json::from_str(slate_json).context(ErrorKind::SlateDeser)?,
// left as a reminder 2 => {
/*0 => { let v2: SlateV2 =
let v0: SlateV0 =
serde_json::from_str(slate_json).context(ErrorKind::SlateDeser)?; serde_json::from_str(slate_json).context(ErrorKind::SlateDeser)?;
let v1 = SlateV1::from(v0); SlateV3::from(v2)
SlateV3::from(v1) }
}*/
_ => return Err(ErrorKind::SlateVersion(version).into()), _ => return Err(ErrorKind::SlateVersion(version).into()),
}; };
Ok(v3.into()) Ok(v3.into())
@ -728,11 +727,10 @@ impl Serialize for Slate {
match self.version_info.orig_version { match self.version_info.orig_version {
3 => v3.serialize(serializer), 3 => v3.serialize(serializer),
// left as a reminder // left as a reminder
/*0 => { 2 => {
let v1 = SlateV1::from(v2); let v2 = SlateV2::from(&v3);
let v0 = SlateV0::from(v1); v2.serialize(serializer)
v0.serialize(serializer) }
}*/
v => Err(S::Error::custom(format!("Unknown slate version {}", v))), v => Err(S::Error::custom(format!("Unknown slate version {}", v))),
} }
} }

View file

@ -18,11 +18,14 @@
//! remains for future needs //! remains for future needs
use crate::slate::Slate; use crate::slate::Slate;
use crate::slate_versions::v2::{CoinbaseV2, SlateV2};
use crate::slate_versions::v3::{CoinbaseV3, SlateV3}; use crate::slate_versions::v3::{CoinbaseV3, SlateV3};
use crate::types::CbData; use crate::types::CbData;
pub mod ser; pub mod ser;
#[allow(missing_docs)]
pub mod v2;
#[allow(missing_docs)] #[allow(missing_docs)]
pub mod v3; pub mod v3;
@ -37,6 +40,8 @@ pub const GRIN_BLOCK_HEADER_VERSION: u16 = 3;
pub enum SlateVersion { pub enum SlateVersion {
/// V3 (most current) /// V3 (most current)
V3, V3,
/// V2 (2.0.0 - Onwards)
V2,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -46,6 +51,8 @@ pub enum SlateVersion {
pub enum VersionedSlate { pub enum VersionedSlate {
/// Current (3.0.0 Onwards ) /// Current (3.0.0 Onwards )
V3(SlateV3), V3(SlateV3),
/// V2 (2.0.0 - Onwards)
V2(SlateV2),
} }
impl VersionedSlate { impl VersionedSlate {
@ -53,6 +60,7 @@ impl VersionedSlate {
pub fn version(&self) -> SlateVersion { pub fn version(&self) -> SlateVersion {
match *self { match *self {
VersionedSlate::V3(_) => SlateVersion::V3, VersionedSlate::V3(_) => SlateVersion::V3,
VersionedSlate::V2(_) => SlateVersion::V2,
} }
} }
@ -62,12 +70,11 @@ impl VersionedSlate {
SlateVersion::V3 => VersionedSlate::V3(slate.into()), SlateVersion::V3 => VersionedSlate::V3(slate.into()),
// Left here as a reminder of what needs to be inserted on // Left here as a reminder of what needs to be inserted on
// the release of a new slate // the release of a new slate
/*SlateVersion::V0 => { SlateVersion::V2 => {
let s = SlateV3::from(slate); let s = SlateV3::from(slate);
let s = SlateV1::from(s); let s = SlateV2::from(&s);
let s = SlateV0::from(s); VersionedSlate::V2(s)
VersionedSlate::V0(s) }
}*/
} }
} }
} }
@ -78,13 +85,11 @@ impl From<VersionedSlate> for Slate {
VersionedSlate::V3(s) => { VersionedSlate::V3(s) => {
let s = SlateV3::from(s); let s = SlateV3::from(s);
Slate::from(s) Slate::from(s)
} // Again, left in as a reminder }
/*VersionedSlate::V0(s) => { VersionedSlate::V2(s) => {
let s = SlateV0::from(s); let s = SlateV3::from(s);
let s = SlateV1::from(s);
let s = SlateV2::from(s);
Slate::from(s) Slate::from(s)
}*/ }
} }
} }
} }
@ -96,6 +101,8 @@ impl From<VersionedSlate> for Slate {
pub enum VersionedCoinbase { pub enum VersionedCoinbase {
/// Current supported coinbase version. /// Current supported coinbase version.
V3(CoinbaseV3), V3(CoinbaseV3),
/// Previous
V2(CoinbaseV2),
} }
impl VersionedCoinbase { impl VersionedCoinbase {
@ -103,6 +110,7 @@ impl VersionedCoinbase {
pub fn into_version(cb: CbData, version: SlateVersion) -> VersionedCoinbase { pub fn into_version(cb: CbData, version: SlateVersion) -> VersionedCoinbase {
match version { match version {
SlateVersion::V3 => VersionedCoinbase::V3(cb.into()), SlateVersion::V3 => VersionedCoinbase::V3(cb.into()),
SlateVersion::V2 => VersionedCoinbase::V2(cb.into()),
} }
} }
} }

View file

@ -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<ParticipantDataV2>,
}
#[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<Signature>,
/// A message for other participants
pub message: Option<String>,
/// Signature, created with private key corresponding to 'public_blind_excess'
#[serde(with = "secp_ser::option_sig_serde")]
pub message_sig: Option<Signature>,
}
/// 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<InputV2>,
/// List of outputs the transaction produces.
pub outputs: Vec<OutputV2>,
/// List of kernels that make up this transaction (usually a single kernel).
pub kernels: Vec<TxKernelV2>,
}
#[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<Identifier>,
}
// Coinbase data to versioned.
impl From<CbData> 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,
}
}
}

View file

@ -19,6 +19,7 @@
use crate::grin_core::core::transaction::OutputFeatures; use crate::grin_core::core::transaction::OutputFeatures;
use crate::grin_core::libtx::secp_ser; use crate::grin_core::libtx::secp_ser;
use crate::grin_core::map_vec;
use crate::grin_keychain::{BlindingFactor, Identifier}; use crate::grin_keychain::{BlindingFactor, Identifier};
use crate::grin_util::secp; use crate::grin_util::secp;
use crate::grin_util::secp::key::PublicKey; use crate::grin_util::secp::key::PublicKey;
@ -30,6 +31,11 @@ use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature; use ed25519_dalek::Signature as DalekSignature;
use uuid::Uuid; use uuid::Uuid;
use crate::slate_versions::v2::{
InputV2, OutputV2, ParticipantDataV2, SlateV2, TransactionBodyV2, TransactionV2, TxKernelV2,
VersionCompatInfoV2,
};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SlateV3 { pub struct SlateV3 {
/// Versioning info /// Versioning info
@ -202,3 +208,298 @@ pub struct CoinbaseV3 {
/// Key Id /// Key Id
pub key_id: Option<Identifier>, pub key_id: Option<Identifier>,
} }
// V2 to V3 For Slate
impl From<SlateV2> 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<String> = 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<TransactionV2> 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<String> = 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<TransactionV3> 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,
}
}
}

View file

@ -155,11 +155,6 @@ subcommands:
short: t short: t
long: stored_tx long: stored_tx
takes_value: true takes_value: true
- slate_version:
help: Target slate version to output/send to receiver
short: v
long: slate_version
takes_value: true
- receive: - receive:
about: Processes a transaction file to accept a transfer from a sender about: Processes a transaction file to accept a transfer from a sender
args: args:
@ -205,11 +200,6 @@ subcommands:
short: g short: g
long: message long: message
takes_value: true takes_value: true
- slate_version:
help: Target slate version to output/send to receiver
short: v
long: slate_version
takes_value: true
- dest: - dest:
help: Name of destination slate output file help: Name of destination slate output file
short: d short: d