Post Hardfork 3 Cleanup (#490)

* Change versioning on master to 4.1.x development

* Remove SlateV3, V3 References from command-line code

* continue to remove pre HF3 functionality, remove participant_id from slate, remove is_compact, derive slate state based on slate state field

* slate no longer needs explicit compact step

* version/build coinbase doctest cleanup

* don't attempt to store transaction during tx lock if it doesn't exist

* repair incorrectly removed logic

* last test fixes (hopefully)
This commit is contained in:
Yeastplume 2020-07-31 10:33:45 +01:00 committed by GitHub
parent 2888882e30
commit 6c9cef1370
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 113 additions and 1201 deletions

14
Cargo.lock generated
View file

@ -1367,7 +1367,7 @@ dependencies = [
[[package]]
name = "grin_wallet"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"built",
"clap",
@ -1395,7 +1395,7 @@ dependencies = [
[[package]]
name = "grin_wallet_api"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"base64 0.12.1",
"chrono",
@ -1419,7 +1419,7 @@ dependencies = [
[[package]]
name = "grin_wallet_config"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"dirs 2.0.2",
"grin_wallet_util",
@ -1432,7 +1432,7 @@ dependencies = [
[[package]]
name = "grin_wallet_controller"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"chrono",
"easy-jsonrpc-mw",
@ -1462,7 +1462,7 @@ dependencies = [
[[package]]
name = "grin_wallet_impls"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"blake2-rfc",
"byteorder",
@ -1497,7 +1497,7 @@ dependencies = [
[[package]]
name = "grin_wallet_libwallet"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"age",
"base64 0.9.3",
@ -1529,7 +1529,7 @@ dependencies = [
[[package]]
name = "grin_wallet_util"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
dependencies = [
"data-encoding",
"ed25519-dalek",

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format."
license = "Apache-2.0"
@ -31,13 +31,13 @@ semver = "0.10"
rustyline = "6"
lazy_static = "1"
grin_wallet_api = { path = "./api", version = "4.0.1-alpha.1" }
grin_wallet_impls = { path = "./impls", version = "4.0.1-alpha.1" }
grin_wallet_libwallet = { path = "./libwallet", version = "4.0.1-alpha.1" }
grin_wallet_controller = { path = "./controller", version = "4.0.1-alpha.1" }
grin_wallet_config = { path = "./config", version = "4.0.1-alpha.1" }
grin_wallet_api = { path = "./api", version = "4.1.0-alpha.1" }
grin_wallet_impls = { path = "./impls", version = "4.1.0-alpha.1" }
grin_wallet_libwallet = { path = "./libwallet", version = "4.1.0-alpha.1" }
grin_wallet_controller = { path = "./controller", version = "4.1.0-alpha.1" }
grin_wallet_config = { path = "./config", version = "4.1.0-alpha.1" }
grin_wallet_util = { path = "./util", version = "4.0.1-alpha.1" }
grin_wallet_util = { path = "./util", version = "4.1.0-alpha.1" }
[build-dependencies]
built = { version = "0.4", features = ["git2"]}

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet_api"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Grin Wallet API"
license = "Apache-2.0"
@ -24,10 +24,10 @@ ring = "0.16"
base64 = "0.12"
ed25519-dalek = "1.0.0-pre.3"
grin_wallet_libwallet = { path = "../libwallet", version = "4.0.1-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.0.1-alpha.1" }
grin_wallet_impls = { path = "../impls", version = "4.0.1-alpha.1" }
grin_wallet_util = { path = "../util", version = "4.0.1-alpha.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "4.1.0-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.1.0-alpha.1" }
grin_wallet_impls = { path = "../impls", version = "4.1.0-alpha.1" }
grin_wallet_util = { path = "../util", version = "4.1.0-alpha.1" }
[dev-dependencies]
serde_json = "1"

View file

@ -40,8 +40,6 @@ pub enum ForeignCheckMiddlewareFn {
VerifySlateMessages,
/// receive_tx
ReceiveTx,
/// finalize_invoice_tx (delete HF3)
FinalizeInvoiceTx,
/// finalize_tx
FinalizeTx,
}
@ -441,13 +439,6 @@ where
pub fn finalize_tx(&self, slate: &Slate, post_automatically: bool) -> Result<Slate, Error> {
let mut w_lock = self.wallet_inst.lock();
let w = w_lock.lc_provider()?.wallet_inst()?;
if let Some(m) = self.middleware.as_ref() {
m(
ForeignCheckMiddlewareFn::FinalizeInvoiceTx,
w.w2n_client().get_version_info(),
Some(slate),
)?;
}
let post_automatically = match self.doctest_mode {
true => false,
false => post_automatically,

View file

@ -53,8 +53,7 @@ pub trait ForeignRpc {
"Ok": {
"foreign_api_version": 2,
"supported_slate_versions": [
"V4",
"V3"
"V4"
]
}
}
@ -96,15 +95,13 @@ pub trait ForeignRpc {
"kernel": {
"excess": "08dfe86d732f2dd24bac36aa7502685221369514197c26d33fac03041d47e4b490",
"excess_sig": "8f07ddd5e9f5179cff19486034181ed76505baaad53e5d994064127b56c5841be02fa098c54c9bf638e0ee1ad5eb896caa11565f632be7b9cd65643ba371044f",
"features": "Coinbase",
"fee": "0",
"lock_height": "0"
"features": "Coinbase"
},
"key_id": "0300000000000000000000000400000000",
"output": {
"commit": "08fe198e525a5937d0c5d01fa354394d2679be6df5d42064a0f7550c332fce3d9d",
"features": "Coinbase",
"proof": "9d8488fcb43c9c0f683b9ce62f3c8e047b71f2b4cd94b99a3c9a36aef3bb8361ee17b4489eb5f6d6507250532911acb76f18664604c2ca4215347a5d5d8e417d00ca2d59ec29371286986428b0ec1177fc2e416339ea8542eff8186550ad0d65ffac35d761c38819601d331fd427576e2fff823bbc3faa04f49f5332bd4de46cd4f83d0fd46cdb1dfb87069e95974e4a45e0235db71f5efe5cec83bbb30e152ac50a010ef4e57e33aabbeb894b9114f90bb5c3bb03b009014e358aa3914b1a208eb9d8806fbb679c256d4c1a47b0fce3f1235d58192cb7f615bd7c5dab48486db8962c2a594e69ff70029784a810b4eb76b0516805f3417308cda8acb38b9a3ea061568f0c97f5b46a3beff556dc7ebb58c774f08be472b4b6f603e5f8309c2d1f8d6f52667cb86816b330eca5374148aa898f5bbaf3f23a3ebcdc359ee1e14d73a65596c0ddf51f123234969ac8b557ba9dc53255dd6f5c0d3dd2c035a6d1a1185102612fdca474d018b9f9e81acfa3965d42769f5a303bbaabb78d17e0c026b8be0039c55ad1378c8316101b5206359f89fd1ee239115dde458749a040997be43c039055594cab76f602a0a1ee4f5322f3ab1157342404239adbf8b6786544cd67d9891c2689530e65f2a4b8e52d8551b92ffefb812ffa4a472a10701884151d1fb77d8cdc0b1868cb31b564e98e4c035e0eaa26203b882552c7b69deb0d8ec67cf28d5ec044554f8a91a6cae87eb377d6d906bba6ec94dda24ebfd372727f68334af798b11256d88e17cef7c4fed092128215f992e712ed128db2a9da2f5e8fadea9395bddd294a524dce47f818794c56b03e1253bf0fb9cb8beebc5742e4acf19c24824aa1d41996e839906e24be120a0bdf6800da599ec9ec3d1c4c11571c9f143eadbb554fa3c8c9777994a3f3421d454e4ec54c11b97eea3e4e6ede2d97a2bc"
"com": "08fe198e525a5937d0c5d01fa354394d2679be6df5d42064a0f7550c332fce3d9d",
"features": 1,
"prf": "9d8488fcb43c9c0f683b9ce62f3c8e047b71f2b4cd94b99a3c9a36aef3bb8361ee17b4489eb5f6d6507250532911acb76f18664604c2ca4215347a5d5d8e417d00ca2d59ec29371286986428b0ec1177fc2e416339ea8542eff8186550ad0d65ffac35d761c38819601d331fd427576e2fff823bbc3faa04f49f5332bd4de46cd4f83d0fd46cdb1dfb87069e95974e4a45e0235db71f5efe5cec83bbb30e152ac50a010ef4e57e33aabbeb894b9114f90bb5c3bb03b009014e358aa3914b1a208eb9d8806fbb679c256d4c1a47b0fce3f1235d58192cb7f615bd7c5dab48486db8962c2a594e69ff70029784a810b4eb76b0516805f3417308cda8acb38b9a3ea061568f0c97f5b46a3beff556dc7ebb58c774f08be472b4b6f603e5f8309c2d1f8d6f52667cb86816b330eca5374148aa898f5bbaf3f23a3ebcdc359ee1e14d73a65596c0ddf51f123234969ac8b557ba9dc53255dd6f5c0d3dd2c035a6d1a1185102612fdca474d018b9f9e81acfa3965d42769f5a303bbaabb78d17e0c026b8be0039c55ad1378c8316101b5206359f89fd1ee239115dde458749a040997be43c039055594cab76f602a0a1ee4f5322f3ab1157342404239adbf8b6786544cd67d9891c2689530e65f2a4b8e52d8551b92ffefb812ffa4a472a10701884151d1fb77d8cdc0b1868cb31b564e98e4c035e0eaa26203b882552c7b69deb0d8ec67cf28d5ec044554f8a91a6cae87eb377d6d906bba6ec94dda24ebfd372727f68334af798b11256d88e17cef7c4fed092128215f992e712ed128db2a9da2f5e8fadea9395bddd294a524dce47f818794c56b03e1253bf0fb9cb8beebc5742e4acf19c24824aa1d41996e839906e24be120a0bdf6800da599ec9ec3d1c4c11571c9f143eadbb554fa3c8c9777994a3f3421d454e4ec54c11b97eea3e4e6ede2d97a2bc"
}
}
}
@ -288,9 +285,6 @@ pub trait ForeignRpc {
```
*/
fn finalize_tx(&self, slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind>;
/// For backwards-compatibility. Remove HF3
fn finalize_invoice_tx(&self, slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind>;
}
impl<'a, L, C, K> ForeignRpc for Foreign<'a, L, C, K>
@ -305,7 +299,7 @@ where
fn build_coinbase(&self, block_fees: &BlockFees) -> Result<VersionedCoinbase, ErrorKind> {
let cb: CbData = Foreign::build_coinbase(self, block_fees).map_err(|e| e.kind())?;
Ok(VersionedCoinbase::into_version(cb, SlateVersion::V3))
Ok(VersionedCoinbase::into_version(cb, SlateVersion::V4))
}
fn receive_tx(
@ -332,14 +326,6 @@ where
Foreign::finalize_tx(self, &Slate::from(in_slate), true).map_err(|e| e.kind())?;
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
}
//TODO: Delete HF3
fn finalize_invoice_tx(&self, in_slate: VersionedSlate) -> Result<VersionedSlate, ErrorKind> {
let version = in_slate.version();
let out_slate =
Foreign::finalize_tx(self, &Slate::from(in_slate), false).map_err(|e| e.kind())?;
Ok(VersionedSlate::into_version(out_slate, version).map_err(|e| e.kind())?)
}
}
fn test_check_middleware(

View file

@ -2320,17 +2320,6 @@ where
) -> Result<(bool, bool), Error> {
owner::verify_payment_proof(self.wallet_inst.clone(), keychain_mask, proof)
}
/// Return whether this transaction is marked as invoice in the context
// TODO: Remove post HF3
// This will be removed once state is added to slate
pub fn context_is_invoice(
&self,
keychain_mask: Option<&SecretKey>,
slate: &Slate,
) -> Result<bool, Error> {
owner::context_is_invoice(self.wallet_inst.clone(), keychain_mask, slate)
}
}
/// attempt to send slate synchronously, starting with TOR and downgrading to HTTP

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet_config"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Configuration for grin wallet , a simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format."
license = "Apache-2.0"
@ -16,7 +16,7 @@ serde_derive = "1"
toml = "0.5"
dirs = "2.0"
grin_wallet_util = { path = "../util", version = "4.0.1-alpha.1" }
grin_wallet_util = { path = "../util", version = "4.1.0-alpha.1" }
[dev-dependencies]
pretty_assertions = "0.6"

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet_controller"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Controllers for grin wallet instantiation"
license = "Apache-2.0"
@ -30,12 +30,12 @@ chrono = { version = "0.4.11", features = ["serde"] }
easy-jsonrpc-mw = "0.5.4"
lazy_static = "1"
grin_wallet_util = { path = "../util", version = "4.0.1-alpha.1" }
grin_wallet_util = { path = "../util", version = "4.1.0-alpha.1" }
grin_wallet_api = { path = "../api", version = "4.0.1-alpha.1" }
grin_wallet_impls = { path = "../impls", version = "4.0.1-alpha.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "4.0.1-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.0.1-alpha.1" }
grin_wallet_api = { path = "../api", version = "4.1.0-alpha.1" }
grin_wallet_impls = { path = "../impls", version = "4.1.0-alpha.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "4.1.0-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.1.0-alpha.1" }
[dev-dependencies]
ed25519-dalek = "1.0.0-pre.3"

View file

@ -19,17 +19,16 @@ use crate::apiwallet::{try_slatepack_sync_workflow, Owner};
use crate::config::{TorConfig, WalletConfig, WALLET_CONFIG_FILE_NAME};
use crate::core::{core, global};
use crate::error::{Error, ErrorKind};
use crate::impls::PathToSlatepack;
use crate::impls::SlateGetter as _;
use crate::impls::{HttpSlateSender, PathToSlate, PathToSlatepack, SlatePutter};
use crate::keychain;
use crate::libwallet::{
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, Slate, SlateVersion, Slatepack,
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, Slate, SlateState, Slatepack,
SlatepackAddress, Slatepacker, SlatepackerArgs, WalletLCProvider,
};
use crate::util::secp::key::SecretKey;
use crate::util::{Mutex, ZeroingString};
use crate::{controller, display};
use grin_wallet_util::OnionV3Address;
use serde_json as json;
use std::convert::TryFrom;
use std::fs::File;
@ -259,8 +258,6 @@ pub struct SendArgs {
pub ttl_blocks: Option<u64>,
pub skip_tor: bool,
pub outfile: Option<String>,
//TODO: Remove HF3
pub output_v4_slate: bool,
}
pub fn send<L, C, K>(
@ -276,126 +273,6 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
let wallet_inst = owner_api.wallet_inst.clone();
// Check other version, and if it only supports 3 set the target slate
// version to 3 to avoid removing the transaction object
// TODO: This block is temporary, for the period between the release of v4.0.0 and HF3,
// after which this should be removable
let mut args = args;
//TODO: Remove block post HF3
// All this block does is determine whether the slate should be
// output as a V3 Slate for the receiver
let mut tor_sender = None;
let is_pre_fork;
{
is_pre_fork = {
let cur_height = {
libwallet::wallet_lock!(wallet_inst, w);
w.w2n_client().get_chain_tip()?.0
};
match global::get_chain_type() {
global::ChainTypes::Mainnet => {
if cur_height < 786240 && !args.output_v4_slate {
true
} else {
false
}
}
global::ChainTypes::Floonet => {
if cur_height < 552960 && !args.output_v4_slate {
true
} else {
false
}
}
_ => false,
}
};
if is_pre_fork {
let trailing = match args.dest.ends_with('/') {
true => "",
false => "/",
};
let mut address_found = false;
// For sync methods, derive intended endpoint from dest
match SlatepackAddress::try_from(args.dest.as_str()) {
Ok(address) => {
let tor_addr = OnionV3Address::try_from(&address).unwrap();
// Try pinging the destination via TOR
debug!("Version ping: TOR address is: {}", tor_addr);
match HttpSlateSender::with_socks_proxy(
&tor_addr.to_http_str(),
&tor_config.as_ref().unwrap().socks_proxy_addr,
&tor_config.as_ref().unwrap().send_config_dir,
) {
Ok(mut sender) => {
let url_str =
format!("{}{}v2/foreign", tor_addr.to_http_str(), trailing);
if let Ok(v) = sender.check_other_version(&url_str) {
if v == SlateVersion::V3 {
args.target_slate_version = Some(3);
}
address_found = true;
}
tor_sender = Some(sender);
}
Err(e) => {
debug!(
"Version ping: Couldn't create slate sender for TOR: {:?}",
e
);
}
}
}
Err(e) => {
debug!("Version ping: Address is not SlatepackAddress: {:?}", e);
}
}
// now try http
if !address_found {
// Try pinging the destination via TOR
match HttpSlateSender::new(&args.dest) {
Ok(mut sender) => {
let url_str = format!("{}{}v2/foreign", args.dest, trailing);
match sender.check_other_version(&url_str) {
Ok(v) => {
if v == SlateVersion::V3 {
args.target_slate_version = Some(3);
}
address_found = true;
}
Err(e) => {
debug!(
"Version ping: Couldn't get other version for HTTP: {:?}",
e
);
}
}
}
Err(e) => {
debug!(
"Version ping: Couldn't create slate sender for HTTP: {:?}",
e
);
}
}
}
if !address_found {
// otherwise, determine slate format based on block height
// For files spit out a V3 Slate if we're before HF3,
// Or V4 slate otherwise
if is_pre_fork {
args.target_slate_version = Some(3);
}
}
}
} // end pre HF3 Block
let mut slate = Slate::blank(2, false);
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
if args.estimate_selection_strategies {
@ -460,8 +337,7 @@ where
None => None,
};
let res =
try_slatepack_sync_workflow(&slate, &args.dest, tor_config, tor_sender, false, test_mode);
let res = try_slatepack_sync_workflow(&slate, &args.dest, tor_config, None, false, test_mode);
match res {
Ok(Some(s)) => {
@ -490,7 +366,6 @@ where
args.outfile,
true,
false,
is_pre_fork,
)?;
}
Err(e) => return Err(e.into()),
@ -506,7 +381,6 @@ pub fn output_slatepack<L, C, K>(
out_file_override: Option<String>,
lock: bool,
finalizing: bool,
is_pre_fork: bool,
) -> Result<(), libwallet::Error>
where
L: WalletLCProvider<'static, C, K> + 'static,
@ -547,20 +421,6 @@ where
})?;
}
// TODO: Remove HF3
if is_pre_fork {
PathToSlate((&out_file_name).into()).put_tx(&slate, false)?;
println!();
println!("Transaction file was output to:");
println!();
println!("{}", out_file_name);
println!();
if !finalizing {
println!("Please send this file to the other party manually");
}
return Ok(());
}
println!("{}", out_file_name);
let mut output = File::create(out_file_name.clone())?;
output.write_all(&message.as_bytes())?;
@ -606,13 +466,8 @@ where
let mut ret_address = None;
let slate = match filename {
Some(f) => {
// first try regular slate - remove HF3
let mut sl = match PathToSlate((&f).into()).get_tx() {
Ok(s) => Some(s.0), //pre HF3, regular slate
Err(_) => None,
};
// otherwise, get slate from slatepack
if sl.is_none() {
let mut sl = None;
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
let dec_key = api.get_slatepack_secret_key(m, 0)?;
let packer = Slatepacker::new(SlatepackerArgs {
@ -625,7 +480,6 @@ where
ret_address = pts.get_slatepack(true)?.sender;
Ok(())
})?;
}
sl
}
None => None,
@ -736,7 +590,6 @@ where
args.outfile,
false,
false,
slate.version_info.version < 4,
)?;
Ok(())
}
@ -851,14 +704,8 @@ where
// Rather than duplicating the entire command, we'll just
// try to determine what kind of finalization this is
// based on the slate contents
// for now, we can tell this is an invoice transaction
// if the receipient (participant 1) hasn't completed sigs
let mut is_invoice = false;
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
is_invoice = api.context_is_invoice(m, &slate)?;
Ok(())
})?;
// based on the slate state
let is_invoice = slate.state == SlateState::Invoice2;
if is_invoice {
let km = match keychain_mask.as_ref() {
@ -905,7 +752,6 @@ where
args.outfile,
false,
true,
slate.version_info.version < 4,
)?;
Ok(())
@ -917,8 +763,6 @@ pub struct IssueInvoiceArgs {
pub dest: String,
/// issue invoice tx args
pub issue_args: IssueInvoiceTxArgs,
/// whether to output a V4 slate
pub output_v4_slate: bool,
/// output file override
pub outfile: Option<String>,
}
@ -933,37 +777,7 @@ where
C: NodeClient + 'static,
K: keychain::Keychain + 'static,
{
//TODO: Remove block HF3
let is_pre_fork = {
let cur_height = {
let wallet_inst = owner_api.wallet_inst.clone();
libwallet::wallet_lock!(wallet_inst, w);
w.w2n_client().get_chain_tip()?.0
};
match global::get_chain_type() {
global::ChainTypes::Mainnet => {
if cur_height < 786240 && !&args.output_v4_slate {
true
} else {
false
}
}
global::ChainTypes::Floonet => {
if cur_height < 552960 && !&args.output_v4_slate {
true
} else {
false
}
}
_ => false,
}
};
let mut issue_args = args.issue_args.clone();
if is_pre_fork {
issue_args.target_slate_version = Some(3);
}
let issue_args = args.issue_args.clone();
let mut slate = Slate::blank(2, false);
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
@ -979,7 +793,6 @@ where
args.outfile,
false,
false,
is_pre_fork,
)?;
Ok(())
}
@ -1098,7 +911,6 @@ where
args.outfile,
true,
false,
slate.version_info.version < 4,
)?;
Ok(())
}

View file

@ -409,7 +409,7 @@ fn slatepack_exchange_test_impl(
wallet::controller::foreign_single_use(wallet2.clone(), mask2_i.clone(), |api| {
let res = slate_from_packed(&send_file, use_armored, (&dec_key_2).as_ref())?;
slatepack = res.0;
let slatepack = res.0;
slate = res.1;
slate = api.receive_tx(&slate, None, None)?;
output_slatepack(

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet_impls"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Concrete types derived from libwallet traits"
license = "Apache-2.0"
@ -41,6 +41,6 @@ regex = "1.3"
timer = "0.2"
sysinfo = "0.14"
grin_wallet_util = { path = "../util", version = "4.0.1-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.0.1-alpha.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "4.0.1-alpha.1" }
grin_wallet_util = { path = "../util", version = "4.1.0-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.1.0-alpha.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "4.1.0-alpha.1" }

View file

@ -16,11 +16,7 @@
use std::fs::File;
use std::io::{Read, Write};
use crate::libwallet::slate_versions::v3::SlateV3;
use crate::libwallet::slate_versions::v4::SlateV4;
use crate::libwallet::{
Error, ErrorKind, Slate, SlateState, SlateVersion, VersionedBinSlate, VersionedSlate,
};
use crate::libwallet::{Error, ErrorKind, Slate, SlateVersion, VersionedBinSlate, VersionedSlate};
use crate::{SlateGetter, SlatePutter};
use grin_wallet_util::byte_ser;
use std::convert::TryFrom;
@ -41,56 +37,7 @@ impl SlatePutter for PathToSlate {
}*/
let mut pub_tx = File::create(&self.0)?;
// TODO:
let out_slate = {
// TODO: Remove post HF3
if slate.version_info.version == 2 || slate.version_info.version == 3 {
// if the slate we read in in V3 or 2 (holdover from 3.0.0), output a slate V3,
// which can be read by v3.x wallets
let v4_slate = SlateV4::from(slate.clone());
let mut v3_slate = SlateV3::try_from(&v4_slate)?;
// Fill in V3 participant IDs according to state
if slate.state == SlateState::Invoice1 {
for mut e in v3_slate.participant_data.iter_mut() {
if Some(e.public_blind_excess.clone()) == slate.participant_id {
e.id = 1;
} else {
e.id = 0;
}
}
}
if slate.state == SlateState::Invoice2 {
for mut e in v3_slate.participant_data.iter_mut() {
if Some(e.public_blind_excess.clone()) == slate.participant_id {
e.id = 0;
} else {
e.id = 1;
}
}
}
if slate.state == SlateState::Standard1 {
for mut e in v3_slate.participant_data.iter_mut() {
if Some(e.public_blind_excess.clone()) == slate.participant_id {
e.id = 0;
} else {
e.id = 1;
}
}
}
if slate.state == SlateState::Standard2 {
for mut e in v3_slate.participant_data.iter_mut() {
if Some(e.public_blind_excess.clone()) == slate.participant_id {
e.id = 1;
} else {
e.id = 0;
}
}
}
v3_slate.version_info.version = 3;
VersionedSlate::V3(v3_slate)
} else {
VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?
}
};
let out_slate = VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?;
if as_bin {
let bin_slate =
VersionedBinSlate::try_from(out_slate).map_err(|_| ErrorKind::SlateSer)?;

View file

@ -148,9 +148,6 @@ impl HttpSlateSender {
if supported_slate_versions.contains(&"V4".to_owned()) {
return Ok(SlateVersion::V4);
}
if supported_slate_versions.contains(&"V3".to_owned()) {
return Ok(SlateVersion::V3);
}
let report = "Unable to negotiate slate format with other wallet.".to_string();
error!("{}", report);
@ -189,18 +186,6 @@ impl SlateSender for HttpSlateSender {
let slate_send = match self.check_other_version(&url_str)? {
SlateVersion::V4 => VersionedSlate::into_version(slate.clone(), SlateVersion::V4)?,
SlateVersion::V3 => {
let mut slate = slate.clone();
//TODO: Fill out with Slate V4 incompatibilities
// * Will need to set particpant id to 1 manually if this is invoice
// * Set slate height manually
// * Reconcile unknown slate states from V3
if false {
return Err(ErrorKind::ClientCallback("feature x requested, but other wallet does not support feature x. Please urge other user to upgrade, or re-send tx without feature x".into()).into());
}
slate.version_info.version = 3;
VersionedSlate::into_version(slate, SlateVersion::V3)?
}
};
// Note: not using easy-jsonrpc as don't want the dependencies in this crate
let req = match finalize {

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet_libwallet"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Simple, private and scalable cryptocurrency implementation based on the MimbleWimble chain format."
license = "Apache-2.0"
@ -36,6 +36,6 @@ secrecy = "0.6"
bech32 = "0.7"
byteorder = "1.3"
grin_wallet_util = { path = "../util", version = "4.0.1-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.0.1-alpha.1" }
grin_wallet_util = { path = "../util", version = "4.1.0-alpha.1" }
grin_wallet_config = { path = "../config", version = "4.1.0-alpha.1" }

View file

@ -91,10 +91,7 @@ where
}
}
// if this is compact mode, we need to create the transaction now
if ret_slate.is_compact() {
ret_slate.tx = Some(Transaction::empty());
}
let height = w.last_confirmed_height()?;
let keychain = w.keychain(keychain_mask)?;
@ -121,15 +118,12 @@ where
p.receiver_signature = Some(sig);
}
// Can remove amount and fee now
// as well as sender's sig data
if ret_slate.is_compact() {
ret_slate.amount = 0;
ret_slate.fee = 0;
ret_slate.remove_other_sigdata(&keychain, &context.sec_nonce, &context.sec_key)?;
}
ret_slate.state = SlateState::Standard2;
Ok(ret_slate)
}
@ -150,12 +144,12 @@ where
let is_invoice = context.is_invoice;
if is_invoice {
check_ttl(w, &sl)?;
if sl.is_compact() {
let mut temp_ctx = context.clone();
temp_ctx.sec_key = context.initial_sec_key.clone();
temp_ctx.sec_nonce = context.initial_sec_nonce.clone();
selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &temp_ctx, false)?;
}
tx::complete_tx(&mut *w, keychain_mask, &mut sl, &context)?;
tx::update_stored_tx(&mut *w, keychain_mask, &context, &mut sl, true)?;
{
@ -164,9 +158,7 @@ where
batch.commit()?;
}
sl.state = SlateState::Invoice3;
if sl.is_compact() {
sl.amount = 0;
}
} else {
sl = owner_finalize(w, keychain_mask, slate)?;
}

View file

@ -541,9 +541,7 @@ where
batch.commit()?;
}
if slate.is_compact() {
slate.compact()?;
}
Ok(slate)
}
@ -595,9 +593,7 @@ where
batch.commit()?;
}
if slate.is_compact() {
slate.compact()?;
}
Ok(slate)
}
@ -650,9 +646,7 @@ where
}
// if this is compact mode, we need to create the transaction now
if ret_slate.is_compact() {
ret_slate.tx = Some(Transaction::empty());
}
// if self sending, make sure to store 'initiator' keys
let context_res = w.get_private_context(keychain_mask, slate.id.as_bytes());
@ -691,12 +685,8 @@ where
}
}
// adjust offset with inputs, repopulate inputs (initiator needs them for now)
// TODO: Revisit post-HF3
if ret_slate.is_compact() {
tx::sub_inputs_from_offset(&mut *w, keychain_mask, &context, &mut ret_slate)?;
selection::repopulate_tx(&mut *w, keychain_mask, &mut ret_slate, &context, false)?;
}
// Save the aggsig context in our DB for when we
// recieve the transaction back
@ -707,10 +697,8 @@ where
}
// Can remove amount as well as other sig data now
if ret_slate.is_compact() {
ret_slate.amount = 0;
ret_slate.remove_other_sigdata(&keychain, &context.sec_nonce, &context.sec_key)?;
}
ret_slate.state = SlateState::Invoice2;
Ok(ret_slate)
@ -728,16 +716,20 @@ where
K: Keychain + 'a,
{
let context = w.get_private_context(keychain_mask, slate.id.as_bytes())?;
let mut sl = slate.clone();
let mut excess_override = None;
if sl.is_compact() && sl.tx == None {
// attempt to repopulate if we're the initiator
let mut sl = slate.clone();
if sl.tx == None {
sl.tx = Some(Transaction::empty());
selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &context, true)?;
} else if sl.participant_data.len() == 1 {
}
if slate.participant_data.len() == 1 {
// purely for invoice workflow, payer needs the excess back temporarily for storage
excess_override = context.calculated_excess;
}
let height = w.w2n_client().get_chain_tip()?.0;
selection::lock_tx_context(
&mut *w,
@ -771,10 +763,8 @@ where
// as opposed to locking them prior to this stage, as the excess to this point
// will just be the change output
if sl.is_compact() {
tx::sub_inputs_from_offset(&mut *w, keychain_mask, &context, &mut sl)?;
selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &context, true)?;
}
tx::complete_tx(&mut *w, keychain_mask, &mut sl, &context)?;
tx::verify_slate_payment_proof(&mut *w, keychain_mask, &parent_key_id, &context, &sl)?;
@ -785,9 +775,8 @@ where
batch.commit()?;
}
sl.state = SlateState::Standard3;
if sl.is_compact() {
sl.amount = 0;
}
Ok(sl)
}

View file

@ -55,10 +55,6 @@ where
C: NodeClient + 'a,
K: Keychain + 'a,
{
//TODO: Revise HF3. If we're sending V4 slates, only include
// change outputs in excess sum
let include_inputs_in_sum = !slate.is_compact();
let (elems, inputs, change_amounts_derivations, fee) = select_send_tx(
wallet,
keychain_mask,
@ -69,7 +65,7 @@ where
change_outputs,
selection_strategy_is_use_all,
&parent_key_id,
include_inputs_in_sum,
false,
)?;
// Update the fee on the slate so we account for this when building the tx.

View file

@ -130,10 +130,6 @@ pub struct Slate {
pub payment_proof: Option<PaymentInfo>,
/// Kernel features arguments
pub kernel_features_args: Option<KernelFeaturesArgs>,
//TODO: Remove post HF3
/// participant ID, only stored for compatibility with V3 slates
/// not serialized anywhere
pub participant_id: Option<PublicKey>,
}
impl fmt::Display for Slate {
@ -216,10 +212,6 @@ impl Slate {
None => Err(ErrorKind::SlateTransactionRequired.into()),
}
}
/// Whether the slate started life as a compact slate
pub fn is_compact(&self) -> bool {
self.version_info.version >= 4
}
/// number of participants
pub fn num_participants(&self) -> u8 {
@ -229,14 +221,6 @@ impl Slate {
}
}
/// Compact the slate for initial sending, storing the excess + offset explicit
/// and removing my input/output data
/// This info must be stored in the context for repopulation later
pub fn compact(&mut self) -> Result<(), Error> {
self.tx = None;
Ok(())
}
/// Recieve a slate, upgrade it to the latest version internally
/// Throw error if this can't be done
pub fn deserialize_upgrade(slate_json: &str) -> Result<Slate, Error> {
@ -249,10 +233,16 @@ impl Slate {
pub fn upgrade(v_slate: VersionedSlate) -> Result<Slate, Error> {
let v4: SlateV4 = match v_slate {
VersionedSlate::V4(s) => s,
VersionedSlate::V3(s) => SlateV4::from(s),
};
Ok(v4.into())
}
/// Compact the slate for initial sending, storing the excess + offset explicit
/// and removing my input/output data
/// This info must be stored in the context for repopulation later
pub fn compact(&mut self) -> Result<(), Error> {
self.tx = None;
Ok(())
}
/// Create a new slate
pub fn blank(num_participants: u8, is_invoice: bool) -> Slate {
@ -280,7 +270,6 @@ impl Slate {
block_header_version: GRIN_BLOCK_HEADER_VERSION,
},
payment_proof: None,
participant_id: None,
kernel_features_args: None,
}
}
@ -352,15 +341,8 @@ impl Slate {
where
K: Keychain,
{
// Whoever does this first generates the offset
// TODO: Remove HF3
if self.participant_data.is_empty() && !self.is_compact() {
self.generate_offset(keychain, sec_key, use_test_rng)?;
}
// Always choose my part of the offset, and subtract from my excess
if self.is_compact() {
self.generate_offset(keychain, sec_key, use_test_rng)?;
}
self.add_participant_info(keychain, &sec_key, &sec_nonce, None)?;
Ok(())
}
@ -414,9 +396,8 @@ impl Slate {
K: Keychain,
{
// TODO: Note we're unable to verify fees in this instance
if !self.is_compact() {
self.check_fees()?;
}
// Left here is a reminder that we no longer check fees
// self.check_fees()?;
self.verify_part_sigs(keychain.secp())?;
let sig_part = aggsig::calculate_partial_sig(
@ -534,7 +515,6 @@ impl Slate {
public_nonce: pub_nonce,
part_sig: part_sig,
});
self.participant_id = Some(pub_key);
Ok(())
}
@ -565,18 +545,12 @@ impl Slate {
}
};
if self.is_compact() {
let total_offset = keychain.blind_sum(
&BlindSum::new()
.add_blinding_factor(self.offset.clone())
.add_blinding_factor(my_offset.clone()),
)?;
self.offset = total_offset;
} else {
//TODO: Remove HF3
self.tx_or_err_mut()?.offset = my_offset.clone();
self.offset = my_offset.clone();
};
let adjusted_offset = keychain.blind_sum(
&BlindSum::new()
@ -765,7 +739,6 @@ impl From<Slate> for SlateV4 {
participant_data,
version_info,
payment_proof,
participant_id: _participant_id,
kernel_features_args,
} = slate.clone();
let participant_data = map_vec!(participant_data, |data| ParticipantDataV4::from(data));
@ -812,7 +785,6 @@ impl From<&Slate> for SlateV4 {
participant_data,
version_info,
payment_proof,
participant_id: _participant_id,
kernel_features_args,
} = slate;
let num_parts = *num_parts;
@ -1090,7 +1062,6 @@ impl From<SlateV4> for Slate {
participant_data,
version_info,
payment_proof,
participant_id: None,
kernel_features_args,
}
}

View file

@ -14,21 +14,18 @@
//! This module contains old slate versions and conversions to the newest slate version
//! Used for serialization and deserialization of slates in a backwards compatible way.
//! Versions earlier than V2 are removed for the 2.0.0 release, but versioning code
//! Versions earlier than V3 are removed for the 4.0.0 release, but versioning code
//! remains for future needs
use crate::slate::Slate;
use crate::slate_versions::v3::{CoinbaseV3, SlateV3};
use crate::slate_versions::v4::{CoinbaseV4, SlateV4};
use crate::slate_versions::v4_bin::SlateV4Bin;
use crate::types::CbData;
use crate::{Error, ErrorKind};
use crate::Error;
use std::convert::TryFrom;
pub mod ser;
#[allow(missing_docs)]
pub mod v3;
#[allow(missing_docs)]
pub mod v4;
#[allow(missing_docs)]
@ -45,8 +42,6 @@ pub const GRIN_BLOCK_HEADER_VERSION: u16 = 3;
pub enum SlateVersion {
/// V4 (most current)
V4,
/// V3 (3.0.0 - 4.0.0)
V3,
}
#[derive(Debug, Serialize, Deserialize)]
@ -56,8 +51,6 @@ pub enum SlateVersion {
pub enum VersionedSlate {
/// Current (4.0.0 Onwards )
V4(SlateV4),
/// V2 (2.0.0 - 3.0.0)
V3(SlateV3),
}
impl VersionedSlate {
@ -65,7 +58,6 @@ impl VersionedSlate {
pub fn version(&self) -> SlateVersion {
match *self {
VersionedSlate::V4(_) => SlateVersion::V4,
VersionedSlate::V3(_) => SlateVersion::V3,
}
}
@ -73,11 +65,6 @@ impl VersionedSlate {
pub fn into_version(slate: Slate, version: SlateVersion) -> Result<VersionedSlate, Error> {
match version {
SlateVersion::V4 => Ok(VersionedSlate::V4(slate.into())),
SlateVersion::V3 => {
let s = SlateV4::from(slate);
let s = SlateV3::try_from(&s)?;
Ok(VersionedSlate::V3(s))
}
}
}
}
@ -86,10 +73,6 @@ impl From<VersionedSlate> for Slate {
fn from(slate: VersionedSlate) -> Slate {
match slate {
VersionedSlate::V4(s) => Slate::from(s),
VersionedSlate::V3(s) => {
let s = SlateV4::from(s);
Slate::from(s)
}
}
}
}
@ -108,11 +91,6 @@ impl TryFrom<VersionedSlate> for VersionedBinSlate {
fn try_from(slate: VersionedSlate) -> Result<VersionedBinSlate, Error> {
match slate {
VersionedSlate::V4(s) => Ok(VersionedBinSlate::V4(SlateV4Bin(s))),
VersionedSlate::V3(_) => {
return Err(
ErrorKind::Compatibility("V3 Slate does not support binary".to_owned()).into(),
)
}
}
}
}
@ -132,8 +110,6 @@ impl From<VersionedBinSlate> for VersionedSlate {
pub enum VersionedCoinbase {
/// Current supported coinbase version.
V4(CoinbaseV4),
/// Previous supported coinbase version.
V3(CoinbaseV3),
}
impl VersionedCoinbase {
@ -141,7 +117,6 @@ impl VersionedCoinbase {
pub fn into_version(cb: CbData, version: SlateVersion) -> VersionedCoinbase {
match version {
SlateVersion::V4 => VersionedCoinbase::V4(cb.into()),
SlateVersion::V3 => VersionedCoinbase::V3(cb.into()),
}
}
}

View file

@ -1,226 +0,0 @@
// Copyright 2020 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 V3 of the slate (grin-wallet 3.0.0)
//! Changes from V2:
//! * Addition of payment_proof (PaymentInfo struct)
//! * Addition of a u64 ttl_cutoff_height field
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::ser as dalek_ser;
use crate::slate_versions::v4::{OutputV4, TxKernelV4};
use crate::types::CbData;
use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature;
use uuid::Uuid;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SlateV3 {
/// Versioning info
pub version_info: VersionCompatInfoV3,
/// 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: TransactionV3,
/// 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,
/// TTL, the block height at which wallets
/// should refuse to process the transaction and unlock all
/// associated outputs
#[serde(default = "default_ttl_none")]
#[serde(with = "secp_ser::opt_string_or_u64")]
pub ttl_cutoff_height: Option<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<ParticipantDataV3>,
/// Payment Proof
#[serde(default = "default_payment_none")]
pub payment_proof: Option<PaymentInfoV3>,
}
fn default_payment_none() -> Option<PaymentInfoV3> {
None
}
fn default_ttl_none() -> Option<u64> {
None
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct VersionCompatInfoV3 {
/// 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 ParticipantDataV3 {
/// 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>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PaymentInfoV3 {
#[serde(with = "dalek_ser::dalek_pubkey_serde")]
pub sender_address: DalekPublicKey,
#[serde(with = "dalek_ser::dalek_pubkey_serde")]
pub receiver_address: DalekPublicKey,
#[serde(with = "dalek_ser::option_dalek_sig_serde")]
pub receiver_signature: Option<DalekSignature>,
}
/// A transaction
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TransactionV3 {
/// 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: TransactionBodyV3,
}
/// TransactionBody is a common abstraction for transaction and block
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TransactionBodyV3 {
/// List of inputs spent by the transaction.
pub inputs: Vec<InputV3>,
/// List of outputs the transaction produces.
pub outputs: Vec<OutputV3>,
/// List of kernels that make up this transaction (usually a single kernel).
pub kernels: Vec<TxKernelV3>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InputV3 {
/// 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 OutputV3 {
/// 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 TxKernelV3 {
/// 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 CoinbaseV3 {
/// Output
pub output: OutputV3,
/// Kernel
pub kernel: TxKernelV3,
/// Key Id
pub key_id: Option<Identifier>,
}
// Coinbase data to versioned.
impl From<CbData> for CoinbaseV3 {
fn from(cb: CbData) -> CoinbaseV3 {
let output = OutputV4::from(&cb.output);
let output = OutputV3::from(&output);
let kernel = TxKernelV4::from(&cb.kernel);
let kernel = TxKernelV3::from(&kernel);
CoinbaseV3 {
output,
kernel,
key_id: cb.key_id,
}
}
}

View file

@ -53,9 +53,7 @@
//! * The `receiver_signature` field is renamed to `rsig`
//! * `rsig` may be omitted if it has not yet been filled out
use crate::grin_core::core::transaction::KernelFeatures;
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;
@ -63,17 +61,10 @@ use crate::grin_util::secp::pedersen::{Commitment, RangeProof};
use crate::grin_util::secp::Signature;
use crate::slate::CompatKernelFeatures;
use crate::slate_versions::ser;
use crate::{Error, ErrorKind};
use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature;
use std::convert::TryFrom;
use uuid::Uuid;
use crate::slate_versions::v3::{
InputV3, OutputV3, ParticipantDataV3, PaymentInfoV3, SlateV3, TransactionBodyV3, TransactionV3,
TxKernelV3, VersionCompatInfoV3,
};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SlateV4 {
// Required Fields
@ -463,471 +454,3 @@ pub struct CoinbaseV4 {
/// Key Id
pub key_id: Option<Identifier>,
}
// V3 to V4 For Slate
impl From<SlateV3> for SlateV4 {
fn from(slate: SlateV3) -> SlateV4 {
let SlateV3 {
version_info,
num_participants,
id,
tx,
amount,
fee,
height: _,
lock_height,
ttl_cutoff_height,
participant_data,
payment_proof,
} = slate.clone();
let participant_data = map_vec!(participant_data, |data| ParticipantDataV4::from(data));
let ver = VersionCompatInfoV4::from(&version_info);
let payment_proof = match payment_proof {
Some(p) => Some(PaymentInfoV4::from(&p)),
None => None,
};
let ttl_cutoff_height = match ttl_cutoff_height {
None => 0,
Some(n) => n,
};
let (feat, feat_args) = match lock_height {
0 => (0, None),
n => (2, Some(KernelFeaturesArgsV4 { lock_hgt: n })),
};
SlateV4 {
ver,
num_parts: num_participants as u8,
id,
sta: SlateStateV4::Unknown,
coms: (&slate).into(),
amt: amount,
fee,
feat,
ttl: ttl_cutoff_height,
off: tx.offset,
sigs: participant_data,
proof: payment_proof,
feat_args,
}
}
}
impl From<&SlateV3> for Option<Vec<CommitsV4>> {
fn from(slate: &SlateV3) -> Option<Vec<CommitsV4>> {
let mut ret_vec = vec![];
for i in slate.tx.body.inputs.iter() {
ret_vec.push(CommitsV4 {
f: i.features.into(),
c: i.commit,
p: None,
});
}
for o in slate.tx.body.outputs.iter() {
ret_vec.push(CommitsV4 {
f: o.features.into(),
c: o.commit,
p: Some(o.proof),
});
}
Some(ret_vec)
}
}
impl From<&ParticipantDataV3> for ParticipantDataV4 {
fn from(data: &ParticipantDataV3) -> ParticipantDataV4 {
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;
ParticipantDataV4 {
xs: public_blind_excess,
nonce: public_nonce,
part: part_sig,
}
}
}
impl From<&VersionCompatInfoV3> for VersionCompatInfoV4 {
fn from(data: &VersionCompatInfoV3) -> VersionCompatInfoV4 {
let VersionCompatInfoV3 {
version,
orig_version,
block_header_version,
} = data;
let version = *version;
let _orig_version = *orig_version;
let block_header_version = *block_header_version;
VersionCompatInfoV4 {
version,
block_header_version,
}
}
}
impl From<TransactionV3> for TransactionV4 {
fn from(tx: TransactionV3) -> TransactionV4 {
let TransactionV3 { offset, body } = tx;
let body = TransactionBodyV4::from(&body);
TransactionV4 { offset, body }
}
}
impl From<&TransactionBodyV3> for TransactionBodyV4 {
fn from(body: &TransactionBodyV3) -> TransactionBodyV4 {
let TransactionBodyV3 {
inputs,
outputs,
kernels,
} = body;
let inputs = map_vec!(inputs, |inp| InputV4::from(inp));
let outputs = map_vec!(outputs, |out| OutputV4::from(out));
let kernels = map_vec!(kernels, |kern| TxKernelV4::from(kern));
TransactionBodyV4 {
ins: inputs,
outs: outputs,
kers: kernels,
}
}
}
impl From<&InputV3> for InputV4 {
fn from(input: &InputV3) -> InputV4 {
let InputV3 { features, commit } = *input;
InputV4 {
features: features.into(),
commit,
}
}
}
impl From<&OutputV3> for OutputV4 {
fn from(output: &OutputV3) -> OutputV4 {
let OutputV3 {
features,
commit,
proof,
} = *output;
OutputV4 {
features: features.into(),
com: commit,
prf: proof,
}
}
}
impl From<&TxKernelV3> for TxKernelV4 {
fn from(kernel: &TxKernelV3) -> TxKernelV4 {
let (fee, lock_height) = (kernel.fee, kernel.lock_height);
TxKernelV4 {
features: kernel.features,
fee,
lock_height,
excess: kernel.excess,
excess_sig: kernel.excess_sig,
}
}
}
impl From<&PaymentInfoV3> for PaymentInfoV4 {
fn from(input: &PaymentInfoV3) -> PaymentInfoV4 {
let PaymentInfoV3 {
sender_address,
receiver_address,
receiver_signature,
} = *input;
PaymentInfoV4 {
saddr: sender_address,
raddr: receiver_address,
rsig: receiver_signature,
}
}
}
// V4 to V3
#[allow(unused_variables)]
impl TryFrom<&SlateV4> for SlateV3 {
type Error = Error;
fn try_from(slate: &SlateV4) -> Result<SlateV3, Error> {
let SlateV4 {
num_parts: num_participants,
id,
sta: _,
coms,
amt: amount,
fee,
feat,
ttl: ttl_cutoff_height,
off: offset,
sigs: participant_data,
ver,
proof: payment_proof,
feat_args,
} = slate;
let num_participants = match *num_participants {
0 => 2,
n => n,
};
let id = *id;
let amount = *amount;
let fee = *fee;
// Match on kernel feature variant:
// 0: plain
// 1: coinbase (invalid)
// 2: height locked (with associated lock_height)
// 3: NRD (with associated relative_height)
// Anything else is unknown.
let lock_height = match feat {
0 => 0,
1 => return Err(ErrorKind::InvalidKernelFeatures(1).into()),
2 => match feat_args {
None => return Err(ErrorKind::KernelFeaturesMissing("lock_hgt".to_owned()).into()),
Some(h) => h.lock_hgt,
},
3 => match feat_args {
None => return Err(ErrorKind::KernelFeaturesMissing("lock_hgt".to_owned()).into()),
Some(h) => h.lock_hgt,
},
n => return Err(ErrorKind::UnknownKernelFeatures(*n).into()),
};
let participant_data = map_vec!(participant_data, |data| ParticipantDataV3::from(data));
let version_info = VersionCompatInfoV3::from(ver);
let payment_proof = match payment_proof {
Some(p) => Some(PaymentInfoV3::from(p)),
None => None,
};
let tx: Option<TransactionV3> = slate.into();
let tx = match tx {
Some(t) => TransactionV3::from(t),
None => {
return Err(ErrorKind::SlateInvalidDowngrade(
"Full transaction info required".to_owned(),
)
.into())
}
};
let ttl_cutoff_height = match *ttl_cutoff_height {
0 => None,
n => Some(n),
};
Ok(SlateV3 {
num_participants: num_participants as usize,
id,
tx,
amount,
fee,
height: 0,
lock_height,
ttl_cutoff_height,
participant_data,
version_info,
payment_proof,
})
}
}
// Node's Transaction object and lock height to SlateV4 `coms`
impl From<&SlateV4> for Option<TransactionV3> {
fn from(slate: &SlateV4) -> Option<TransactionV3> {
let res = crate::slate::tx_from_slate_v4(slate);
let tx = match res {
Some(tx) => tx,
None => return None,
};
let mut out_fee = 0;
let mut out_lock_height = 0;
let txv3 = TransactionV3 {
offset: tx.offset,
body: TransactionBodyV3 {
inputs: tx
.body
.inputs
.iter()
.map(|i| InputV3 {
features: i.features,
commit: i.commit,
})
.collect(),
outputs: tx
.body
.outputs
.iter()
.map(|o| OutputV3 {
features: o.features,
commit: o.commit,
proof: o.proof,
})
.collect(),
kernels: tx
.body
.kernels
.iter()
.map(|k| TxKernelV3 {
features: match k.features {
KernelFeatures::Plain { fee } => {
out_fee = fee;
CompatKernelFeatures::Plain
}
KernelFeatures::Coinbase => CompatKernelFeatures::Coinbase,
KernelFeatures::HeightLocked { fee, lock_height } => {
out_fee = fee;
out_lock_height = lock_height;
CompatKernelFeatures::HeightLocked
}
KernelFeatures::NoRecentDuplicate {
fee,
relative_height,
} => {
out_fee = fee;
out_lock_height = relative_height.into();
CompatKernelFeatures::NoRecentDuplicate
}
},
fee: out_fee,
lock_height: out_lock_height,
excess: k.excess,
excess_sig: k.excess_sig,
})
.collect(),
},
};
Some(txv3)
}
}
impl From<&ParticipantDataV4> for ParticipantDataV3 {
fn from(data: &ParticipantDataV4) -> ParticipantDataV3 {
let ParticipantDataV4 {
xs: public_blind_excess,
nonce: public_nonce,
part: part_sig,
} = data;
let public_blind_excess = *public_blind_excess;
let public_nonce = *public_nonce;
let part_sig = *part_sig;
ParticipantDataV3 {
id: 0,
public_blind_excess,
public_nonce,
part_sig,
message: None,
message_sig: None,
}
}
}
impl From<&VersionCompatInfoV4> for VersionCompatInfoV3 {
fn from(data: &VersionCompatInfoV4) -> VersionCompatInfoV3 {
let VersionCompatInfoV4 {
version,
block_header_version,
} = data;
let version = *version;
let orig_version = version;
let block_header_version = *block_header_version;
VersionCompatInfoV3 {
version,
orig_version,
block_header_version,
}
}
}
impl From<TransactionV4> for TransactionV3 {
fn from(tx: TransactionV4) -> TransactionV3 {
let TransactionV4 { offset, body } = tx;
let body = TransactionBodyV3::from(&body);
TransactionV3 { offset, body }
}
}
impl From<&TransactionV4> for TransactionV3 {
fn from(tx: &TransactionV4) -> TransactionV3 {
let TransactionV4 { offset, body } = tx;
let offset = offset.clone();
let body = TransactionBodyV3::from(body);
TransactionV3 { offset, body }
}
}
impl From<&TransactionBodyV4> for TransactionBodyV3 {
fn from(body: &TransactionBodyV4) -> TransactionBodyV3 {
let TransactionBodyV4 { ins, outs, kers } = body;
let inputs = map_vec!(ins, |inp| InputV3::from(inp));
let outputs = map_vec!(outs, |out| OutputV3::from(out));
let kernels = map_vec!(kers, |kern| TxKernelV3::from(kern));
TransactionBodyV3 {
inputs,
outputs,
kernels,
}
}
}
impl From<&InputV4> for InputV3 {
fn from(input: &InputV4) -> InputV3 {
let InputV4 { features, commit } = *input;
InputV3 {
features: features.into(),
commit,
}
}
}
impl From<&OutputV4> for OutputV3 {
fn from(output: &OutputV4) -> OutputV3 {
let OutputV4 {
features,
com: commit,
prf: proof,
} = *output;
OutputV3 {
features: features.into(),
commit,
proof,
}
}
}
impl From<&TxKernelV4> for TxKernelV3 {
fn from(kernel: &TxKernelV4) -> TxKernelV3 {
TxKernelV3 {
features: kernel.features,
fee: kernel.fee,
lock_height: kernel.lock_height,
excess: kernel.excess,
excess_sig: kernel.excess_sig,
}
}
}
impl From<&PaymentInfoV4> for PaymentInfoV3 {
fn from(input: &PaymentInfoV4) -> PaymentInfoV3 {
let PaymentInfoV4 {
saddr: sender_address,
raddr: receiver_address,
rsig: receiver_signature,
} = *input;
PaymentInfoV3 {
sender_address,
receiver_address,
receiver_signature,
}
}
}

View file

@ -150,11 +150,6 @@ subcommands:
short: u
long: outfile
takes_value: true
#TODO: Remove HF3
- v4:
help: Output a V4 slate prior to HF3 block
long: v4
takes_value: false
- unpack:
about: Unpack and display an armored Slatepack Message, decrypting if possible
args:
@ -217,11 +212,6 @@ subcommands:
short: u
long: outfile
takes_value: true
#TODO: Remove HF3
- v4:
help: Output a V4 slate prior to HF3 block
long: v4
takes_value: false
- pay:
about: Spend coins to pay the provided invoice transaction
args:

View file

@ -502,9 +502,6 @@ pub fn parse_send_args(args: &ArgMatches) -> Result<command::SendArgs, ParseErro
// max_outputs
let max_outputs = 500;
// TODO: Remove HF3
let output_v4_slate = args.is_present("v4");
// target slate version to create/send
let target_slate_version = {
match args.is_present("slate_version") {
@ -543,7 +540,6 @@ pub fn parse_send_args(args: &ArgMatches) -> Result<command::SendArgs, ParseErro
payment_proof_address,
ttl_blocks,
target_slate_version: target_slate_version,
output_v4_slate,
outfile,
skip_tor: args.is_present("manual"),
})
@ -658,9 +654,6 @@ pub fn parse_issue_invoice_args(
}
};
// TODO: Remove HF3
let output_v4_slate = args.is_present("v4");
// target slate version to create
let target_slate_version = {
match args.is_present("slate_version") {
@ -682,7 +675,6 @@ pub fn parse_issue_invoice_args(
Ok(command::IssueInvoiceArgs {
dest: dest.into(),
output_v4_slate,
issue_args: IssueInvoiceTxArgs {
dest_acct_name: None,
amount,

View file

@ -1,6 +1,6 @@
[package]
name = "grin_wallet_util"
version = "4.0.1-alpha.1"
version = "4.1.0-alpha.1"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Util, for generic utilities and to re-export grin crates"
license = "Apache-2.0"