pub trait BasicSnippet {
// Required methods
fn inputs(&self) -> Vec<(DataType, String)>;
fn outputs(&self) -> Vec<(DataType, String)>;
fn entrypoint(&self) -> String;
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction>;
// Provided methods
fn annotated_code(&self, library: &mut Library) -> Vec<LabelledInstruction> { ... }
fn link_for_isolated_run(&self) -> Vec<LabelledInstruction> { ... }
fn init_stack_for_isolated_run(&self) -> Vec<BFieldElement> { ... }
fn stack_diff(&self) -> isize { ... }
fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint> { ... }
}
Expand description
§Dyn-Compatibility
This trait is dyn-compatible (previously known as “object safe”).
Required Methods§
fn inputs(&self) -> Vec<(DataType, String)>
fn outputs(&self) -> Vec<(DataType, String)>
fn entrypoint(&self) -> String
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction>
Provided Methods§
fn annotated_code(&self, library: &mut Library) -> Vec<LabelledInstruction>
fn link_for_isolated_run(&self) -> Vec<LabelledInstruction>
Sourcefn init_stack_for_isolated_run(&self) -> Vec<BFieldElement>
fn init_stack_for_isolated_run(&self) -> Vec<BFieldElement>
Initial stack on program start, when the snippet runs in isolation.
fn stack_diff(&self) -> isize
Sourcefn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint>
fn sign_offs(&self) -> HashMap<Reviewer, SignOffFingerprint>
Contains an entry for every sign off.
Many of the snippets defined in this TASM library are critical for the consensus logic of the blockchain Neptune Cash. Therefore, it is paramount that the snippets are free of errors. In order to catch as many errors as possible, the snippets are reviewed by as many developers as possible. The requirements of such a review are listed here.
A reviewer can (and should) sign off on any snippet they have reviewed and for which they found no defects. This is done by adding that snippet’s fingerprint (at the time) to the overriding implementation of this method on that snippet.
Together with the tools git blame
and cryptographic
signing of commits, this makes sign-offs traceable. It also guarantees
that changes to snippets that have already been signed-off are easy to
detect.
§For Reviewers
§Modifying snippets
While the primary intention of the review process is to review a snippet, there are circumstances under which modifying it is acceptable.
Modifying a snippet to simplify reviewing that snippet is fair game. A
common example of this case is replacing a swap
-juggle chain with a few
pick
s & place
s.
Modifying a snippet in order to improve performance should only happen if the performance impact is meaningful. The currently agreed-upon threshold is 0.5% of at least one consensus program.
It is acceptable, and can be desired, to modify a snippet by including assumption checks. For example, if the snippet’s pre-conditions require some input to fall within a certain range, it is fine to add a corresponding range check to the snippet. Removing existing checks of such nature is considered bad practice.
In either case, modifying a snippet that has already been reviewed and signed off by someone else in a way that alters its fingerprint requires their consent.
§Checklist
Use the following checklist to guide your review. Signing off on a snippet means that in your eyes, all points on this checklist are true.
- the snippet’s documentation lists pre- and post-conditions
- the snippet makes no assumptions outside the stated pre-conditions
- given all pre-conditions, all post-conditions are met
- whenever this snippet calls another snippet, all of that other snippet’s pre-conditions are met
- all dynamic memory offsets are range-checked before they are used
- each field accessor is used at most once per struct instance, or range-checked before each use
- reading from non-deterministically initialized memory only happens from the region specified in the memory convention
- memory-writes only happen outside of page 0 (see memory convention)
§Documentation Template
If a snippet you are reviewing is not (properly) documented yet, you can use
the following template to document the type implementing BasicSnippet
.
/// ### Behavior
///
/// ```text
/// BEFORE: _
/// AFTER: _
/// ```
///
/// ### Preconditions
///
/// - condition
///
/// ### Postconditions
///
/// - condition
§Non-Unit Structs
Most, but not all types implementing BasicSnippet
are unit structs.
Fingerprinting gets more difficult for non-unit structs.
In such cases, a default instantiation should be selected and signed off.
§Overriding this Method
This default implementation is intended to be overridden for any snippet that has been signed off, but should not call the fingerprint method.