Skip to content

Commit f28d109

Browse files
committed
Add Node
1 parent 18410e2 commit f28d109

File tree

6 files changed

+199
-40
lines changed

6 files changed

+199
-40
lines changed

src/core/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
//! Defines Simplicity terms, values, types, DAGs and programs.
1919
2020
// pub mod iter;
21-
// pub mod types;
2221
pub mod commit;
22+
pub mod node;
23+
#[allow(dead_code)]
24+
pub mod types;
2325
mod value;
2426

2527
pub use commit::CommitNode;
28+
pub use node::Node;
2629
pub use value::Value;

src/core/node.rs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Rust Simplicity Library
2+
// Written in 2022 by
3+
// Christian Lewe <[email protected]>
4+
//
5+
// To the extent possible under law, the author(s) have dedicated all
6+
// copyright and related and neighboring rights to this software to
7+
// the public domain worldwide. This software is distributed without
8+
// any warranty.
9+
//
10+
// You should have received a copy of the CC0 Public Domain Dedication
11+
// along with this software.
12+
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13+
//
14+
15+
use crate::core::types::Type;
16+
use crate::jet::{Application, JetNode};
17+
use crate::merkle::cmr::Cmr;
18+
use crate::merkle::imr::Imr;
19+
use std::rc::Rc;
20+
use std::sync::Arc;
21+
22+
/// Underlying combinator of a [`Node`].
23+
///
24+
/// # See
25+
/// - [`crate::core::commit::CommitNodeInner`]
26+
#[derive(Debug)]
27+
pub enum NodeInner<Witness, App: Application> {
28+
/// Identity
29+
Iden,
30+
/// Unit constant
31+
Unit,
32+
/// Left injection of some child
33+
InjL(Rc<Node<Witness, App>>),
34+
/// Right injection of some child
35+
InjR(Rc<Node<Witness, App>>),
36+
/// Take of some child
37+
Take(Rc<Node<Witness, App>>),
38+
/// Drop of some child
39+
Drop(Rc<Node<Witness, App>>),
40+
/// Composition of a left and right child
41+
Comp(Rc<Node<Witness, App>>, Rc<Node<Witness, App>>),
42+
/// Case of a left and right child
43+
Case(Rc<Node<Witness, App>>, Rc<Node<Witness, App>>),
44+
/// Left assertion of a left and right child.
45+
AssertL(Rc<Node<Witness, App>>, Rc<Node<Witness, App>>),
46+
/// Right assertion of a left and right child.
47+
AssertR(Rc<Node<Witness, App>>, Rc<Node<Witness, App>>),
48+
/// Pair of a left and right child
49+
Pair(Rc<Node<Witness, App>>, Rc<Node<Witness, App>>),
50+
/// Disconnect of a left and right child
51+
Disconnect(Rc<Node<Witness, App>>, Rc<Node<Witness, App>>),
52+
/// Witness data
53+
Witness(Witness),
54+
/// Universal fail
55+
Fail(Cmr, Cmr),
56+
/// Hidden CMR
57+
Hidden(Cmr),
58+
/// Application jet
59+
Jet(&'static JetNode<App>),
60+
}
61+
62+
#[allow(dead_code)]
63+
/// Source and target type of a node
64+
#[derive(Debug)]
65+
pub struct NodeType {
66+
/// Source type of the node
67+
pub(crate) source: Arc<Type>,
68+
/// Target type of the node
69+
pub(crate) target: Arc<Type>,
70+
}
71+
72+
/// Bounds on the resources required by a node during execution on the Bit Machine
73+
#[derive(Debug)]
74+
pub struct NodeBounds {
75+
/// Upper bound on the required number of cells
76+
pub extra_cells: usize,
77+
/// Upper bound on the required number of frames
78+
pub frame_count: usize,
79+
}
80+
81+
/// Root node of a Simplicity DAG for some application.
82+
/// The DAG contains full metadata, including the witness, for redeeming it.
83+
///
84+
/// # See
85+
/// - [`crate::core::CommitNode`]
86+
#[derive(Debug)]
87+
pub struct Node<Witness, App: Application> {
88+
/// Underlying combinator of the node
89+
pub inner: NodeInner<Witness, App>,
90+
/// Commitment Merkle root of the node
91+
pub cmr: Cmr,
92+
/// Identity Merkle root of the node
93+
pub imr: Imr,
94+
/// Type of the node
95+
pub ty: NodeType,
96+
/// Bounds for the node during execution on the Bit Machine
97+
pub bounds: NodeBounds,
98+
}
99+
100+
impl<Witness, App: Application> Node<Witness, App> {
101+
/// Return the left child of the node, if there is such a child.
102+
pub fn get_left(&self) -> Option<&Self> {
103+
match &self.inner {
104+
NodeInner::Iden
105+
| NodeInner::Unit
106+
| NodeInner::Witness(_)
107+
| NodeInner::Fail(_, _)
108+
| NodeInner::Hidden(_)
109+
| NodeInner::Jet(_) => None,
110+
NodeInner::InjL(l)
111+
| NodeInner::InjR(l)
112+
| NodeInner::Take(l)
113+
| NodeInner::Drop(l)
114+
| NodeInner::Comp(l, _)
115+
| NodeInner::Case(l, _)
116+
| NodeInner::AssertL(l, _)
117+
| NodeInner::AssertR(l, _)
118+
| NodeInner::Pair(l, _)
119+
| NodeInner::Disconnect(l, _) => Some(l),
120+
}
121+
}
122+
123+
/// Return the right child of the node, if there is such a child.
124+
pub fn get_right(&self) -> Option<&Self> {
125+
match &self.inner {
126+
NodeInner::Iden
127+
| NodeInner::Unit
128+
| NodeInner::Witness(_)
129+
| NodeInner::Fail(_, _)
130+
| NodeInner::Hidden(_)
131+
| NodeInner::Jet(_)
132+
| NodeInner::InjL(_)
133+
| NodeInner::InjR(_)
134+
| NodeInner::Take(_)
135+
| NodeInner::Drop(_) => None,
136+
NodeInner::Comp(_, r)
137+
| NodeInner::Case(_, r)
138+
| NodeInner::AssertL(_, r)
139+
| NodeInner::AssertR(_, r)
140+
| NodeInner::Pair(_, r)
141+
| NodeInner::Disconnect(_, r) => Some(r),
142+
}
143+
}
144+
}

src/jet/mod.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ pub mod type_name;
3434

3535
use crate::bititer::BitIter;
3636
use crate::encode::BitWriter;
37+
use crate::exec::BitMachine;
3738
use crate::jet::type_name::TypeName;
3839
use crate::merkle::cmr::Cmr;
39-
// use crate::merkle::common::MerkleRoot;
40-
// use crate::merkle::imr::Imr;
41-
use crate::exec::BitMachine;
40+
use crate::merkle::common::MerkleRoot;
41+
use crate::merkle::imr::Imr;
4242
use std::hash::Hash;
4343
use std::io::Write;
4444

@@ -105,15 +105,13 @@ impl<App: Application> JetNode<App> {
105105
self.cmr
106106
}
107107

108-
/*
109108
/// Return the IMR of the jet.
110109
///
111110
/// A jet's CMR equals its IMR.
112111
/// Jets may not include `witness` or `disconnect` nodes as a result.
113112
pub fn imr(&self) -> Imr {
114113
self.cmr.into_inner().into()
115114
}
116-
*/
117115
}
118116

119117
impl<App: Application> std::fmt::Display for JetNode<App> {

src/merkle/common.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
//! # Common traits and macros
1616
17-
// use crate::core::types::{Type, TypeInner};
1817
use crate::core::commit::CommitNodeInner;
18+
use crate::core::types::{Type, TypeInner};
19+
use crate::core::Value;
1920
use crate::jet::Application;
21+
use crate::util::u64_to_array_be;
2022
use bitcoin_hashes::sha256::Midstate;
2123
use bitcoin_hashes::{sha256, Hash, HashEngine};
2224

@@ -64,7 +66,6 @@ pub trait MerkleRoot: From<[u8; 32]> + Into<[u8; 32]> {
6466
Self::from(engine.midstate().into_inner())
6567
}
6668

67-
/*
6869
/// Extend the given tagged hash by the hash of the given `value` and the TMR of its `value_type`.
6970
///
7071
/// The hash `self` is taken as initial value,
@@ -116,7 +117,6 @@ pub trait MerkleRoot: From<[u8; 32]> + Into<[u8; 32]> {
116117
engine.input(value_type.tmr.as_ref());
117118
Self::from(engine.midstate().into_inner())
118119
}
119-
*/
120120

121121
/// Converts the given tagged hash into a byte array
122122
fn into_inner(self) -> [u8; 32] {
@@ -133,7 +133,6 @@ pub trait CommitMerkleRoot: MerkleRoot {
133133
fn get_iv<Witness, App: Application>(node: &CommitNodeInner<Witness, App>) -> Self;
134134
}
135135

136-
/*
137136
/// Tagged SHA256 hash used for [`Type`]
138137
pub trait TypeMerkleRoot: MerkleRoot {
139138
/// Return the initial value for the given type.
@@ -142,7 +141,6 @@ pub trait TypeMerkleRoot: MerkleRoot {
142141
/// and returned as initial value
143142
fn get_iv(ty: &TypeInner) -> Self;
144143
}
145-
*/
146144

147145
/// Convenience macro for wrappers of `Midstate`.
148146
///

src/merkle/imr.rs

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,49 +18,65 @@
1818
//! In contrast to [`super::cmr`], `witness` data and both `disconnect` branches are included in the hash.
1919
//! The type of `witness` data is included in the hash via [`super::tmr`].
2020
21-
use crate::core::{ProgramNode, Term, TypedNode, Value};
21+
use crate::core::commit::CommitNodeInner;
22+
use crate::core::node::NodeType;
23+
use crate::core::{Node, Value};
2224
use crate::impl_midstate_wrapper;
2325
use crate::jet::Application;
2426
use crate::merkle::cmr::Cmr;
25-
use crate::merkle::common::{MerkleRoot, TermMerkleRoot};
27+
use crate::merkle::common::{CommitMerkleRoot, MerkleRoot};
2628
use bitcoin_hashes::sha256::Midstate;
29+
use std::rc::Rc;
2730

2831
/// Identity Merkle root
2932
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
3033
pub struct Imr(Midstate);
3134

3235
impl_midstate_wrapper!(Imr);
3336

34-
impl TermMerkleRoot for Imr {
35-
fn get_iv<Witness, App: Application>(term: &Term<Witness, App>) -> Self {
36-
match term {
37-
Term::Disconnect(..) => Imr::tag_iv(b"Simplicity-Draft\x1fIdentity\x1fdisconnect"),
38-
Term::Witness(..) => Imr::tag_iv(b"Simplicity-Draft\x1fIdentity\x1fwitness"),
39-
_ => Cmr::get_iv(term).into_inner().into(),
37+
impl CommitMerkleRoot for Imr {
38+
fn get_iv<Witness, App: Application>(node: &CommitNodeInner<Witness, App>) -> Self {
39+
match node {
40+
CommitNodeInner::Disconnect(_, _) => {
41+
Imr::tag_iv(b"Simplicity-Draft\x1fIdentity\x1fdisconnect")
42+
}
43+
CommitNodeInner::Witness(_) => Imr::tag_iv(b"Simplicity-Draft\x1fIdentity\x1fwitness"),
44+
_ => Cmr::get_iv(node).into_inner().into(),
4045
}
4146
}
4247
}
4348

44-
/// Compute the IMR of the given `node` that will be appended to the given `program`
45-
/// at the given `index`.
46-
pub(crate) fn compute_imr<App: Application>(
47-
program: &[ProgramNode<App>],
48-
node: &TypedNode<Value, App>,
49-
index: usize,
49+
#[allow(dead_code)]
50+
/// Compute the IMR of the given node (once finalized).
51+
///
52+
/// Nodes with left children require their finalized left child,
53+
/// while nodes with right children require their finalized right child.
54+
/// Witness nodes require their value and node type.
55+
pub(crate) fn compute_imr<Witness, App: Application>(
56+
node: &CommitNodeInner<Witness, App>,
57+
left: Option<Rc<Node<Value, App>>>,
58+
right: Option<Rc<Node<Value, App>>>,
59+
value: Option<&Value>,
60+
ty: &NodeType,
5061
) -> Imr {
51-
let imr_iv = Imr::get_iv(&node.term);
62+
let imr_iv = Imr::get_iv(node);
5263

53-
match node.term {
54-
Term::Iden | Term::Unit | Term::Fail(..) | Term::Hidden(..) | Term::Jet(..) => imr_iv,
55-
Term::InjL(i) | Term::InjR(i) | Term::Take(i) | Term::Drop(i) => {
56-
imr_iv.update_1(program[index - i].imr)
57-
}
58-
Term::Comp(i, j)
59-
| Term::Case(i, j)
60-
| Term::Pair(i, j)
61-
| Term::AssertL(i, j)
62-
| Term::AssertR(i, j)
63-
| Term::Disconnect(i, j) => imr_iv.update(program[index - i].imr, program[index - j].imr),
64-
Term::Witness(ref value) => imr_iv.update_value(value, &node.target_ty),
64+
match node {
65+
CommitNodeInner::Iden
66+
| CommitNodeInner::Unit
67+
| CommitNodeInner::Fail(..)
68+
| CommitNodeInner::Hidden(..)
69+
| CommitNodeInner::Jet(..) => imr_iv,
70+
CommitNodeInner::InjL(_)
71+
| CommitNodeInner::InjR(_)
72+
| CommitNodeInner::Take(_)
73+
| CommitNodeInner::Drop(_)
74+
| CommitNodeInner::Disconnect(_, _) => imr_iv.update_1(left.unwrap().imr),
75+
CommitNodeInner::Comp(_, _)
76+
| CommitNodeInner::Case(_, _)
77+
| CommitNodeInner::Pair(_, _)
78+
| CommitNodeInner::AssertL(_, _)
79+
| CommitNodeInner::AssertR(_, _) => imr_iv.update(left.unwrap().imr, right.unwrap().imr),
80+
CommitNodeInner::Witness(_) => imr_iv.update_value(value.unwrap(), ty.target.as_ref()),
6581
}
6682
}

src/merkle/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
2020
pub mod cmr;
2121
pub mod common;
22-
// pub mod imr;
23-
// pub mod tmr;
22+
pub mod imr;
23+
pub mod tmr;

0 commit comments

Comments
 (0)