Slate compatibility between versions (#35)

* wallet compatibilities

* rustfmt
This commit is contained in:
Yeastplume 2019-04-02 15:42:28 +01:00 committed by GitHub
parent 2d8a6b81e0
commit 0e9ccef3e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 24 deletions

View file

@ -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()),
}
}
}
}),
)

View file

@ -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> {

View file

@ -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)?;

View file

@ -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,
}