mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
implemented Encodable for IncrementalWitness and finished put_own_coins
This commit is contained in:
@@ -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,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};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<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>) {
|
||||
|
||||
Reference in New Issue
Block a user