Interpret hex memos properly.

Fixes #38
This commit is contained in:
Aditya Kulkarni 2020-07-28 09:52:53 -07:00
parent 5675f5b359
commit 22bde5a404
4 changed files with 55 additions and 19 deletions

View File

@ -1015,11 +1015,18 @@ impl LightClient {
// Collect outgoing metadata
let outgoing_json = wtx.outgoing_metadata.iter()
.map(|om|
object!{
.map(|om| {
let mut o = object!{
"address" => om.address.clone(),
"value" => om.value,
"memo" => LightWallet::memo_str(&Some(om.memo.clone())),
};
if include_memo_hex {
o.insert("memohex", hex::encode(om.memo.as_bytes())).unwrap();
}
return o;
}).collect::<Vec<JsonValue>>();
object! {

View File

@ -2066,22 +2066,12 @@ impl LightWallet {
Some(s) => {
// If the string starts with an "0x", and contains only hex chars ([a-f0-9]+) then
// interpret it as a hex
let s_bytes = if s.to_lowercase().starts_with("0x") {
match hex::decode(&s[2..s.len()]) {
Ok(data) => data,
Err(_) => Vec::from(s.as_bytes())
}
} else {
Vec::from(s.as_bytes())
};
match Memo::from_bytes(&s_bytes) {
None => {
let e = format!("Error creating output. Memo {:?} is too long", s);
match utils::interpret_memo_string(&s) {
Ok(m) => Some(m),
Err(e) => {
error!("{}", e);
return Err(e);
},
Some(m) => Some(m)
}
}
}
};
@ -2154,10 +2144,16 @@ impl LightWallet {
None => Memo::default(),
Some(s) => {
// If the address is not a z-address, then drop the memo
if LightWallet::is_shielded_address(&addr.to_string(), &self.config) {
Memo::from_bytes(s.as_bytes()).unwrap()
} else {
if !LightWallet::is_shielded_address(&addr.to_string(), &self.config) {
Memo::default()
} else {
match utils::interpret_memo_string(s) {
Ok(m) => m,
Err(e) => {
error!("{}", e);
Memo::default()
}
}
}
}
},

View File

@ -1412,6 +1412,16 @@ fn test_z_incoming_hex_memo() {
let sent_tx = Transaction::read(&raw_tx[..]).unwrap();
let sent_txid = sent_tx.txid();
// Make sure it is in the mempool properly
{
let mempool = wallet.mempool_txs.read().unwrap();
let wtx = mempool.get(&sent_txid).unwrap();
assert_eq!(wtx.outgoing_metadata.get(0).unwrap().address, my_address);
assert_eq!(wtx.outgoing_metadata.get(0).unwrap().value, AMOUNT1 - fee);
assert_eq!(wtx.outgoing_metadata.get(0).unwrap().memo.to_utf8().unwrap().unwrap(), orig_memo);
}
// Add it to a block
let mut cb3 = FakeCompactBlock::new(2, block_hash);
cb3.add_tx(&sent_tx);

View File

@ -1,5 +1,6 @@
use std::io::{self, Read, Write};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use zcash_primitives::note_encryption::Memo;
pub fn read_string<R: Read>(mut reader: R) -> io::Result<String> {
// Strings are written as <littleendian> len + bytes
@ -18,4 +19,26 @@ pub fn write_string<W: Write>(mut writer: W, s: &String) -> io::Result<()> {
// Strings are written as len + utf8
writer.write_u64::<LittleEndian>(s.as_bytes().len() as u64)?;
writer.write_all(s.as_bytes())
}
// Interpret a string or hex-encoded memo, and return a Memo object
pub fn interpret_memo_string(memo_str: &String) -> Result<Memo, String> {
// If the string starts with an "0x", and contains only hex chars ([a-f0-9]+) then
// interpret it as a hex
let s_bytes = if memo_str.to_lowercase().starts_with("0x") {
match hex::decode(&memo_str[2..memo_str.len()]) {
Ok(data) => data,
Err(_) => Vec::from(memo_str.as_bytes())
}
} else {
Vec::from(memo_str.as_bytes())
};
match Memo::from_bytes(&s_bytes) {
None => {
let e = format!("Error creating output. Memo {:?} is too long", memo_str);
return Err(e);
},
Some(m) => Ok(m)
}
}