Skip to content

Commit 71adc3d

Browse files
author
Mohammad Fawaz
committed
- Move to consensus version 13
- Add a few more tests
1 parent 4fb2cd3 commit 71adc3d

File tree

11 files changed

+380
-12
lines changed

11 files changed

+380
-12
lines changed

console/network/src/consensus_heights.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ pub enum ConsensusVersion {
4747
V11 = 11,
4848
/// V12: Prevent connection to forked nodes, disable StringType.
4949
V12 = 12,
50+
/// V13: Introduces external structs.
51+
V13 = 13,
5052
}
5153

5254
impl ToBytes for ConsensusVersion {
@@ -71,6 +73,7 @@ impl FromBytes for ConsensusVersion {
7173
10 => Ok(Self::V10),
7274
11 => Ok(Self::V11),
7375
12 => Ok(Self::V12),
76+
13 => Ok(Self::V13),
7477
_ => Err(io_error("Invalid consensus version")),
7578
}
7679
}
@@ -106,6 +109,7 @@ pub const CANARY_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CON
106109
(ConsensusVersion::V10, 8_600_000),
107110
(ConsensusVersion::V11, 9_510_000),
108111
(ConsensusVersion::V12, 9_906_000),
112+
(ConsensusVersion::V13, u32::MAX),
109113
];
110114

111115
/// The consensus version height for `MainnetV0`.
@@ -122,6 +126,7 @@ pub const MAINNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CO
122126
(ConsensusVersion::V10, 11_205_000),
123127
(ConsensusVersion::V11, 12_870_000),
124128
(ConsensusVersion::V12, 13_579_000),
129+
(ConsensusVersion::V13, u32::MAX),
125130
];
126131

127132
/// The consensus version heights for `TestnetV0`.
@@ -138,6 +143,7 @@ pub const TESTNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CO
138143
(ConsensusVersion::V10, 10_525_000),
139144
(ConsensusVersion::V11, 11_952_000),
140145
(ConsensusVersion::V12, 12_522_984),
146+
(ConsensusVersion::V13, u32::MAX),
141147
];
142148

143149
/// The consensus version heights when the `test_consensus_heights` feature is enabled.
@@ -154,6 +160,7 @@ pub const TEST_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); NUM_CONSENSU
154160
(ConsensusVersion::V10, 13),
155161
(ConsensusVersion::V11, 14),
156162
(ConsensusVersion::V12, 15),
163+
(ConsensusVersion::V13, 16),
157164
];
158165

159166
#[cfg(any(test, feature = "test", feature = "test_consensus_heights"))]

synthesizer/program/src/traits/stack_and_registers.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,16 @@ pub fn types_equivalent<N: Network>(
242242
struct_compare(&*external_stack, struct_type0, stack1, struct_type1)
243243
}
244244
(Struct(id), ExternalStruct(loc)) => {
245+
dbg!("HERE!");
245246
if id != loc.resource() {
246247
return Ok(false);
247248
}
248-
let struct_type0 = stack0.program().get_struct(id)?;
249-
let external_stack = stack1.get_external_stack(loc.program_id())?;
249+
dbg!("HERE2!");
250+
dbg!(&stack0.program());
251+
dbg!(&stack1.program());
252+
let struct_type0 = dbg!(stack0.program().get_struct(id)?);
253+
let external_stack = stack1.get_external_stack(dbg!(loc.program_id()))?;
254+
dbg!("found the external stack");
250255
let struct_type1 = external_stack.program().get_struct(loc.resource())?;
251256
struct_compare(stack0, struct_type0, &*external_stack, struct_type1)
252257
}

synthesizer/program/tests/instruction/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ mod ecdsa;
2020
mod hash;
2121
mod is;
2222
mod serialize;
23+
mod util;
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
// Copyright (c) 2019-2025 Provable Inc.
2+
// This file is part of the snarkVM library.
3+
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at:
7+
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
use console::{
17+
network::MainnetV0,
18+
prelude::*,
19+
program::{ArrayType, LiteralType, Locator, PlaintextType, U32},
20+
};
21+
use snarkvm_synthesizer_process::{Process, Stack};
22+
use snarkvm_synthesizer_program::{Program, types_equivalent};
23+
24+
type CurrentNetwork = MainnetV0;
25+
26+
// ---------- Helper ----------
27+
fn sample_stack(program_text: &str) -> Result<Stack<CurrentNetwork>> {
28+
let program = Program::from_str(program_text)?;
29+
let stack = Stack::new(&Process::load()?, &program)?;
30+
Ok(stack)
31+
}
32+
33+
// ---------- 1️⃣ Literal equivalence ----------
34+
#[test]
35+
fn test_literal_equivalence() -> Result<()> {
36+
let stack = sample_stack("program p_lit.aleo; function main:")?;
37+
38+
let u32_ty = PlaintextType::Literal(LiteralType::U32);
39+
let u64_ty = PlaintextType::Literal(LiteralType::U64);
40+
41+
assert!(types_equivalent(&stack, &u32_ty, &stack, &u32_ty)?);
42+
assert!(!types_equivalent(&stack, &u32_ty, &stack, &u64_ty)?);
43+
44+
Ok(())
45+
}
46+
47+
// ---------- 2️⃣ Struct equivalence (same program) ----------
48+
#[test]
49+
fn test_struct_equivalence_same_program() -> Result<()> {
50+
let program_text = r"
51+
program p_struct.aleo;
52+
struct Foo: x as u32; y as u32;
53+
struct Bar: x as u32; y as u32; z as u32;
54+
function main:
55+
";
56+
57+
let stack = sample_stack(program_text)?;
58+
let foo_ty = PlaintextType::Struct("Foo".try_into()?);
59+
let bar_ty = PlaintextType::Struct("Bar".try_into()?);
60+
61+
assert!(types_equivalent(&stack, &foo_ty, &stack, &foo_ty)?);
62+
assert!(!types_equivalent(&stack, &foo_ty, &stack, &bar_ty)?);
63+
64+
Ok(())
65+
}
66+
67+
// ---------- 3️⃣ Array equivalence ----------
68+
#[test]
69+
fn test_array_equivalence() -> Result<()> {
70+
let stack = sample_stack("program p_array.aleo; function main:")?;
71+
72+
let u32_ty = PlaintextType::Literal(LiteralType::U32);
73+
74+
let array1 = PlaintextType::Array(ArrayType::new(*Box::new(u32_ty.clone()), vec![U32::new(3)])?);
75+
let array2 = PlaintextType::Array(ArrayType::new(*Box::new(u32_ty.clone()), vec![U32::new(3)])?);
76+
let array3 = PlaintextType::Array(ArrayType::new(*Box::new(u32_ty.clone()), vec![U32::new(4)])?);
77+
78+
assert!(types_equivalent(&stack, &array1, &stack, &array2)?);
79+
assert!(!types_equivalent(&stack, &array1, &stack, &array3)?);
80+
81+
Ok(())
82+
}
83+
84+
// ---------- 4️⃣ Cross-program struct equivalence ----------
85+
#[test]
86+
fn test_cross_program_structs_equivalence() -> Result<()> {
87+
// ---------- Sample stacks ----------
88+
let s1 = sample_stack("program p1.aleo; struct Foo: x as u32; y as u32; function main:")?;
89+
let s2 = sample_stack("program p2.aleo; struct Foo: x as u32; y as u32; function main:")?;
90+
let s3 = sample_stack("program p3.aleo; struct Foo: x as u32; y as u32; z as u32; function main:")?;
91+
let s4 = sample_stack("program p4.aleo; struct Bar: x as u32; y as u32; function main:")?;
92+
let s5 = sample_stack(
93+
"program p5.aleo; struct Inner: a as u32; struct Outer: inner as Inner; b as u32; function main:",
94+
)?;
95+
let s6 = sample_stack(
96+
"program p6.aleo; struct Inner: a as u32; struct Outer: inner as Inner; b as u32; function main:",
97+
)?;
98+
let s7 = sample_stack(
99+
"program p7.aleo; struct Inner: a as u32; struct Outer: inner as Inner; c as u32; function main:",
100+
)?;
101+
102+
// ---------- Define types ----------
103+
let foo_ty = PlaintextType::Struct("Foo".try_into()?);
104+
let foo_ty_diff = PlaintextType::Struct("Foo".try_into()?); // will use s3 to test different fields
105+
let bar_ty = PlaintextType::Struct("Bar".try_into()?);
106+
let outer_ty = PlaintextType::Struct("Outer".try_into()?);
107+
let outer_ty_diff = PlaintextType::Struct("Outer".try_into()?);
108+
109+
// ---------- Assertions ----------
110+
// Same name, same fields
111+
assert!(types_equivalent(&s1, &foo_ty, &s2, &foo_ty)?);
112+
113+
// Same name, different fields
114+
assert!(!types_equivalent(&s1, &foo_ty, &s3, &foo_ty_diff)?);
115+
116+
// Different names, same fields
117+
assert!(!types_equivalent(&s1, &foo_ty, &s4, &bar_ty)?);
118+
119+
// Nested structs, same fields
120+
assert!(types_equivalent(&s5, &outer_ty, &s6, &outer_ty)?);
121+
122+
// Nested structs, different fields in inner
123+
assert!(!types_equivalent(&s5, &outer_ty, &s7, &outer_ty_diff)?);
124+
125+
Ok(())
126+
}
127+
128+
// ---------- 5️⃣ External vs Local struct ----------
129+
#[test]
130+
fn test_external_vs_local_struct_equivalence() -> Result<()> {
131+
// Create a single process to hold both programs
132+
let mut process = Process::<CurrentNetwork>::load()?;
133+
134+
// 1️⃣ External program
135+
let external_program = Program::from_str(
136+
r"program external.aleo;
137+
struct Foo: x as u32; y as u32;
138+
function main:",
139+
)?;
140+
process.add_program(&external_program)?;
141+
142+
// 2️⃣ Local program that imports external
143+
let local_program = Program::from_str(
144+
r"import external.aleo;
145+
program local.aleo;
146+
struct Foo: x as u32; y as u32;
147+
function main:",
148+
)?;
149+
process.add_program(&local_program)?;
150+
151+
// 3️⃣ Retrieve the stack for the local program
152+
let s_local = process.get_stack(local_program.id())?;
153+
154+
let local_ty = PlaintextType::<CurrentNetwork>::Struct("Foo".try_into()?);
155+
let external_ty =
156+
PlaintextType::<CurrentNetwork>::ExternalStruct(Locator::new("external.aleo".try_into()?, "Foo".try_into()?));
157+
158+
// Local vs External
159+
assert!(types_equivalent(&*s_local, &local_ty, &*s_local, &external_ty)?);
160+
161+
// External vs Local
162+
assert!(types_equivalent(&*s_local, &external_ty, &*s_local, &local_ty)?);
163+
164+
// External vs External
165+
assert!(types_equivalent(&*s_local, &external_ty, &*s_local, &external_ty)?);
166+
167+
Ok(())
168+
}
169+
170+
#[test]
171+
fn test_external_and_array_struct_equivalence() -> Result<()> {
172+
use console::program::{ArrayType, LiteralType, Locator, PlaintextType, U32};
173+
use snarkvm_synthesizer_program::types_equivalent;
174+
175+
// ---------- 1️⃣ Create a single process ----------
176+
let mut process = Process::<CurrentNetwork>::load()?;
177+
178+
// ---------- 2️⃣ External program ----------
179+
let external_program = Program::from_str(
180+
r"program external.aleo;
181+
struct Foo: x as u32; y as u32;
182+
struct Bar: a as u32; b as u32;
183+
function main:",
184+
)?;
185+
process.add_program(&external_program)?;
186+
187+
// ---------- 3️⃣ Local program importing external ----------
188+
let local_program = Program::from_str(
189+
r"import external.aleo;
190+
program local.aleo;
191+
struct Foo: x as u32; y as u32;
192+
struct Baz: f as Foo; g as u32;
193+
function main:",
194+
)?;
195+
process.add_program(&local_program)?;
196+
197+
// ---------- 4️⃣ Retrieve the stack ----------
198+
let s_local = process.get_stack(local_program.id())?;
199+
200+
// ---------- 5️⃣ Define types ----------
201+
let local_foo = PlaintextType::Struct("Foo".try_into()?);
202+
let external_foo = PlaintextType::ExternalStruct(Locator::new("external.aleo".try_into()?, "Foo".try_into()?));
203+
204+
let local_baz = PlaintextType::Struct("Baz".try_into()?);
205+
206+
// Arrays of literals
207+
let u32_lit = PlaintextType::Literal(LiteralType::U32);
208+
let array_3 = PlaintextType::Array(ArrayType::new(*Box::new(u32_lit.clone()), vec![U32::new(3)])?);
209+
let array_4 = PlaintextType::Array(ArrayType::new(*Box::new(u32_lit.clone()), vec![U32::new(4)])?);
210+
211+
// Arrays of structs
212+
let array_foo_2 = PlaintextType::Array(ArrayType::new(*Box::new(local_foo.clone()), vec![U32::new(2)])?);
213+
let array_external_foo_2 =
214+
PlaintextType::Array(ArrayType::new(*Box::new(external_foo.clone()), vec![U32::new(2)])?);
215+
216+
// ---------- 6️⃣ Assertions ----------
217+
218+
// Local vs External struct
219+
assert!(types_equivalent(&*s_local, &local_foo, &*s_local, &external_foo)?);
220+
assert!(types_equivalent(&*s_local, &external_foo, &*s_local, &local_foo)?);
221+
222+
// External vs External
223+
assert!(types_equivalent(&*s_local, &external_foo, &*s_local, &external_foo)?);
224+
225+
// Arrays of literals
226+
assert!(types_equivalent(&*s_local, &array_3, &*s_local, &array_3)?);
227+
assert!(!types_equivalent(&*s_local, &array_3, &*s_local, &array_4)?);
228+
229+
// Arrays of structs
230+
assert!(types_equivalent(&*s_local, &array_foo_2, &*s_local, &array_external_foo_2)?);
231+
232+
// Nested struct inside local
233+
assert!(types_equivalent(&*s_local, &local_baz, &*s_local, &local_baz)?);
234+
235+
Ok(())
236+
}

synthesizer/src/vm/tests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ mod test_v10;
2626
mod test_v11;
2727

2828
#[cfg(feature = "test")]
29-
mod test_v12;
29+
mod test_v13;
3030

3131
#[cfg(feature = "test")]
3232
use super::*;
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ use console::network::ConsensusVersion;
2323
use snarkvm_utilities::TestRng;
2424

2525
// This test verifies that a program with external structs cannot be deployed on
26-
// consensus version 9.
26+
// consensus version 11.
2727
#[test]
2828
fn test_deploy_external_structs_v10() {
29-
// Use V10 rather than V11 to make sure we still won't be on V12
29+
// Use V11 rather than V12 to make sure we still won't be on V13
3030
// when deploying the second program.
31-
let block = deploy_programs(ConsensusVersion::V10);
31+
let block = deploy_programs(ConsensusVersion::V11);
3232

3333
assert_eq!(block.transactions().num_accepted(), 0);
3434
assert_eq!(block.transactions().num_rejected(), 0);
@@ -38,8 +38,8 @@ fn test_deploy_external_structs_v10() {
3838
// This test verifies that a program with external structs can be deployed on
3939
// consensus version 12.
4040
#[test]
41-
fn test_deploy_external_structs_v12() {
42-
let block = deploy_programs(ConsensusVersion::V12);
41+
fn test_deploy_external_structs_v13() {
42+
let block = deploy_programs(ConsensusVersion::V13);
4343

4444
assert_eq!(block.transactions().num_accepted(), 1);
4545
assert_eq!(block.transactions().num_rejected(), 0);

synthesizer/src/vm/verify.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,18 +256,18 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
256256
);
257257
}
258258

259-
// If the `CONSENSUS_VERSION` is less than `V12`, then verify that:
259+
// If the `CONSENSUS_VERSION` is less than `V13`, then verify that:
260260
// - the program does not use the external struct syntax `some_program.aleo/StructT`
261-
// If the `CONSENSUS_VERSION` is greater than or equal to `V12`, then verify that:
261+
// If the `CONSENSUS_VERSION` is greater than or equal to `V13`, then verify that:
262262
// - the program's mappings do not use non-existent structs.
263-
if consensus_version < ConsensusVersion::V12 {
263+
if consensus_version < ConsensusVersion::V13 {
264264
ensure!(
265265
!deployment.program().contains_external_struct(),
266266
"Invalid deployment transaction '{id}' - external structs may only be used beginning with Consensus version 10"
267267
);
268268
}
269269

270-
if consensus_version >= ConsensusVersion::V12 {
270+
if consensus_version >= ConsensusVersion::V13 {
271271
self.process.read().mapping_types_exist(deployment.program())?;
272272
}
273273

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
errors: []
2+
outputs:
3+
- verified: true
4+
execute:
5+
committee_array_test.aleo/main:
6+
outputs: []
7+
speculate: the execution was accepted
8+
add_next_block: succeeded.
9+
additional:
10+
- child_outputs:
11+
credits.aleo/fee_public:
12+
outputs:
13+
- '{"type":"future","id":"4217238272995135610737415165368736931078444858571711422898870491529866562856field","value":"{\n program_id: credits.aleo,\n function_name: fee_public,\n arguments: [\n aleo186yu9rn7k3da66rhmwj3mpkh4aqs2wsu52nfdy6xg2wh7l69xvrqlled0e,\n 1290u64\n ]\n}"}'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
errors: []
2+
outputs:
3+
- verified: true
4+
execute:
5+
committee_test.aleo/main:
6+
outputs: []
7+
speculate: the execution was accepted
8+
add_next_block: succeeded.
9+
additional:
10+
- child_outputs:
11+
credits.aleo/fee_public:
12+
outputs:
13+
- '{"type":"future","id":"7028676572901512266841148061498709341769090753580542406028590304440583867290field","value":"{\n program_id: credits.aleo,\n function_name: fee_public,\n arguments: [\n aleo153m2erq5d0fqxmerjln3x2f6vrdz3hkacxnn2cktch5y8q89rv9qu3lhju,\n 1284u64\n ]\n}"}'

0 commit comments

Comments
 (0)