|
13 | 13 | // If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
14 | 14 | //
|
15 | 15 |
|
16 |
| -use crate::core::Value; |
17 |
| -use crate::impl_ref_wrapper; |
| 16 | +use crate::core::iter::DagIterable; |
| 17 | +use crate::core::node::NodeInner; |
| 18 | +use crate::core::{Node, Value}; |
| 19 | +use crate::decode::WitnessIterator; |
18 | 20 | use crate::jet::{Application, JetNode};
|
19 |
| -use crate::merkle::cmr; |
20 | 21 | use crate::merkle::cmr::Cmr;
|
| 22 | +use crate::merkle::{cmr, imr}; |
| 23 | +use crate::{analysis, impl_ref_wrapper, inference, Error}; |
| 24 | +use std::collections::HashMap; |
21 | 25 | use std::rc::Rc;
|
22 | 26 |
|
23 | 27 | /// Underlying combinator of a [`CommitNode`].
|
@@ -358,6 +362,82 @@ impl<Witness, App: Application> CommitNode<Witness, App> {
|
358 | 362 | | CommitNodeInner::Disconnect(_, r) => Some(r),
|
359 | 363 | }
|
360 | 364 | }
|
| 365 | + |
| 366 | + /// Create a new DAG, enriched with the witness and computed metadata. |
| 367 | + pub fn finalize<W: WitnessIterator>( |
| 368 | + &self, |
| 369 | + mut witness: W, |
| 370 | + ) -> Result<Rc<Node<Value, App>>, Error> { |
| 371 | + let root = RefWrapper(self); |
| 372 | + let post_order_it = root.iter_post_order(); |
| 373 | + let arrows = inference::get_arrows(post_order_it.clone())?; |
| 374 | + let mut to_finalized: HashMap<RefWrapper<Witness, App>, Rc<Node<Value, App>>> = |
| 375 | + HashMap::new(); |
| 376 | + |
| 377 | + for commit in post_order_it { |
| 378 | + let left = commit.get_left().map(|x| { |
| 379 | + to_finalized |
| 380 | + .get(&x) |
| 381 | + .expect("Children come before parent in post order") |
| 382 | + .clone() |
| 383 | + }); |
| 384 | + let right = commit.get_right().map(|x| { |
| 385 | + to_finalized |
| 386 | + .get(&x) |
| 387 | + .expect("Children come before parent in post order") |
| 388 | + .clone() |
| 389 | + }); |
| 390 | + |
| 391 | + let ty = arrows.finalize(&commit)?; |
| 392 | + let value = if let CommitNodeInner::Witness(_) = commit.0.inner { |
| 393 | + Some(witness.next(&ty.target)?) |
| 394 | + } else { |
| 395 | + None |
| 396 | + }; |
| 397 | + let imr = imr::compute_imr( |
| 398 | + &commit.0.inner, |
| 399 | + left.clone(), |
| 400 | + right.clone(), |
| 401 | + value.as_ref(), |
| 402 | + &ty, |
| 403 | + ); |
| 404 | + let bounds = analysis::compute_bounds(commit.0, left.clone(), right.clone(), &ty); |
| 405 | + |
| 406 | + // Verbose but necessary thanks to Rust |
| 407 | + let inner = match commit.0.inner { |
| 408 | + CommitNodeInner::Iden => NodeInner::Iden, |
| 409 | + CommitNodeInner::Unit => NodeInner::Unit, |
| 410 | + CommitNodeInner::InjL(_) => NodeInner::InjL(left.unwrap()), |
| 411 | + CommitNodeInner::InjR(_) => NodeInner::InjR(left.unwrap()), |
| 412 | + CommitNodeInner::Take(_) => NodeInner::Take(left.unwrap()), |
| 413 | + CommitNodeInner::Drop(_) => NodeInner::Drop(left.unwrap()), |
| 414 | + CommitNodeInner::Comp(_, _) => NodeInner::Comp(left.unwrap(), right.unwrap()), |
| 415 | + CommitNodeInner::Case(_, _) => NodeInner::Case(left.unwrap(), right.unwrap()), |
| 416 | + CommitNodeInner::AssertL(_, _) => NodeInner::AssertL(left.unwrap(), right.unwrap()), |
| 417 | + CommitNodeInner::AssertR(_, _) => NodeInner::AssertR(left.unwrap(), right.unwrap()), |
| 418 | + CommitNodeInner::Pair(_, _) => NodeInner::Pair(left.unwrap(), right.unwrap()), |
| 419 | + CommitNodeInner::Disconnect(_, _) => { |
| 420 | + NodeInner::Disconnect(left.unwrap(), right.unwrap()) |
| 421 | + } |
| 422 | + CommitNodeInner::Witness(_) => NodeInner::Witness(value.unwrap()), |
| 423 | + CommitNodeInner::Fail(hl, hr) => NodeInner::Fail(hl, hr), |
| 424 | + CommitNodeInner::Hidden(h) => NodeInner::Hidden(h), |
| 425 | + CommitNodeInner::Jet(jet) => NodeInner::Jet(jet), |
| 426 | + }; |
| 427 | + let node = Node { |
| 428 | + inner, |
| 429 | + cmr: commit.0.cmr, |
| 430 | + imr, |
| 431 | + ty, |
| 432 | + bounds, |
| 433 | + }; |
| 434 | + |
| 435 | + to_finalized.insert(commit, Rc::new(node)); |
| 436 | + } |
| 437 | + |
| 438 | + witness.finish()?; |
| 439 | + Ok(to_finalized.get(&root).unwrap().clone()) |
| 440 | + } |
361 | 441 | }
|
362 | 442 |
|
363 | 443 | /// Wrapper of references to [`CommitNode`].
|
|
0 commit comments