Merge 2.0.0 branch into master (#164)

* create 2.0.0 branch

* V0/V1 Slate Removal + Grin Header Version Bump (#140)

* Remove V0 and V1 Slates from Wallet

* rustfmt

* V1 API + V2 wallet to wallet impl (#144)

* remove v1 API

* rustfmt

* convert http adapter to use V2 api

* rustfmt

* V2 API conversion Pt2 - Check version (#146)

* call check_version on wallet before http send

* rustfmt

* Support new Bulletproof rewind scheme (#122)

* Restore with LegacyProofBuilder

* Switch to ProofBuilder at HF block

* Switch proof builder for coinbase outputs at hard fork

* Use valid_header_version to switch proof builder

* Fix compilation errors

* Use legacy proof builder for AutomatedTesting chain type

* Add macro to avoid duplicate code

* Read version info from server, react accordingly (#154)

* read and parse version, bump hf

* rustfmt

* add foreign api middleware check

* rustfmt

* add middleware checks

* rustfmt

* add check for incoming pre-hf slates

* api tests

* Add double rewind period (#155)

* Add double rewind period

* Simplify restore

* Fix comment

* bump imported version for beta release

* version bump for next (potential) release

* Provide more specific error when other wallet is outdated (#162)

* add appropriate error message when other wallet is out of date

* rustfmt

* missing cargo.lock
This commit is contained in:
Yeastplume
2019-06-27 10:41:05 +01:00
committed by GitHub
parent c7a00478aa
commit 64e8c48c35
37 changed files with 935 additions and 4061 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "grin_wallet_impls"
version = "1.1.1-beta.1"
version = "2.0.0-beta.2"
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
description = "Concrete types derived from libwallet traits"
license = "Apache-2.0"
@@ -26,7 +26,7 @@ tokio-retry = "0.1"
uuid = { version = "0.7", features = ["serde", "v4"] }
chrono = { version = "0.4.4", features = ["serde"] }
grin_wallet_util = { path = "../util", version = "1.1.1-beta.1" }
grin_wallet_util = { path = "../util", version = "2.0.0-beta.2" }
grin_wallet_libwallet = { path = "../libwallet", version = "1.1.1-beta.1" }
grin_wallet_config = { path = "../config", version = "1.1.1-beta.1" }
grin_wallet_libwallet = { path = "../libwallet", version = "2.0.0-beta.2" }
grin_wallet_config = { path = "../config", version = "2.0.0-beta.2" }
+92 -5
View File
@@ -12,14 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//TODO: Update to V2 API when after Hard fork
/// HTTP Wallet 'plugin' implementation
use crate::api;
use crate::libwallet::{Error, ErrorKind, Slate};
use crate::WalletCommAdapter;
use config::WalletConfig;
use serde::Serialize;
use serde_json::{json, Value};
use std::collections::HashMap;
#[derive(Clone)]
@@ -30,6 +29,63 @@ impl HTTPWalletCommAdapter {
pub fn new() -> Box<dyn WalletCommAdapter> {
Box::new(HTTPWalletCommAdapter {})
}
/// Check version of the other wallet
fn check_other_version(&self, url: &str) -> Result<(), Error> {
let req = json!({
"jsonrpc": "2.0",
"method": "check_version",
"id": 1,
"params": []
});
let res: String = post(url, None, &req).map_err(|e| {
let mut report = format!("Performing version check (is recipient listening?): {}", e);
let err_string = format!("{}", e);
if err_string.contains("404") {
// Report that the other version of the wallet is out of date
report = format!(
"Other wallet is incompatible and requires an upgrade. \
Please urge the other wallet owner to upgrade and try the transaction again."
);
}
error!("{}", report);
ErrorKind::ClientCallback(report)
})?;
let res: Value = serde_json::from_str(&res).unwrap();
trace!("Response: {}", res);
if res["error"] != json!(null) {
let report = format!(
"Posting transaction slate: Error: {}, Message: {}",
res["error"]["code"], res["error"]["message"]
);
error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into());
}
let resp_value = res["result"]["Ok"].clone();
trace!("resp_value: {}", resp_value.clone());
let foreign_api_version: u16 =
serde_json::from_value(resp_value["foreign_api_version"].clone()).unwrap();
let supported_slate_versions: Vec<String> =
serde_json::from_value(resp_value["supported_slate_versions"].clone()).unwrap();
// trivial tests for now, but will be expanded later
if foreign_api_version < 2 {
let report = format!("Other wallet reports unrecognized API format.");
error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into());
}
if !supported_slate_versions.contains(&"V2".to_owned()) {
let report = format!("Unable to negotiate slate format with other wallet.");
error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into());
}
Ok(())
}
}
impl WalletCommAdapter for HTTPWalletCommAdapter {
@@ -46,14 +102,45 @@ impl WalletCommAdapter for HTTPWalletCommAdapter {
error!("{}", err_str,);
Err(ErrorKind::Uri)?
}
let url = format!("{}/v1/wallet/foreign/receive_tx", dest);
let url = format!("{}/v2/foreign", dest);
debug!("Posting transaction slate to {}", url);
let res: String = post(url.as_str(), None, &slate).map_err(|e| {
self.check_other_version(&url)?;
// 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,
null,
null
]
});
trace!("Sending receive_tx request: {}", req);
let res: String = post(url.as_str(), None, &req).map_err(|e| {
let report = format!("Posting transaction slate (is recipient listening?): {}", e);
error!("{}", report);
ErrorKind::ClientCallback(report)
})?;
let slate = Slate::deserialize_upgrade(&res).map_err(|_| ErrorKind::SlateDeser)?;
let res: Value = serde_json::from_str(&res).unwrap();
trace!("Response: {}", res);
if res["error"] != json!(null) {
let report = format!(
"Posting transaction slate: Error: {}, Message: {}",
res["error"]["code"], res["error"]["message"]
);
error!("{}", report);
return Err(ErrorKind::ClientCallback(report).into());
}
let slate_value = res["result"]["Ok"].clone();
trace!("slate_value: {}", slate_value);
let slate = Slate::deserialize_upgrade(&serde_json::to_string(&slate_value).unwrap())
.map_err(|_| ErrorKind::SlateDeser)?;
Ok(slate)
}
+6 -3
View File
@@ -25,7 +25,7 @@ use uuid::Uuid;
use crate::blake2::blake2b::Blake2b;
use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain, SwitchCommitmentType};
use crate::store::{self, option_to_not_found, to_key, to_key_u64};
use crate::core::core::Transaction;
@@ -68,7 +68,7 @@ fn private_ctx_xor_keys<K>(
where
K: Keychain,
{
let root_key = keychain.derive_key(0, &K::root_key_id())?;
let root_key = keychain.derive_key(0, &K::root_key_id(), &SwitchCommitmentType::Regular)?;
// derive XOR values for storing secret values in DB
// h(root_key|slate_id|"blind")
@@ -203,7 +203,10 @@ where
Ok(None)
} else {
Ok(Some(util::to_hex(
self.keychain().commit(amount, &id)?.0.to_vec(),
self.keychain()
.commit(amount, &id, &SwitchCommitmentType::Regular)?
.0
.to_vec(), // TODO: proper support for different switch commitment schemes
)))
}
}
+34 -3
View File
@@ -17,7 +17,7 @@
use futures::{stream, Stream};
use crate::libwallet::{NodeClient, TxWrapper};
use crate::libwallet::{NodeClient, NodeVersionInfo, TxWrapper};
use std::collections::HashMap;
use tokio::runtime::Runtime;
@@ -30,6 +30,7 @@ use crate::util::secp::pedersen;
pub struct HTTPNodeClient {
node_url: String,
node_api_secret: Option<String>,
node_version_info: Option<NodeVersionInfo>,
}
impl HTTPNodeClient {
@@ -38,6 +39,7 @@ impl HTTPNodeClient {
HTTPNodeClient {
node_url: node_url.to_owned(),
node_api_secret: node_api_secret,
node_version_info: None,
}
}
@@ -63,14 +65,43 @@ impl NodeClient for HTTPNodeClient {
self.node_api_secret = node_api_secret;
}
fn get_version_info(&mut self) -> Option<NodeVersionInfo> {
if let Some(v) = self.node_version_info.as_ref() {
return Some(v.clone());
}
let url = format!("{}/v1/version", self.node_url());
let mut retval =
match api::client::get::<NodeVersionInfo>(url.as_str(), self.node_api_secret()) {
Ok(n) => n,
Err(e) => {
// If node isn't available, allow offline functions
// unfortunately have to parse string due to error structure
let err_string = format!("{}", e);
if err_string.contains("404") {
return Some(NodeVersionInfo {
node_version: "1.0.0".into(),
block_header_version: 1,
verified: Some(false),
});
} else {
error!("Unable to contact Node to get version info: {}", e);
return None;
}
}
};
retval.verified = Some(true);
self.node_version_info = Some(retval.clone());
Some(retval)
}
/// Posts a transaction to a grin node
fn post_tx(&self, tx: &TxWrapper, fluff: bool) -> Result<(), libwallet::Error> {
let url;
let dest = self.node_url();
if fluff {
url = format!("{}/v1/pool/push?fluff", dest);
url = format!("{}/v1/pool/push_tx?fluff", dest);
} else {
url = format!("{}/v1/pool/push", dest);
url = format!("{}/v1/pool/push_tx", dest);
}
let res = api::client::post_no_ret(url.as_str(), self.node_api_secret(), tx);
if let Err(e) = res {
+4 -1
View File
@@ -26,7 +26,7 @@ use crate::core::global::{set_mining_mode, ChainTypes};
use crate::core::{pow, ser};
use crate::keychain::Keychain;
use crate::libwallet::api_impl::foreign;
use crate::libwallet::{NodeClient, Slate, TxWrapper, WalletInst};
use crate::libwallet::{NodeClient, NodeVersionInfo, Slate, TxWrapper, WalletInst};
use crate::util;
use crate::util::secp::pedersen;
use crate::util::secp::pedersen::Commitment;
@@ -402,6 +402,9 @@ impl NodeClient for LocalWalletClient {
}
fn set_node_url(&mut self, _node_url: &str) {}
fn set_node_api_secret(&mut self, _node_api_secret: Option<String>) {}
fn get_version_info(&mut self) -> Option<NodeVersionInfo> {
None
}
/// Posts a transaction to a grin node
/// In this case it will create a new block with award rewarded to
fn post_tx(&self, tx: &TxWrapper, _fluff: bool) -> Result<(), libwallet::Error> {