mirror of
https://github.com/mimblewimble/grin-wallet.git
synced 2025-01-20 19:11:09 +03:00
Slate compatibility between versions (#35)
* wallet compatibilities * rustfmt
This commit is contained in:
parent
2d8a6b81e0
commit
0e9ccef3e5
4 changed files with 115 additions and 24 deletions
|
@ -763,14 +763,14 @@ where
|
|||
Box::new(parse_body(req).and_then(
|
||||
//TODO: No way to insert a message from the params
|
||||
move |slate_str: String| {
|
||||
let mut slate: Slate = Slate::deserialize_upgrade(&slate_str).unwrap();
|
||||
let slate: Slate = Slate::deserialize_upgrade(&slate_str).unwrap();
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
err(e)
|
||||
} else {
|
||||
match api.receive_tx(&mut slate, None, None) {
|
||||
Ok(_) => ok(slate
|
||||
.serialize_to_version(Some(slate.version_info.orig_version))
|
||||
match api.receive_tx(&slate, None, None) {
|
||||
Ok(s) => ok(s
|
||||
.serialize_to_version(Some(s.version_info.orig_version))
|
||||
.unwrap()),
|
||||
Err(e) => {
|
||||
error!("receive_tx: failed with error: {}", e);
|
||||
|
@ -798,7 +798,7 @@ where
|
|||
),
|
||||
"receive_tx" => Box::new(
|
||||
self.receive_tx(req, api)
|
||||
.and_then(|res| ok(json_response(&res))),
|
||||
.and_then(|res| ok(json_response_slate(&res))),
|
||||
),
|
||||
_ => Box::new(ok(response(StatusCode::BAD_REQUEST, "unknown action"))),
|
||||
}
|
||||
|
@ -909,6 +909,29 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// As above, dealing with stringified slate output
|
||||
// from older versions.
|
||||
// Older versions are expecting a slate objects, anything from
|
||||
// 1.1.0 up is expecting a string
|
||||
fn json_response_slate<T>(s: &T) -> Response<Body>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
match serde_json::to_string(s) {
|
||||
Ok(mut json) => {
|
||||
if let None = json.find("version_info") {
|
||||
let mut r = json.clone();
|
||||
r.pop();
|
||||
r.remove(0);
|
||||
// again, for backwards slate compat
|
||||
json = r.replace("\\\"", "\"")
|
||||
}
|
||||
response(StatusCode::OK, json)
|
||||
}
|
||||
Err(_) => response(StatusCode::INTERNAL_SERVER_ERROR, ""),
|
||||
}
|
||||
}
|
||||
|
||||
// pretty-printed version of above
|
||||
fn json_response_pretty<T>(s: &T) -> Response<Body>
|
||||
where
|
||||
|
@ -987,10 +1010,26 @@ where
|
|||
req.into_body()
|
||||
.concat2()
|
||||
.map_err(|_| ErrorKind::GenericError("Failed to read request".to_owned()).into())
|
||||
.and_then(|body| match serde_json::from_reader(&body.to_vec()[..]) {
|
||||
Ok(obj) => ok(obj),
|
||||
Err(e) => {
|
||||
err(ErrorKind::GenericError(format!("Invalid request body: {}", e)).into())
|
||||
.and_then(|body| {
|
||||
match serde_json::from_reader(&body.to_vec()[..]) {
|
||||
Ok(obj) => ok(obj),
|
||||
Err(_) => {
|
||||
// try to parse as string instead, for backwards compatibility
|
||||
let replaced_str = String::from_utf8(body.to_vec().clone())
|
||||
.unwrap()
|
||||
.replace("\"", "\\\"");
|
||||
let mut str_vec = replaced_str.as_bytes().to_vec();
|
||||
str_vec.push(0x22);
|
||||
str_vec.insert(0, 0x22);
|
||||
match serde_json::from_reader(&str_vec[..]) {
|
||||
Ok(obj) => ok(obj),
|
||||
Err(e) => err(ErrorKind::GenericError(format!(
|
||||
"Invalid request body: {}",
|
||||
e
|
||||
))
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
/// HTTP Wallet 'plugin' implementation
|
||||
use crate::api;
|
||||
use crate::libwallet::slate::Slate;
|
||||
use crate::libwallet::slate_versions::{v0, v1};
|
||||
use crate::libwallet::{Error, ErrorKind};
|
||||
use crate::WalletCommAdapter;
|
||||
use config::WalletConfig;
|
||||
use failure::ResultExt;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -47,15 +49,64 @@ impl WalletCommAdapter for HTTPWalletCommAdapter {
|
|||
let url = format!("{}/v1/wallet/foreign/receive_tx", dest);
|
||||
debug!("Posting transaction slate to {}", url);
|
||||
let slate = slate.serialize_to_version(Some(slate.version_info.orig_version))?;
|
||||
let res: Result<String, _> = api::client::post(url.as_str(), None, &slate);
|
||||
match res {
|
||||
Err(e) => {
|
||||
let report = format!("Posting transaction slate (is recipient listening?): {}", e);
|
||||
error!("{}", report);
|
||||
Err(ErrorKind::ClientCallback(report).into())
|
||||
// For compatibility with older clients
|
||||
let res: Slate = {
|
||||
if let None = slate.find("version_info") {
|
||||
let version = Slate::parse_slate_version(&slate)?;
|
||||
match version {
|
||||
1 => {
|
||||
let ver1: v1::SlateV1 =
|
||||
serde_json::from_str(&slate).context(ErrorKind::SlateDeser)?;
|
||||
let r: Result<v1::SlateV1, _> =
|
||||
api::client::post(url.as_str(), None, &ver1);
|
||||
match r {
|
||||
Err(e) => {
|
||||
let report = format!(
|
||||
"Posting transaction slate (is recipient listening?): {}",
|
||||
e
|
||||
);
|
||||
error!("{}", report);
|
||||
return Err(ErrorKind::ClientCallback(report).into());
|
||||
}
|
||||
Ok(s) => Slate::deserialize_upgrade(
|
||||
&serde_json::to_string(&s).context(ErrorKind::SlateDeser)?,
|
||||
)?,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let ver0: v0::SlateV0 =
|
||||
serde_json::from_str(&slate).context(ErrorKind::SlateDeser)?;
|
||||
let r: Result<v0::SlateV0, _> =
|
||||
api::client::post(url.as_str(), None, &ver0);
|
||||
match r {
|
||||
Err(e) => {
|
||||
let report = format!(
|
||||
"Posting transaction slate (is recipient listening?): {}",
|
||||
e
|
||||
);
|
||||
error!("{}", report);
|
||||
return Err(ErrorKind::ClientCallback(report).into());
|
||||
}
|
||||
Ok(s) => Slate::deserialize_upgrade(
|
||||
&serde_json::to_string(&s).context(ErrorKind::SlateDeser)?,
|
||||
)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let res: Result<String, _> = api::client::post(url.as_str(), None, &slate);
|
||||
match res {
|
||||
Err(e) => {
|
||||
let report =
|
||||
format!("Posting transaction slate (is recipient listening?): {}", e);
|
||||
error!("{}", report);
|
||||
return Err(ErrorKind::ClientCallback(report).into());
|
||||
}
|
||||
Ok(r) => Slate::deserialize_upgrade(&r)?,
|
||||
}
|
||||
}
|
||||
Ok(r) => Ok(Slate::deserialize_upgrade(&r)?),
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn send_tx_async(&self, _dest: &str, _slate: &Slate) -> Result<(), Error> {
|
||||
|
|
|
@ -163,9 +163,9 @@ pub struct ParticipantMessages {
|
|||
}
|
||||
|
||||
impl Slate {
|
||||
// TODO: Reduce the number of changes that need to occur below for each new
|
||||
// slate version
|
||||
fn parse_slate_version(slate_json: &str) -> Result<u16, Error> {
|
||||
/// TODO: Reduce the number of changes that need to occur below for each new
|
||||
/// slate version
|
||||
pub fn parse_slate_version(slate_json: &str) -> Result<u16, Error> {
|
||||
// keep attempting to deser, working through known versions until we have
|
||||
// enough to get the version out
|
||||
let res: Result<SlateV2, serde_json::Error> = serde_json::from_str(slate_json);
|
||||
|
@ -218,7 +218,8 @@ impl Slate {
|
|||
1 => {
|
||||
let v2: SlateV2 = serde_json::from_str(&ser_self).context(ErrorKind::SlateDeser)?;
|
||||
let v1 = SlateV1::from(v2);
|
||||
Ok(serde_json::to_string(&v1).context(ErrorKind::SlateDeser)?)
|
||||
let slate = serde_json::to_string(&v1).context(ErrorKind::SlateDeser)?;
|
||||
Ok(slate)
|
||||
}
|
||||
0 => {
|
||||
let v2: SlateV2 = serde_json::from_str(&ser_self).context(ErrorKind::SlateDeser)?;
|
||||
|
|
|
@ -397,10 +397,10 @@ pub fn parse_send_args(args: &ArgMatches) -> Result<command::SendArgs, ParseErro
|
|||
|
||||
// target slate version to create/send
|
||||
let target_slate_version = {
|
||||
match args.is_present("target_slate_version") {
|
||||
match args.is_present("slate_version") {
|
||||
true => {
|
||||
let v = parse_required(args, "target_slate_version")?;
|
||||
Some(parse_u64(v, "target_slate_version")? as u16)
|
||||
let v = parse_required(args, "slate_version")?;
|
||||
Some(parse_u64(v, "slate_version")? as u16)
|
||||
}
|
||||
false => None,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue