Synthetic demo datademo

Every block, transaction, address and hash on this chain is generated from a fixed seed. None of them exists on any network, and none of these values can be looked up anywhere else. The execution trace is real — it is a recorded Noir program — but it is not the execution of the transaction it is published under.

Verified source

0x20f0…00b7

0x20f0d03c1058150377f77a15c0ccdde4e5bc00b7

Verification

Code hash
0x935ba960575473fc332aee4254fb64117645e402
Status
full match
Provider
demo-vendored
Compiler
nargo 1.0.0-beta.26
Language
noir
Bundle
sha1:f0b15e017d44fd4c9431cd3a771c156fb574c599

Sources

Nargo.toml7 lines
1[package]
2name = "tour_limits"
3type = "bin"
4authors = ["BlockTracer capability tour"]
5
6[dependencies]
7
Prover.toml3 lines
1seed = "203"
2limit = "500"
3
src/checked.nr32 lines
1// A small value object with an immutable-reference method, so the tour has a
2// `&T` beside its `&mut T` — the two are different forms and only one of them
3// is affected by the recorder gap NR-04.
4
5pub struct Bounds {
6 pub low: u32,
7 pub high: u32,
8}
9
10impl Bounds {
11 pub fn new(low: u32, high: u32) -> Self {
12 Bounds { low, high }
13 }
14
15 // Takes `self` by IMMUTABLE reference and returns a new value. Reading
16 // through `&self` is recorded correctly; it is only writing through a
17 // reference that is not (NR-04).
18 pub unconstrained fn span(self: &Self) -> u32 {
19 (*self).high - (*self).low
20 }
21
22 pub unconstrained fn widen(self, by: u32) -> Self {
23 let grown = Bounds { low: self.low, high: self.high + by };
24 assert(grown.span_by_value() >= self.span_by_value());
25 grown
26 }
27
28 pub unconstrained fn span_by_value(self) -> u32 {
29 self.high - self.low
30 }
31}
32
src/main.nr131 lines
1// TOUR: bounds, limits and overflow
2//
3// The subject is what happens at the EDGES of a type. In a circuit this is not
4// a curiosity: an addition that overflows is a failed constraint, and the
5// difference between "this wrapped" and "this aborted" is the difference
6// between a proof and no proof. A debugger is where that becomes visible.
7//
8// This program exists because `tools/noir-coverage.mjs` enumerates the
9// compiler's own AST and reported a cluster of forms as neither demonstrated
10// nor explained — globals, type aliases, shadowing, `loop`, the shift and
11// compound-assignment operators, `Option`, `u32::max_value()` and the wrapping
12// arithmetic traits. They are gathered here rather than sprinkled about because
13// they share a subject: every one of them is about the boundary of a type.
14
15mod checked;
16
17use checked::Bounds;
18use std::ops::WrappingAdd;
19
20// ── a global constant, and a type alias over it ───────────────────────────
21// A `global` is evaluated once at compile time and is in scope everywhere; the
22// alias gives the width a name that says what it is FOR rather than how wide it
23// is, which is the whole reason aliases exist.
24global HEADROOM: u32 = 8;
25type Counter = u32;
26
27// ── a NUMERIC type alias: the alias computes a length ─────────────────────
28// `Window<N>` is `N * 2` used in array-length position. The generic is a value,
29// not a type, so this is arithmetic the compiler performs on types.
30type Window<let N: u32>: u32 = N * 2;
31
32unconstrained fn saturating_add(a: u32, b: u32) -> u32 {
33 // `u32::max_value()` is a method reached through the TYPE rather than
34 // through a value — a path form of its own.
35 let ceiling = u32::max_value();
36 if a > ceiling - b {
37 ceiling
38 } else {
39 a + b
40 }
41}
42
43unconstrained fn wrapping_walk(start: u32) -> u32 {
44 // The wrapping traits are the language's way of asking for modular
45 // arithmetic explicitly, instead of getting it by accident. `wrapping_add`
46 // past the ceiling comes back to zero, and the recording shows it doing so
47 // one step at a time.
48 let mut v = start;
49 for _ in 0..3 {
50 v = v.wrapping_add(u32::max_value() / 2);
51 }
52 v
53}
54
55unconstrained fn shift_ladder(seed: u32) -> u32 {
56 // Every compound assignment operator the language has, in one place, plus
57 // both shifts. `seed` is masked first so the ladder cannot overflow —
58 // which is itself the point of the mask.
59 let mut v = seed & 0xff;
60 v <<= 3;
61 v |= 1;
62 v ^= 10;
63 v &= 0xfff;
64 v >>= 2;
65 v += HEADROOM;
66 v -= 1;
67 v *= 2;
68 v /= 3;
69 v %= 1000;
70 v
71}
72
73unconstrained fn first_over(limit: u32) -> Option<u32> {
74 // `loop` — unconstrained only, and it must contain a reachable `break`.
75 // The trip count is in no bound anywhere in the source, so the recording is
76 // the only place it exists.
77 //
78 // `Option` is how a Noir function says "there may be no answer" without a
79 // sentinel value a caller could mistake for a real one.
80 let mut n: Counter = 1;
81 loop {
82 n = n * 3;
83 if n > limit {
84 break;
85 }
86 }
87 if n > limit {
88 Option::some(n)
89 } else {
90 Option::none()
91 }
92}
93
94unconstrained fn main(seed: u32, limit: pub u32) -> pub u32 {
95 let sat = saturating_add(u32::max_value() - 2, 10);
96 let wrapped = wrapping_walk(seed);
97 let laddered = shift_ladder(seed);
98
99 // SHADOWING: the second `bounds` is a new binding with the same name, and
100 // the first is still in the recording at the steps before this line. That
101 // is the case a values pane has to get right and a printout cannot show at
102 // all.
103 let bounds = Bounds::new(0, HEADROOM);
104 let bounds = bounds.widen(limit);
105
106 // Destructuring a struct, and a tuple pattern beside it.
107 // `span` takes `&self` — reading THROUGH a reference, which the recorder
108 // handles correctly. Only writing through one does not (NR-04).
109 let by_ref = bounds.span();
110 let Bounds { low, high } = bounds;
111 let (span, midpoint) = (high - low, (high + low) / 2);
112
113 // A window whose length is computed by the numeric alias: N = 3, so 6.
114 // The turbofish is required in array-length position.
115 let window: [u32; Window::<3>] = [0, 1, 2, 3, 4, 5];
116
117 // `_` discards a value the program does not need, which is a binding form
118 // rather than an absence of one.
119 let _ = window[5];
120
121 let found = first_over(limit);
122 let reached = if found.is_some() { found.unwrap() } else { 0 };
123
124 assert_eq(sat, u32::max_value());
125 assert(span >= HEADROOM);
126 assert_eq(by_ref, span);
127 assert(window.len() == 6);
128
129 sat / 1000 + wrapped % 1000 + laddered + span + midpoint + reached % 1000
130}
131
This is a circuit, not a contract. It declares no ABI and no storage layout, so there is no interface list and no slot mapping to show. The source above is the whole of what it publishes.

Deployments

This code is deployed at one address. Any other address running the same bytecode would appear here too, already verified.