mirror of
https://github.com/jwinterm/grin-wallet.git
synced 2026-10-17 15:21:39 +02:00
Update transactions via kernel where necessary (#220)
* add test for no change output scenario * rustfmt * add kernel lookup functionality to transaction retrievals * rustfmt * updates and fixes for no-change invoice workflow, test implementations * rustfmt
This commit is contained in:
@@ -15,6 +15,7 @@ failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
futures = "0.1"
|
||||
rand = "0.5"
|
||||
semver = "0.9"
|
||||
serde = "1"
|
||||
serde_derive = "1"
|
||||
serde_json = "1"
|
||||
|
||||
@@ -17,14 +17,17 @@
|
||||
|
||||
use futures::{stream, Stream};
|
||||
|
||||
use crate::api::LocatedTxKernel;
|
||||
use crate::core::core::TxKernel;
|
||||
use crate::libwallet::{NodeClient, NodeVersionInfo, TxWrapper};
|
||||
use semver::Version;
|
||||
use std::collections::HashMap;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::api;
|
||||
use crate::libwallet;
|
||||
use crate::util;
|
||||
use crate::util::secp::pedersen;
|
||||
use crate::util::{self, to_hex};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HTTPNodeClient {
|
||||
@@ -127,6 +130,55 @@ impl NodeClient for HTTPNodeClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get kernel implementation
|
||||
fn get_kernel(
|
||||
&mut self,
|
||||
excess: &pedersen::Commitment,
|
||||
min_height: Option<u64>,
|
||||
max_height: Option<u64>,
|
||||
) -> Result<Option<(TxKernel, u64, u64)>, libwallet::Error> {
|
||||
let version = self
|
||||
.get_version_info()
|
||||
.ok_or(libwallet::ErrorKind::ClientCallback(
|
||||
"Unable to get version".into(),
|
||||
))?;
|
||||
let version = Version::parse(&version.node_version)
|
||||
.map_err(|_| libwallet::ErrorKind::ClientCallback("Unable to parse version".into()))?;
|
||||
if version <= Version::new(2, 0, 0) {
|
||||
return Err(libwallet::ErrorKind::ClientCallback(
|
||||
"Kernel lookup not supported by node, please upgrade it".into(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let mut query = String::new();
|
||||
if let Some(h) = min_height {
|
||||
query += &format!("min_height={}", h);
|
||||
}
|
||||
if let Some(h) = max_height {
|
||||
if query.len() > 0 {
|
||||
query += "&";
|
||||
}
|
||||
query += &format!("max_height={}", h);
|
||||
}
|
||||
if query.len() > 0 {
|
||||
query.insert_str(0, "?");
|
||||
}
|
||||
|
||||
let url = format!(
|
||||
"{}/v1/chain/kernels/{}{}",
|
||||
self.node_url(),
|
||||
to_hex(excess.0.to_vec()),
|
||||
query
|
||||
);
|
||||
let res: Option<LocatedTxKernel> = api::client::get(url.as_str(), self.node_api_secret())
|
||||
.map_err(|e| {
|
||||
libwallet::ErrorKind::ClientCallback(format!("Kernel lookup: {}", e))
|
||||
})?;
|
||||
|
||||
Ok(res.map(|k| (k.tx_kernel, k.height, k.mmr_index)))
|
||||
}
|
||||
|
||||
/// Retrieve outputs from node
|
||||
fn get_outputs_from_node(
|
||||
&self,
|
||||
|
||||
@@ -52,6 +52,23 @@ fn get_output_local(chain: &chain::Chain, commit: &pedersen::Commitment) -> Opti
|
||||
None
|
||||
}
|
||||
|
||||
/// Get a kernel from the chain locally
|
||||
fn get_kernel_local(
|
||||
chain: Arc<chain::Chain>,
|
||||
excess: &pedersen::Commitment,
|
||||
min_height: Option<u64>,
|
||||
max_height: Option<u64>,
|
||||
) -> Option<api::LocatedTxKernel> {
|
||||
chain
|
||||
.get_kernel_height(&excess, min_height, max_height)
|
||||
.unwrap()
|
||||
.map(|(tx_kernel, height, mmr_index)| api::LocatedTxKernel {
|
||||
tx_kernel,
|
||||
height,
|
||||
mmr_index,
|
||||
})
|
||||
}
|
||||
|
||||
/// get output listing traversing pmmr from local
|
||||
fn get_outputs_by_pmmr_index_local(
|
||||
chain: Arc<chain::Chain>,
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
//! so that wallet API can be fully exercised
|
||||
//! Operates directly on a chain instance
|
||||
|
||||
use crate::api;
|
||||
use crate::api::{self, LocatedTxKernel};
|
||||
use crate::chain::types::NoopAdapter;
|
||||
use crate::chain::Chain;
|
||||
use crate::core::core::verifier_cache::LruVerifierCache;
|
||||
use crate::core::core::Transaction;
|
||||
use crate::core::core::{Transaction, TxKernel};
|
||||
use crate::core::global::{set_mining_mode, ChainTypes};
|
||||
use crate::core::{pow, ser};
|
||||
use crate::keychain::Keychain;
|
||||
@@ -151,6 +151,7 @@ where
|
||||
"get_outputs_by_pmmr_index" => self.get_outputs_by_pmmr_index(m)?,
|
||||
"send_tx_slate" => self.send_tx_slate(m)?,
|
||||
"post_tx" => self.post_tx(m)?,
|
||||
"get_kernel" => self.get_kernel(m)?,
|
||||
_ => panic!("Unknown Wallet Proxy Message"),
|
||||
};
|
||||
|
||||
@@ -299,6 +300,26 @@ where
|
||||
body: serde_json::to_string(&ol).unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
/// get kernel
|
||||
fn get_kernel(
|
||||
&mut self,
|
||||
m: WalletProxyMessage,
|
||||
) -> Result<WalletProxyMessage, libwallet::Error> {
|
||||
let split = m.body.split(",").collect::<Vec<&str>>();
|
||||
let excess = split[0].parse::<String>().unwrap();
|
||||
let min = split[1].parse::<u64>().unwrap();
|
||||
let max = split[2].parse::<u64>().unwrap();
|
||||
let commit_bytes = util::from_hex(excess).unwrap();
|
||||
let commit = pedersen::Commitment::from_vec(commit_bytes);
|
||||
let k = super::get_kernel_local(self.chain.clone(), &commit, Some(min), Some(max));
|
||||
Ok(WalletProxyMessage {
|
||||
sender_id: "node".to_owned(),
|
||||
dest: m.sender_id,
|
||||
method: m.method,
|
||||
body: serde_json::to_string(&k).unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -450,6 +471,47 @@ impl NodeClient for LocalWalletClient {
|
||||
Ok(api_outputs)
|
||||
}
|
||||
|
||||
fn get_kernel(
|
||||
&mut self,
|
||||
excess: &pedersen::Commitment,
|
||||
min_height: Option<u64>,
|
||||
max_height: Option<u64>,
|
||||
) -> Result<Option<(TxKernel, u64, u64)>, libwallet::Error> {
|
||||
let mut query = format!("{},", util::to_hex(excess.0.to_vec()));
|
||||
if let Some(h) = min_height {
|
||||
query += &format!("{},", h);
|
||||
} else {
|
||||
query += "0,"
|
||||
}
|
||||
if let Some(h) = max_height {
|
||||
query += &format!("{}", h);
|
||||
} else {
|
||||
query += "0"
|
||||
}
|
||||
|
||||
let m = WalletProxyMessage {
|
||||
sender_id: self.id.clone(),
|
||||
dest: self.node_url().to_owned(),
|
||||
method: "get_kernel".to_owned(),
|
||||
body: query,
|
||||
};
|
||||
{
|
||||
let p = self.proxy_tx.lock();
|
||||
p.send(m).context(libwallet::ErrorKind::ClientCallback(
|
||||
"Get outputs from node by PMMR index send".to_owned(),
|
||||
))?;
|
||||
}
|
||||
let r = self.rx.lock();
|
||||
let m = r.recv().unwrap();
|
||||
let res: Option<LocatedTxKernel> = serde_json::from_str(&m.body).context(
|
||||
libwallet::ErrorKind::ClientCallback("Get transaction kernels send".to_owned()),
|
||||
)?;
|
||||
match res {
|
||||
Some(k) => Ok(Some((k.tx_kernel, k.height, k.mmr_index))),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_outputs_by_pmmr_index(
|
||||
&self,
|
||||
start_height: u64,
|
||||
|
||||
Reference in New Issue
Block a user