diff --git a/src/bin/darkfid.rs b/src/bin/darkfid.rs index 4b7a17ed0..f337ed063 100644 --- a/src/bin/darkfid.rs +++ b/src/bin/darkfid.rs @@ -1,7 +1,7 @@ use async_std::sync::Arc; use drk::rpc::adapter::RpcAdapter; -use drk::rpc::options::ProgramOptions; use drk::rpc::jsonserver; +use drk::rpc::options::ProgramOptions; use rand::rngs::OsRng; use std::net::SocketAddr; diff --git a/src/crypto/fr_serial.rs b/src/crypto/fr_serial.rs index d73a1e699..f19955290 100644 --- a/src/crypto/fr_serial.rs +++ b/src/crypto/fr_serial.rs @@ -1,6 +1,7 @@ use group::GroupEncoding; use std::io; +use crate::crypto::{merkle::IncrementalWitness, merkle_node::MerkleNode}; use crate::error::{Error, Result}; use crate::serial::{Decodable, Encodable, ReadExt, WriteExt}; diff --git a/src/crypto/merkle.rs b/src/crypto/merkle.rs index f42e8f4a9..bff617752 100644 --- a/src/crypto/merkle.rs +++ b/src/crypto/merkle.rs @@ -2,19 +2,22 @@ //! of notes. //use byteorder::{LittleEndian, ReadBytesExt}; +use crate::serial::{Decodable, Encodable, VarInt}; +use crate::{Error, Result}; use std::collections::VecDeque; -use std::io::{self, Read, Write}; +use std::io; +use std::io::{Read, Write}; -//use crate::serialize::{Optional, Vector}; +//use super::serialize::{Optional, Vector}; use super::merkle_node::SAPLING_COMMITMENT_TREE_DEPTH; /// A hashable node within a Merkle tree. -pub trait Hashable: Clone + Copy { +pub trait Hashable: Clone + Copy + Encodable + Decodable { /// Parses a node from the given byte source. - fn read(reader: R) -> io::Result; + fn read(reader: R) -> Result; /// Serializes this node. - fn write(&self, writer: W) -> io::Result<()>; + fn write(&self, writer: W) -> Result<()>; /// Returns the parent node within the tree of the two given nodes. fn combine(_: usize, _: &Self, _: &Self) -> Self; @@ -65,31 +68,6 @@ impl CommitmentTree { } } - /* - /// Reads a `CommitmentTree` from its serialized form. - #[allow(clippy::redundant_closure)] - pub fn read(mut reader: R) -> io::Result { - let left = Optional::read(&mut reader, |r| Node::read(r))?; - let right = Optional::read(&mut reader, |r| Node::read(r))?; - let parents = Vector::read(&mut reader, |r| Optional::read(r, |r| Node::read(r)))?; - - Ok(CommitmentTree { - left, - right, - parents, - }) - } - - /// Serializes this tree as an array of bytes. - pub fn write(&self, mut writer: W) -> io::Result<()> { - Optional::write(&mut writer, &self.left, |w, n| n.write(w))?; - Optional::write(&mut writer, &self.right, |w, n| n.write(w))?; - Vector::write(&mut writer, &self.parents, |w, e| { - Optional::write(w, e, |w, n| n.write(w)) - }) - } - */ - /// Returns the number of leaf nodes in the tree. pub fn size(&self) -> usize { self.parents.iter().enumerate().fold( @@ -117,14 +95,13 @@ impl CommitmentTree { /// Adds a leaf node to the tree. /// /// Returns an error if the tree is full. - pub fn append(&mut self, node: Node) -> Result<(), ()> { + pub fn append(&mut self, node: Node) -> Result<()> { self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH) } - fn append_inner(&mut self, node: Node, depth: usize) -> Result<(), ()> { + fn append_inner(&mut self, node: Node, depth: usize) -> Result<()> { if self.is_complete(depth) { - // Tree is full - return Err(()); + return Err(Error::TreeFull); } match (self.left, self.right) { @@ -188,6 +165,55 @@ impl CommitmentTree { } } +impl Encodable for CommitmentTree { + fn encode(&self, mut s: S) -> Result { + let mut len = 0; + match self.left { + Some(v) => { + len += v.encode(&mut s)?; + 1 + } + None => 0, + }; + match self.right { + Some(v) => { + len += v.encode(&mut s)?; + 1 + } + None => 0, + }; + for c in self.parents.iter() { + match c { + Some(v) => { + len += v.encode(&mut s)?; + 1 + } + None => 0, + }; + } + match self.parents[0] { + Some(v) => { + len += v.encode(&mut s)?; + 1 + } + None => 0, + }; + Ok(len) + } +} + +// TODO: implement Decodable +//impl Decodable for CommitmentTree { +// fn decode(mut d: D) -> Result { +// Ok(Self { +// //left: Decodable::decode(&mut d)?, +// //right: Decodable::decode(&mut d)?, +// //parents: Decodable::decode(&mut d)?, +// }) +// } +//} + +/* /// An updatable witness to a path from a position in a particular /// [`CommitmentTree`]. /// @@ -220,6 +246,9 @@ impl CommitmentTree { /// witness.append(cmu); /// assert_eq!(tree.root(), witness.root()); /// ``` +/// +*/ + #[derive(Clone)] pub struct IncrementalWitness { tree: CommitmentTree, @@ -228,6 +257,37 @@ pub struct IncrementalWitness { cursor: Option>, } +impl Encodable for IncrementalWitness { + fn encode(&self, mut s: S) -> Result { + let mut len = 0; + len += self.tree.encode(&mut s)?; + for c in self.filled.iter() { + len += c.encode(&mut s)?; + } + len += self.cursor_depth.encode(&mut s)?; + match &self.cursor { + Some(v) => { + len += v.encode(&mut s)?; + 1 + } + None => 0, + }; + Ok(len) + } +} + +// TODO: implement Decodable +//impl Decodable for IncrementalWitness { +// fn decode(mut d: D) -> Result { +// Ok(Self { +// tree: Decodable::decode(&mut d)?, +// filled: Decodable::decode(&mut d)?, +// cursor_depth: Decodable::decode(&mut d)?, +// cursor: Decodable::decode(d)?, +// }) +// } +//} + impl IncrementalWitness { /// Creates an `IncrementalWitness` for the most recent commitment added to /// the given [`CommitmentTree`]. @@ -240,34 +300,6 @@ impl IncrementalWitness { } } - /* - /// Reads an `IncrementalWitness` from its serialized form. - #[allow(clippy::redundant_closure)] - pub fn read(mut reader: R) -> io::Result { - let tree = CommitmentTree::read(&mut reader)?; - let filled = Vector::read(&mut reader, |r| Node::read(r))?; - let cursor = Optional::read(&mut reader, |r| CommitmentTree::read(r))?; - - let mut witness = IncrementalWitness { - tree, - filled, - cursor_depth: 0, - cursor, - }; - - witness.cursor_depth = witness.next_depth(); - - Ok(witness) - } - - /// Serializes this `IncrementalWitness` as an array of bytes. - pub fn write(&self, mut writer: W) -> io::Result<()> { - self.tree.write(&mut writer)?; - Vector::write(&mut writer, &self.filled, |w, n| n.write(w))?; - Optional::write(&mut writer, &self.cursor, |w, t| t.write(w)) - } - */ - /// Returns the position of the witnessed leaf node in the commitment tree. pub fn position(&self) -> usize { self.tree.size() - 1 @@ -322,11 +354,11 @@ impl IncrementalWitness { /// Tracks a leaf node that has been added to the underlying tree. /// /// Returns an error if the tree is full. - pub fn append(&mut self, node: Node) -> Result<(), ()> { + pub fn append(&mut self, node: Node) -> Result<()> { self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH) } - fn append_inner(&mut self, node: Node, depth: usize) -> Result<(), ()> { + fn append_inner(&mut self, node: Node, depth: usize) -> Result<()> { if let Some(mut cursor) = self.cursor.take() { cursor .append_inner(node, depth) @@ -340,8 +372,7 @@ impl IncrementalWitness { } else { self.cursor_depth = self.next_depth(); if self.cursor_depth >= depth { - // Tree is full - return Err(()); + return Err(Error::TreeFull); } if self.cursor_depth == 0 { @@ -420,73 +451,6 @@ impl MerklePath { } } - /* - /// Reads a Merkle path from its serialized form. - pub fn from_slice(witness: &[u8]) -> Result { - Self::from_slice_with_depth(witness, SAPLING_COMMITMENT_TREE_DEPTH) - } - - fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result { - // Skip the first byte, which should be "depth" to signify the length of - // the following vector of Pedersen hashes. - if witness[0] != depth as u8 { - return Err(()); - } - witness = &witness[1..]; - - // Begin to construct the authentication path - let iter = witness.chunks_exact(33); - witness = iter.remainder(); - - // The vector works in reverse - let mut auth_path = iter - .rev() - .map(|bytes| { - // Length of inner vector should be the length of a Pedersen hash - if bytes[0] == 32 { - // Sibling node should be an element of Fr - Node::read(&bytes[1..]) - .map(|sibling| { - // Set the value in the auth path; we put false here - // for now (signifying the position bit) which we'll - // fill in later. - (sibling, false) - }) - .map_err(|_| ()) - } else { - Err(()) - } - }) - .collect::, _>>()?; - if auth_path.len() != depth { - return Err(()); - } - - // Read the position from the witness - let position = witness.read_u64::().map_err(|_| ())?; - - // Given the position, let's finish constructing the authentication - // path - let mut tmp = position; - for entry in auth_path.iter_mut() { - entry.1 =(tmp & 1) == 1; - tmp >>= 1; - } - - // The witnesmas should be empty now; if it wasn't, the caller would - // have provided more information than they should have, indicating - // a bug downstream - if witness.is_empty() { - Ok(MerklePath { - auth_path, - position, - }) - } else { - Err(()) - } - } - */ - /// Returns the root of the tree corresponding to this path applied to /// `leaf`. pub fn root(&self, leaf: Node) -> Node { diff --git a/src/crypto/merkle_node.rs b/src/crypto/merkle_node.rs index 4e7606790..110c89c42 100644 --- a/src/crypto/merkle_node.rs +++ b/src/crypto/merkle_node.rs @@ -5,10 +5,9 @@ use lazy_static::lazy_static; use std::io; use super::{coin::Coin, merkle::Hashable}; -use crate::{ - error::Result, - serial::{Decodable, Encodable}, -}; +use crate::impl_vec; +use crate::serial::{Decodable, Encodable, VarInt}; +use crate::{Error, Result}; pub const SAPLING_COMMITMENT_TREE_DEPTH: usize = 6; @@ -82,14 +81,16 @@ impl MerkleNode { } impl Hashable for MerkleNode { - fn read(mut reader: R) -> io::Result { + fn read(mut reader: R) -> Result { let mut repr = [0u8; 32]; reader.read_exact(&mut repr)?; Ok(Self::new(repr)) } - fn write(&self, mut writer: W) -> io::Result<()> { - writer.write_all(self.repr.as_ref()) + fn write(&self, mut writer: W) -> Result<()> { + writer + .write_all(self.repr.as_ref()) + .map_err(|e| Error::Io(e.kind())) } fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self { @@ -142,3 +143,5 @@ lazy_static! { v }; } + +impl_vec!(MerkleNode); diff --git a/src/error.rs b/src/error.rs index fa6b965cf..2e1779c12 100644 --- a/src/error.rs +++ b/src/error.rs @@ -43,6 +43,7 @@ pub enum Error { TryFromError, JsonRpcError(String), RocksdbError(String), + TreeFull, } impl std::error::Error for Error {} @@ -83,6 +84,7 @@ impl fmt::Display for Error { Error::TryFromError => f.write_str("TryFrom error"), Error::RocksdbError(ref err) => write!(f, "Rocksdb Error: {}", err), Error::JsonRpcError(ref err) => write!(f, "JsonRpc Error: {}", err), + Error::TreeFull => f.write_str("MerkleTree is full"), } } } diff --git a/src/wallet/walletdb.rs b/src/wallet/walletdb.rs index 9bfb65843..0f6d31ef8 100644 --- a/src/wallet/walletdb.rs +++ b/src/wallet/walletdb.rs @@ -43,14 +43,14 @@ impl WalletDB { } pub async fn put_own_coins(&self) -> Result<()> { - let note = &self.own_coins[0].1; let coin = self.get_value_serialized(&self.own_coins[0].0.repr).await?; + let note = &self.own_coins[0].1; let serial = self.get_value_serialized(¬e.serial).await?; let coin_blind = self.get_value_serialized(¬e.coin_blind).await?; let valcom_blind = self.get_value_serialized(¬e.valcom_blind).await?; let value = self.get_value_serialized(¬e.value).await?; let conn = Connection::open(&self.path)?; - // witness deserialization not implemented + let witness = self.get_value_serialized(&self.own_coins[0].3).await?; conn.execute( "INSERT INTO coins(coin, serial, value, coin_blind, valcom_blind, witness, key_id) VALUES (NULL, :coin, :serial, :value, :coin_blind, :valcom_blind, :witness, :key_id)", @@ -60,21 +60,20 @@ impl WalletDB { ":value": value, ":coin_blind": coin_blind, ":valcom_blind": valcom_blind, - //":privkey": privkey, - //":pubkey": pubkey + ":witness": witness, }, )?; Ok(()) } fn create_path(wallet: &str) -> Result { - let mut path = dirs::home_dir() - .ok_or(Error::PathNotFound)? - .as_path() - .join(".config/darkfi/"); - path.push(wallet); - debug!(target: "walletdb", "CREATE PATH {:?}", path); - Ok(path) + let mut path = dirs::home_dir() + .ok_or(Error::PathNotFound)? + .as_path() + .join(".config/darkfi/"); + path.push(wallet); + debug!(target: "walletdb", "CREATE PATH {:?}", path); + Ok(path) } pub async fn key_gen(&self) -> (Vec, Vec) {