Просмотр исходного кода

implemented Encodable for IncrementalWitness and finished put_own_coins

rachel-rose 5 лет назад
Родитель
Сommit
83a7148e08
6 измененных файлов с 121 добавлено и 152 удалено
  1. 1 1
      src/bin/darkfid.rs
  2. 1 0
      src/crypto/fr_serial.rs
  3. 97 133
      src/crypto/merkle.rs
  4. 10 7
      src/crypto/merkle_node.rs
  5. 2 0
      src/error.rs
  6. 10 11
      src/wallet/walletdb.rs

+ 1 - 1
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;
 

+ 1 - 0
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};
 

+ 97 - 133
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<R: Read>(reader: R) -> io::Result<Self>;
+    fn read<R: Read>(reader: R) -> Result<Self>;
 
     /// Serializes this node.
-    fn write<W: Write>(&self, writer: W) -> io::Result<()>;
+    fn write<W: 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<Node: Hashable> CommitmentTree<Node> {
         }
     }
 
-    /*
-    /// Reads a `CommitmentTree` from its serialized form.
-    #[allow(clippy::redundant_closure)]
-    pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
-        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<W: 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<Node: Hashable> CommitmentTree<Node> {
     /// 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<Node: Hashable> CommitmentTree<Node> {
     }
 }
 
+impl<Node: Hashable> Encodable for CommitmentTree<Node> {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        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<Node: Hashable> Decodable for CommitmentTree<Node> {
+//    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+//        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<Node: Hashable> CommitmentTree<Node> {
 /// witness.append(cmu);
 /// assert_eq!(tree.root(), witness.root());
 /// ```
+///
+*/
+
 #[derive(Clone)]
 pub struct IncrementalWitness<Node: Hashable> {
     tree: CommitmentTree<Node>,
@@ -228,6 +257,37 @@ pub struct IncrementalWitness<Node: Hashable> {
     cursor: Option<CommitmentTree<Node>>,
 }
 
+impl<Node: Hashable> Encodable for IncrementalWitness<Node> {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        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<Node: Hashable> Decodable for IncrementalWitness<Node> {
+//    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+//        Ok(Self {
+//            tree: Decodable::decode(&mut d)?,
+//            filled: Decodable::decode(&mut d)?,
+//            cursor_depth: Decodable::decode(&mut d)?,
+//            cursor: Decodable::decode(d)?,
+//        })
+//    }
+//}
+
 impl<Node: Hashable> IncrementalWitness<Node> {
     /// Creates an `IncrementalWitness` for the most recent commitment added to
     /// the given [`CommitmentTree`].
@@ -240,34 +300,6 @@ impl<Node: Hashable> IncrementalWitness<Node> {
         }
     }
 
-    /*
-    /// Reads an `IncrementalWitness` from its serialized form.
-    #[allow(clippy::redundant_closure)]
-    pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
-        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<W: 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<Node: Hashable> IncrementalWitness<Node> {
     /// 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<Node: Hashable> IncrementalWitness<Node> {
         } 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<Node: Hashable> MerklePath<Node> {
         }
     }
 
-    /*
-    /// Reads a Merkle path from its serialized form.
-    pub fn from_slice(witness: &[u8]) -> Result<Self, ()> {
-        Self::from_slice_with_depth(witness, SAPLING_COMMITMENT_TREE_DEPTH)
-    }
-
-    fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result<Self, ()> {
-        // 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::<Result<Vec<_>, _>>()?;
-        if auth_path.len() != depth {
-            return Err(());
-        }
-
-        // Read the position from the witness
-        let position = witness.read_u64::<LittleEndian>().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 {

+ 10 - 7
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<R: io::Read>(mut reader: R) -> io::Result<Self> {
+    fn read<R: io::Read>(mut reader: R) -> Result<Self> {
         let mut repr = [0u8; 32];
         reader.read_exact(&mut repr)?;
         Ok(Self::new(repr))
     }
 
-    fn write<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
-        writer.write_all(self.repr.as_ref())
+    fn write<W: io::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);

+ 2 - 0
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"),
         }
     }
 }

+ 10 - 11
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(&note.serial).await?;
         let coin_blind = self.get_value_serialized(&note.coin_blind).await?;
         let valcom_blind = self.get_value_serialized(&note.valcom_blind).await?;
         let value = self.get_value_serialized(&note.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<PathBuf> {
-       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<u8>, Vec<u8>) {