Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 21 additions & 7 deletions circuit/program/src/request/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ impl<A: Aleo> Request<A> {
/// and the signature is valid.
///
/// Verifies (challenge == challenge') && (address == address') && (serial_numbers == serial_numbers') where:
/// challenge' := HashToScalar(r * G, pk_sig, pr_sig, signer, \[tvk, tcm, function ID, input IDs\])
/// challenge' := HashToScalar(r * G, pk_sig, pr_sig, signer, \[tvk, tcm, function ID, is_root, program checksum?, input IDs\])
/// The program checksum must be provided if the program has a constructor and should not be provided otherwise.
pub fn verify(
&self,
input_types: &[console::ValueType<A::Network>],
tpk: &Group<A>,
root_tvk: Option<Field<A>>,
is_root: Boolean<A>,
program_checksum: Option<Field<A>>,
) -> Boolean<A> {
// Compute the function ID.
let function_id = compute_function_id(&self.network_id, &self.program_id, &self.function_name);
Expand All @@ -40,6 +42,10 @@ impl<A: Aleo> Request<A> {
message.push(self.tcm.clone());
message.push(function_id);
message.push(is_root);
// Add the program checksum to the signature message if it was provided.
if let Some(program_checksum) = program_checksum {
message.push(program_checksum);
}

// Check the input IDs and construct the rest of the signature message.
let (input_checks, append_to_message) = Self::check_input_ids::<true>(
Expand All @@ -61,6 +67,7 @@ impl<A: Aleo> Request<A> {
None => A::halt("Missing input elements in request verification"),
}

// Determine the root transition view key.
let root_tvk = root_tvk.unwrap_or(Field::<A>::new(Mode::Private, self.tvk.eject_value()));

// Verify the transition public key and commitments are well-formed.
Expand Down Expand Up @@ -324,6 +331,7 @@ mod tests {
num_public: u64,
num_private: u64,
num_constraints: u64,
set_program_checksum: bool,
) -> Result<()> {
let rng = &mut TestRng::default();

Expand Down Expand Up @@ -366,9 +374,10 @@ mod tests {

// Sample 'root_tvk'.
let root_tvk = None;

// Sample 'is_root'.
let is_root = true;
// Sample 'program_checksum'.
let program_checksum = set_program_checksum.then(|| console::Field::from_u64(i as u64));

// Compute the signed request.
let request = console::Request::sign(
Expand All @@ -379,18 +388,20 @@ mod tests {
&input_types,
root_tvk,
is_root,
program_checksum,
rng,
)?;
assert!(request.verify(&input_types, is_root));
assert!(request.verify(&input_types, is_root, program_checksum));

// Inject the request into a circuit.
let tpk = Group::<Circuit>::new(mode, request.to_tpk());
let request = Request::<Circuit>::new(mode, request);
let is_root = Boolean::new(mode, is_root);
let program_checksum = program_checksum.map(|hash| Field::<Circuit>::new(mode, hash));

Circuit::scope(format!("Request {i}"), || {
let root_tvk = None;
let candidate = request.verify(&input_types, &tpk, root_tvk, is_root);
let candidate = request.verify(&input_types, &tpk, root_tvk, is_root, program_checksum);
assert!(candidate.eject_value());
match mode.is_constant() {
true => assert_scope!(<=num_constants, <=num_public, <=num_private, <=num_constraints),
Expand Down Expand Up @@ -424,16 +435,19 @@ mod tests {
// Note: This is correct. At this (high) level of a program, we override the default mode in the `Record` case,
// based on the user-defined visibility in the record type. Thus, we have nonzero private and constraint values.
// These bounds are determined experimentally.
check_verify(Mode::Constant, 43000, 0, 18000, 18000)
check_verify(Mode::Constant, 43000, 0, 18000, 18000, false)?;
check_verify(Mode::Constant, 43000, 0, 18273, 18296, true)
}

#[test]
fn test_sign_and_verify_public() -> Result<()> {
check_verify(Mode::Public, 40131, 0, 26675, 26702)
check_verify(Mode::Public, 40131, 0, 26675, 26702, false)?;
check_verify(Mode::Public, 40131, 0, 27190, 27217, true)
}

#[test]
fn test_sign_and_verify_private() -> Result<()> {
check_verify(Mode::Private, 40131, 0, 26675, 26702)
check_verify(Mode::Private, 40131, 0, 26675, 26702, false)?;
check_verify(Mode::Private, 40131, 0, 27190, 27217, true)
}
}
3 changes: 3 additions & 0 deletions console/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ version = "=3.7.1"
[dependencies.anyhow]
version = "1.0.73"

[dependencies.enum-iterator]
version = "2.1"

[dependencies.indexmap]
version = "2"

Expand Down
22 changes: 2 additions & 20 deletions console/network/src/canary_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,29 +136,11 @@ impl Network for CanaryV0 {
/// A list of (consensus_version, block_height) pairs indicating when each consensus version takes effect.
/// Documentation for what is changed at each version can be found in `ConsensusVersion`.
#[cfg(not(any(test, feature = "test", feature = "test_consensus_heights")))]
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 2_900_000),
(ConsensusVersion::V3, 4_560_000),
(ConsensusVersion::V4, 5_730_000),
(ConsensusVersion::V5, 5_780_000),
(ConsensusVersion::V6, 6_240_000),
(ConsensusVersion::V7, 6_895_000),
(ConsensusVersion::V8, 999_999_999),
];
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = CANARY_V0_CONSENSUS_VERSION_HEIGHTS;
/// A list of (consensus_version, block_height) pairs indicating when each consensus version takes effect.
/// Documentation for what is changed at each version can be found in `ConsensusVersion`.
#[cfg(any(test, feature = "test", feature = "test_consensus_heights"))]
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 10),
(ConsensusVersion::V3, 11),
(ConsensusVersion::V4, 12),
(ConsensusVersion::V5, 13),
(ConsensusVersion::V6, 14),
(ConsensusVersion::V7, 15),
(ConsensusVersion::V8, 16),
];
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = TEST_CONSENSUS_VERSION_HEIGHTS;
/// The genesis block coinbase target.
#[cfg(not(feature = "test_targets"))]
const GENESIS_COINBASE_TARGET: u64 = (1u64 << 29).saturating_sub(1);
Expand Down
64 changes: 64 additions & 0 deletions console/network/src/consensus_heights.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2019-2025 Provable Inc.
// This file is part of the snarkVM library.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::ConsensusVersion;

/// The consensus version height for `CanaryV0`.
pub const CANARY_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 2_900_000),
(ConsensusVersion::V3, 4_560_000),
(ConsensusVersion::V4, 5_730_000),
(ConsensusVersion::V5, 5_780_000),
(ConsensusVersion::V6, 6_240_000),
(ConsensusVersion::V7, 6_895_000),
(ConsensusVersion::V8, 999_999_999),
];

/// The consensus version height for `MainnetV0`.
pub const MAINNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 2_800_000),
(ConsensusVersion::V3, 4_900_000),
(ConsensusVersion::V4, 6_135_000),
(ConsensusVersion::V5, 7_060_000),
(ConsensusVersion::V6, 7_560_000),
(ConsensusVersion::V7, 7_570_000),
(ConsensusVersion::V8, 999_999_999),
];

/// The consensus version heights for `TestnetV0`.
pub const TESTNET_V0_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 2_950_000),
(ConsensusVersion::V3, 4_800_000),
(ConsensusVersion::V4, 6_625_000),
(ConsensusVersion::V5, 6_765_000),
(ConsensusVersion::V6, 7_600_000),
(ConsensusVersion::V7, 8_365_000),
(ConsensusVersion::V8, 999_999_999),
];

/// The consensus version heights for `TestConsensusV0`.
pub const TEST_CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 10),
(ConsensusVersion::V3, 11),
(ConsensusVersion::V4, 12),
(ConsensusVersion::V5, 13),
(ConsensusVersion::V6, 14),
(ConsensusVersion::V7, 15),
(ConsensusVersion::V8, 16),
];
31 changes: 29 additions & 2 deletions console/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,27 @@ pub use helpers::*;
mod canary_v0;
pub use canary_v0::*;

mod consensus_heights;
pub use consensus_heights::*;

mod mainnet_v0;
pub use mainnet_v0::*;

mod testnet_v0;

pub use testnet_v0::*;

pub mod prelude {
pub use crate::{ConsensusVersion, Network, consensus_config_value, environment::prelude::*};
pub use crate::{
CANARY_V0_CONSENSUS_VERSION_HEIGHTS,
ConsensusVersion,
MAINNET_V0_CONSENSUS_VERSION_HEIGHTS,
Network,
TEST_CONSENSUS_VERSION_HEIGHTS,
TESTNET_V0_CONSENSUS_VERSION_HEIGHTS,
consensus_config_value,
environment::prelude::*,
};
}

use crate::environment::prelude::*;
Expand All @@ -51,6 +64,7 @@ use snarkvm_console_collections::merkle_tree::{MerklePath, MerkleTree};
use snarkvm_console_types::{Field, Group, Scalar};
use snarkvm_curves::PairingEngine;

use enum_iterator::{Sequence, last};
use indexmap::IndexMap;
use once_cell::sync::OnceCell;
use std::sync::Arc;
Expand All @@ -71,7 +85,7 @@ pub(crate) type VarunaVerifyingKey<N> = CircuitVerifyingKey<<N as Environment>::

/// The different consensus versions.
/// If you need the version active for a specific height, see: `N::CONSENSUS_VERSION`.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Sequence)]
pub enum ConsensusVersion {
/// V1: The initial genesis consensus version.
V1 = 1,
Expand All @@ -92,6 +106,12 @@ pub enum ConsensusVersion {
V8 = 8,
}

impl ConsensusVersion {
pub fn latest() -> Self {
last::<ConsensusVersion>().unwrap()
}
}

pub trait Network:
'static
+ Environment
Expand Down Expand Up @@ -201,6 +221,8 @@ pub trait Network:
const MAX_COMMANDS: usize = u16::MAX as usize;
/// The maximum number of write commands in finalize.
const MAX_WRITES: u16 = 16;
/// The maximum number of `position` commands in finalize.
const MAX_POSITIONS: usize = u8::MAX as usize;

/// The maximum number of inputs per transition.
const MAX_INPUTS: usize = 16;
Expand Down Expand Up @@ -583,4 +605,9 @@ mod tests {

constants_equal_length::<MainnetV0, TestnetV0, CanaryV0>();
}

#[test]
fn test_latest_consensus_version() {
assert_eq!(ConsensusVersion::latest(), ConsensusVersion::V8); // UPDATE ME, if changed.
}
}
22 changes: 2 additions & 20 deletions console/network/src/mainnet_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,29 +137,11 @@ impl Network for MainnetV0 {
/// A list of (consensus_version, block_height) pairs indicating when each consensus version takes effect.
/// Documentation for what is changed at each version can be found in `ConsensusVersion`.
#[cfg(not(any(test, feature = "test")))]
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 2_800_000),
(ConsensusVersion::V3, 4_900_000),
(ConsensusVersion::V4, 6_135_000),
(ConsensusVersion::V5, 7_060_000),
(ConsensusVersion::V6, 7_560_000),
(ConsensusVersion::V7, 7_570_000),
(ConsensusVersion::V8, 999_999_999),
];
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = MAINNET_V0_CONSENSUS_VERSION_HEIGHTS;
/// A list of (consensus_version, block_height) pairs indicating when each consensus version takes effect.
/// Documentation for what is changed at each version can be found in `ConsensusVersion`.
#[cfg(any(test, feature = "test"))]
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 10),
(ConsensusVersion::V3, 11),
(ConsensusVersion::V4, 12),
(ConsensusVersion::V5, 13),
(ConsensusVersion::V6, 14),
(ConsensusVersion::V7, 15),
(ConsensusVersion::V8, 16),
];
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = TEST_CONSENSUS_VERSION_HEIGHTS;
/// The genesis block coinbase target.
#[cfg(not(feature = "test"))]
const GENESIS_COINBASE_TARGET: u64 = (1u64 << 29).saturating_sub(1);
Expand Down
22 changes: 2 additions & 20 deletions console/network/src/testnet_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,29 +136,11 @@ impl Network for TestnetV0 {
/// A list of (consensus_version, block_height) pairs indicating when each consensus version takes effect.
/// Documentation for what is changed at each version can be found in `ConsensusVersion`.
#[cfg(not(any(test, feature = "test", feature = "test_consensus_heights")))]
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 2_950_000),
(ConsensusVersion::V3, 4_800_000),
(ConsensusVersion::V4, 6_625_000),
(ConsensusVersion::V5, 6_765_000),
(ConsensusVersion::V6, 7_600_000),
(ConsensusVersion::V7, 8_365_000),
(ConsensusVersion::V8, 999_999_999),
];
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = TESTNET_V0_CONSENSUS_VERSION_HEIGHTS;
/// A list of (consensus_version, block_height) pairs indicating when each consensus version takes effect.
/// Documentation for what is changed at each version can be found in `ConsensusVersion`.
#[cfg(any(test, feature = "test", feature = "test_consensus_heights"))]
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = [
(ConsensusVersion::V1, 0),
(ConsensusVersion::V2, 10),
(ConsensusVersion::V3, 11),
(ConsensusVersion::V4, 12),
(ConsensusVersion::V5, 13),
(ConsensusVersion::V6, 14),
(ConsensusVersion::V7, 15),
(ConsensusVersion::V8, 16),
];
const CONSENSUS_VERSION_HEIGHTS: [(ConsensusVersion, u32); 8] = TEST_CONSENSUS_VERSION_HEIGHTS;
/// The genesis block coinbase target.
#[cfg(not(feature = "test_targets"))]
const GENESIS_COINBASE_TARGET: u64 = (1u64 << 29).saturating_sub(1);
Expand Down
2 changes: 1 addition & 1 deletion console/program/src/owner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<N: Network> ProgramOwner<N> {
// Sign the transaction ID.
let signature = private_key.sign(&[deployment_id], rng)?;
// Return the program owner.
Ok(Self { signature, address })
Ok(Self { address, signature })
}

/// Initializes a new program owner from an address and signature.
Expand Down
14 changes: 9 additions & 5 deletions console/program/src/request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,6 @@ mod test_helpers {
let input_external_record = Value::from_str(&record_string).unwrap();
let inputs = vec![input_constant, input_public, input_private, input_record, input_external_record];

// Construct 'is_root'.
let is_root = false;

// Construct the input types.
let input_types = [
ValueType::from_str("amount.constant").unwrap(),
Expand All @@ -208,11 +205,18 @@ mod test_helpers {

// Sample root_tvk.
let root_tvk = None;
// Construct 'is_root'.
let is_root = Uniform::rand(rng);
// Sample the program checksum.
let program_checksum = match i % 2 == 0 {
true => Some(Field::rand(rng)),
false => None,
};

// Compute the signed request.
let request =
Request::sign(&private_key, program_id, function_name, inputs.into_iter(), &input_types, root_tvk, is_root, rng).unwrap();
assert!(request.verify(&input_types, is_root));
Request::sign(&private_key, program_id, function_name, inputs.into_iter(), &input_types, root_tvk, is_root, program_checksum, rng).unwrap();
assert!(request.verify(&input_types, is_root, program_checksum));
request
})
.collect()
Expand Down
Loading