Procházet zdrojové kódy

current work on merklenode

narodnik před 4 roky
rodič
revize
c4581bb957
5 změnil soubory, kde provedl 99 přidání a 1 odebrání
  1. 1 0
      Cargo.lock
  2. 2 0
      Cargo.toml
  3. 90 0
      src/bin/tx2.rs
  4. 5 0
      src/crypto/constants.rs
  5. 1 1
      src/crypto/constants/sinsemilla.rs

+ 1 - 0
Cargo.lock

@@ -1313,6 +1313,7 @@ dependencies = [
  "solana-sdk",
  "spl-associated-token-account",
  "spl-token",
+ "subtle",
  "toml",
  "tungstenite 0.15.0",
  "url",

+ 2 - 0
Cargo.toml

@@ -43,6 +43,8 @@ crypto_api_chachapoly = "0.5.0"
 arrayvec = "0.7.0"
 sha2 = "0.9.8"
 ripemd160 = "0.9.1"
+# Constant time options which is used for MerkleNode incrementalmerkletree
+subtle = "2.3"
 
 # Encoding and parsing
 bs58 = "0.4.0"

+ 90 - 0
src/bin/tx2.rs

@@ -38,6 +38,10 @@ use pasta_curves::{
     },
     pallas,
 };
+use incrementalmerkletree::{
+    bridgetree::{BridgeTree, Frontier as BridgeFrontier},
+    Altitude, Frontier, Tree,
+};
 
 use drk::{
     circuit::{mint_contract::MintContract, spend_contract::SpendContract},
@@ -433,6 +437,85 @@ pub fn state_transition<S: ProgramState>(
     })
 }
 
+use std::iter;
+use subtle::ConstantTimeEq;
+use incrementalmerkletree::Hashable;
+use halo2_gadgets::primitives::sinsemilla::HashDomain;
+use lazy_static::lazy_static;
+
+use drk::crypto::constants::{L_ORCHARD_MERKLE, MERKLE_DEPTH_ORCHARD, sinsemilla::i2lebsp_k};
+
+//const UNCOMMITTED_ORCHARD: pallas::Base = pallas::Base::from_u64(2);
+
+lazy_static! {
+    static ref UNCOMMITTED_ORCHARD: pallas::Base = pallas::Base::from_u64(2);
+    static ref EMPTY_ROOTS: Vec<MerkleNode> = {
+        iter::empty()
+            .chain(Some(MerkleNode::empty_leaf()))
+            .chain(
+                (0..MERKLE_DEPTH_ORCHARD).scan(MerkleNode::empty_leaf(), |state, l| {
+                    let l = l as u8;
+                    *state = MerkleNode::combine(l.into(), state, state);
+                    Some(state.clone())
+                }),
+            )
+            .collect()
+    };
+}
+
+#[derive(Clone, std::cmp::Eq)]
+pub struct MerkleNode(pallas::Base);
+
+impl std::cmp::PartialEq for MerkleNode {
+    fn eq(&self, other: &Self) -> bool {
+        self.0.ct_eq(&other.0).into()
+    }
+}
+
+impl std::hash::Hash for MerkleNode {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        <Option<pallas::Base>>::from(self.0)
+            .map(|b| b.to_bytes())
+            .hash(state)
+    }
+}
+
+impl Hashable for MerkleNode {
+    fn empty_leaf() -> Self {
+        MerkleNode(UNCOMMITTED_ORCHARD.clone())
+    }
+
+    /// Implements `MerkleCRH^Orchard` as defined in
+    /// <https://zips.z.cash/protocol/protocol.pdf#orchardmerklecrh>
+    ///
+    /// The layer with 2^n nodes is called "layer n":
+    ///      - leaves are at layer MERKLE_DEPTH_ORCHARD = 32;
+    ///      - the root is at layer 0.
+    /// `l` is MERKLE_DEPTH_ORCHARD - layer - 1.
+    ///      - when hashing two leaves, we produce a node on the layer above the leaves, i.e.
+    ///        layer = 31, l = 0
+    ///      - when hashing to the final root, we produce the anchor with layer = 0, l = 31.
+    fn combine(altitude: Altitude, left: &Self, right: &Self) -> Self {
+        // MerkleCRH Sinsemilla hash domain.
+        let domain = HashDomain::new(MERKLE_CRH_PERSONALIZATION);
+
+        MerkleNode(
+            domain
+                .hash(
+                    iter::empty()
+                        .chain(i2lebsp_k(altitude.into()).iter().copied())
+                        .chain(left.0.to_le_bits().iter().by_val().take(L_ORCHARD_MERKLE))
+                        .chain(right.0.to_le_bits().iter().by_val().take(L_ORCHARD_MERKLE)),
+                )
+                .unwrap_or(pallas::Base::zero()),
+        )
+    }
+
+    fn empty_root(altitude: Altitude) -> Self {
+        EMPTY_ROOTS[<usize>::from(altitude)].clone()
+    }
+}
+
 fn main() -> std::result::Result<(), failure::Error> {
     use drk::{
         crypto::mint_proof::{create_mint_proof, verify_mint_proof},
@@ -472,5 +555,12 @@ fn main() -> std::result::Result<(), failure::Error> {
     let update = state_transition(&state, tx)?;
     state.apply(update);
 
+    //let mut tree = BridgeTree::<MerkleNode, 32>::new(100);
+    //let coin = MerkleNode(pallas::Base::random(&mut OsRng));
+    //tree.append(&coin);
+    //tree.witness();
+
+    let mut tree = BridgeTree::<String, 3>::new(100);
+
     Ok(())
 }

+ 5 - 0
src/crypto/constants.rs

@@ -5,3 +5,8 @@ pub mod util;
 pub use fixed_bases::OrchardFixedBases;
 
 pub const DRK_SCHNORR_DOMAIN: &[u8] = b"DarkFi_Schnorr";
+
+pub const MERKLE_DEPTH_ORCHARD: usize = 32;
+
+pub const L_ORCHARD_MERKLE: usize = 255;
+

+ 1 - 1
src/crypto/constants/sinsemilla.rs

@@ -85,7 +85,7 @@ fn lebs2ip_k(bits: &[bool]) -> u32 {
 
 /// The sequence of K bits in little-endian order representing an integer
 /// up to `2^K` - 1.
-pub(crate) fn i2lebsp_k(int: usize) -> [bool; K] {
+pub fn i2lebsp_k(int: usize) -> [bool; K] {
     assert!(int < (1 << K));
     i2lebsp(int as u64)
 }