66//! frame management optimizations which can be used to great benefit.
77//!
88
9- use simplicity_sys:: ffi:: UWORD ;
109use std:: collections:: HashSet ;
1110
1211use crate :: jet:: Jet ;
13- use crate :: { Cmr , Ihr , Value } ;
12+ use crate :: node:: Inner ;
13+ use crate :: { Ihr , RedeemNode , Value } ;
1414
15- /// A type that keeps track of Bit Machine execution .
15+ /// An object which can be used to introspect the execution of the Bit Machine.
1616///
17- /// The trait is implemented for [`SetTracker`], that tracks which case branches were executed,
18- /// and it is implemented for [`NoTracker`], which is a dummy tracker that is
19- /// optimized out by the compiler.
17+ /// As an example of what you can do with this
2018///
21- /// The trait enables us to turn tracking on or off depending on a generic parameter.
19+ /// If this tracker records accesses to the left and right children of `Case` nodes, you
20+ /// may want to also implement [`PruningTracker`] so that this data can be used by
21+ /// [`RedeemNode::prune_with_tracking`] to prune the program. The most straightforward
22+ /// way to do this is to embed a [`SetTracker`] in your tracker and forward all the trait
23+ /// methods to that.
2224pub trait ExecTracker < J : Jet > {
23- /// Track the execution of the left branch of the case node with the given `ihr`.
24- fn track_left ( & mut self , ihr : Ihr ) ;
25-
26- /// Track the execution of the right branch of the case node with the given `ihr`.
27- fn track_right ( & mut self , ihr : Ihr ) ;
28-
29- /// Track the execution of a `jet` call with the given `input_buffer`, `output_buffer`, and call result `success`.
30- fn track_jet_call (
25+ /// Called immediately after a specific node of the program is executed, but before
26+ /// its children are executed.
27+ ///
28+ /// More precisely, this iterates through the through the Simplicity program tree in
29+ /// *pre* ordering. That is, for the program `comp iden unit` the nodes will be visited
30+ /// in the order `comp`, `iden`, `unit`.
31+ ///
32+ /// This method be used for logging, to track left or write accesses of the children of a
33+ /// `Case` node (to do this, call `input.peek_bit()`; false means left and true means right),
34+ /// to extract debug information (which may be embedded in the hidden CMR in `AssertL`
35+ /// and `AssertR` nodes, depending how the program was constructed), and so on.
36+ ///
37+ /// The provided arguments are:
38+ /// * `node` is the node which was just visited.
39+ /// * `input` is an iterator over the read frame when the node's execution began
40+ /// * for terminal nodes (`witness`, `unit`, `iden` and jets), `output` is an iterator
41+ /// the write frame after the node has executed. For non-terminal nodes, the contents
42+ /// of this iterator are unspecified and should not be relied upon.
43+ fn visit_node < ' d > (
3144 & mut self ,
32- jet : & J ,
33- input_buffer : & [ UWORD ] ,
34- output_buffer : & [ UWORD ] ,
35- success : bool ,
36- ) ;
37-
38- /// Track the potential execution of a `dbg!` call with the given `cmr` and `value`.
39- fn track_dbg_call ( & mut self , cmr : & Cmr , value : Value ) ;
40-
41- /// Check if tracking debug calls is enabled.
42- fn is_track_debug_enabled ( & self ) -> bool ;
45+ _node : & RedeemNode < J > ,
46+ _input : super :: FrameIter ,
47+ _output : super :: FrameIter ,
48+ ) {
49+ }
4350}
4451
4552pub trait PruneTracker < J : Jet > : ExecTracker < J > {
@@ -58,20 +65,21 @@ pub struct SetTracker {
5865}
5966
6067impl < J : Jet > ExecTracker < J > for SetTracker {
61- fn track_left ( & mut self , ihr : Ihr ) {
62- self . left . insert ( ihr) ;
63- }
64-
65- fn track_right ( & mut self , ihr : Ihr ) {
66- self . right . insert ( ihr) ;
67- }
68-
69- fn track_jet_call ( & mut self , _: & J , _: & [ UWORD ] , _: & [ UWORD ] , _: bool ) { }
70-
71- fn track_dbg_call ( & mut self , _: & Cmr , _: Value ) { }
72-
73- fn is_track_debug_enabled ( & self ) -> bool {
74- false
68+ fn visit_node < ' d > (
69+ & mut self ,
70+ node : & RedeemNode < J > ,
71+ mut input : super :: FrameIter ,
72+ _output : super :: FrameIter ,
73+ ) {
74+ match ( node. inner ( ) , input. next ( ) ) {
75+ ( Inner :: AssertL ( ..) | Inner :: Case ( ..) , Some ( false ) ) => {
76+ self . left . insert ( node. ihr ( ) ) ;
77+ }
78+ ( Inner :: AssertR ( ..) | Inner :: Case ( ..) , Some ( true ) ) => {
79+ self . right . insert ( node. ihr ( ) ) ;
80+ }
81+ _ => { }
82+ }
7583 }
7684}
7785
@@ -90,16 +98,17 @@ impl<J: Jet> PruneTracker<J> for SetTracker {
9098pub struct NoTracker ;
9199
92100impl < J : Jet > ExecTracker < J > for NoTracker {
93- fn track_left ( & mut self , _: Ihr ) { }
94-
95- fn track_right ( & mut self , _: Ihr ) { }
96-
97- fn track_jet_call ( & mut self , _: & J , _: & [ UWORD ] , _: & [ UWORD ] , _: bool ) { }
98-
99- fn track_dbg_call ( & mut self , _: & Cmr , _: Value ) { }
100-
101- fn is_track_debug_enabled ( & self ) -> bool {
102- // Set flag to test frame decoding in unit tests
103- cfg ! ( test)
101+ fn visit_node < ' d > (
102+ & mut self ,
103+ node : & RedeemNode < J > ,
104+ mut input : super :: FrameIter ,
105+ mut output : super :: FrameIter ,
106+ ) {
107+ if cfg ! ( test) {
108+ // In unit tests, attempt to decode values from the frames, confirming that
109+ // these work.
110+ let _input_val = Value :: from_padded_bits ( & mut input, & node. arrow ( ) . source ) ;
111+ let _output_val = Value :: from_padded_bits ( & mut output, & node. arrow ( ) . source ) ;
112+ }
104113 }
105114}
0 commit comments