mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 07:11:36 +02:00
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:
+4
-4
@@ -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" }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user