Skip to content

Commit

Permalink
Track num_variables for each function in a Deployment to prevent goin…
Browse files Browse the repository at this point in the history
…g over those limits

Lower MAX_DEPLOYMENT_VARIABLES
Initialize circuit gadget constants before synthesis
Update test expectation
  • Loading branch information
vicsn committed Apr 12, 2024
1 parent 07ac80c commit d2f8d1e
Show file tree
Hide file tree
Showing 20 changed files with 255 additions and 59 deletions.
3 changes: 3 additions & 0 deletions circuit/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub trait Aleo: Environment {
/// The maximum number of field elements in data (must not exceed u16::MAX).
const MAX_DATA_SIZE_IN_FIELDS: u32 = <Self::Network as console::Network>::MAX_DATA_SIZE_IN_FIELDS;

/// Initializes all of the constants for the Aleo environment.
fn init_constants();

/// Returns the encryption domain as a constant field element.
fn encryption_domain() -> Field<Self>;

Expand Down
23 changes: 23 additions & 0 deletions circuit/network/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,29 @@ thread_local! {
pub struct AleoV0;

impl Aleo for AleoV0 {
/// Initializes all of the constants for the Aleo environment.
fn init_constants() {
GENERATOR_G.with(|_| ());
ENCRYPTION_DOMAIN.with(|_| ());
GRAPH_KEY_DOMAIN.with(|_| ());
SERIAL_NUMBER_DOMAIN.with(|_| ());
BHP_256.with(|_| ());
BHP_512.with(|_| ());
BHP_768.with(|_| ());
BHP_1024.with(|_| ());
KECCAK_256.with(|_| ());
KECCAK_384.with(|_| ());
KECCAK_512.with(|_| ());
PEDERSEN_64.with(|_| ());
PEDERSEN_128.with(|_| ());
POSEIDON_2.with(|_| ());
POSEIDON_4.with(|_| ());
POSEIDON_8.with(|_| ());
SHA3_256.with(|_| ());
SHA3_384.with(|_| ());
SHA3_512.with(|_| ());
}

/// Returns the encryption domain as a constant field element.
fn encryption_domain() -> Field<Self> {
ENCRYPTION_DOMAIN.with(|domain| domain.clone())
Expand Down
2 changes: 1 addition & 1 deletion console/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub trait Network:
/// The maximum number of constraints in a deployment.
const MAX_DEPLOYMENT_CONSTRAINTS: u64 = 1 << 20; // 1,048,576 constraints
/// The maximum number of variables in a deployment.
const MAX_DEPLOYMENT_VARIABLES: u64 = 1 << 22; // 4,194,304 variables
const MAX_DEPLOYMENT_VARIABLES: u64 = 1 << 20; // 1,048,576 variables
/// The maximum number of microcredits that can be spent as a fee.
const MAX_FEE: u64 = 1_000_000_000_000_000;
/// The maximum number of microcredits that can be spent on a finalize block.
Expand Down
16 changes: 10 additions & 6 deletions ledger/block/src/transaction/deployment/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,23 @@ impl<N: Network> FromBytes for Deployment<N> {

// Read the number of entries in the bundle.
let num_entries = u16::read_le(&mut reader)?;
// Read the verifying keys.
let mut verifying_keys = Vec::with_capacity(num_entries as usize);
// Read the function specifications.
let mut function_specs = Vec::with_capacity(num_entries as usize);
for _ in 0..num_entries {
// Read the identifier.
let identifier = Identifier::<N>::read_le(&mut reader)?;
// Read the verifying key.
let verifying_key = VerifyingKey::<N>::read_le(&mut reader)?;
// Read the certificate.
let certificate = Certificate::<N>::read_le(&mut reader)?;
// Read the variable count.
let variable_count = u64::read_le(&mut reader)?;
// Add the entry.
verifying_keys.push((identifier, (verifying_key, certificate)));
function_specs.push((identifier, (verifying_key, certificate, variable_count)));
}

// Return the deployment.
Self::new(edition, program, verifying_keys).map_err(|err| error(format!("{err}")))
Self::new(edition, program, function_specs).map_err(|err| error(format!("{err}")))
}
}

Expand All @@ -59,15 +61,17 @@ impl<N: Network> ToBytes for Deployment<N> {
// Write the program.
self.program.write_le(&mut writer)?;
// Write the number of entries in the bundle.
(u16::try_from(self.verifying_keys.len()).map_err(|e| error(e.to_string()))?).write_le(&mut writer)?;
(u16::try_from(self.function_specs.len()).map_err(|e| error(e.to_string()))?).write_le(&mut writer)?;
// Write each entry.
for (function_name, (verifying_key, certificate)) in &self.verifying_keys {
for (function_name, (verifying_key, certificate, variable_count)) in &self.function_specs {
// Write the function name.
function_name.write_le(&mut writer)?;
// Write the verifying key.
verifying_key.write_le(&mut writer)?;
// Write the certificate.
certificate.write_le(&mut writer)?;
// Write the variable count.
variable_count.write_le(&mut writer)?;
}
Ok(())
}
Expand Down
49 changes: 34 additions & 15 deletions ledger/block/src/transaction/deployment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,27 @@ use console::{
use synthesizer_program::Program;
use synthesizer_snark::{Certificate, VerifyingKey};

/// The verification key, certificate, and number of variables for a function.
type FunctionSpec<N> = (VerifyingKey<N>, Certificate<N>, u64);

#[derive(Clone, PartialEq, Eq)]
pub struct Deployment<N: Network> {
/// The edition.
edition: u16,
/// The program.
program: Program<N>,
/// The mapping of function names to their verifying key and certificate.
verifying_keys: Vec<(Identifier<N>, (VerifyingKey<N>, Certificate<N>))>,
/// The mapping of function names to their specification.
function_specs: Vec<(Identifier<N>, FunctionSpec<N>)>,
}

impl<N: Network> Deployment<N> {
/// Initializes a new deployment.
pub fn new(
edition: u16,
program: Program<N>,
verifying_keys: Vec<(Identifier<N>, (VerifyingKey<N>, Certificate<N>))>,
function_specs: Vec<(Identifier<N>, FunctionSpec<N>)>,
) -> Result<Self> {
// Construct the deployment.
let deployment = Self { edition, program, verifying_keys };
let deployment = Self { edition, program, function_specs };
// Ensure the deployment is ordered.
deployment.check_is_ordered()?;
// Return the deployment.
Expand All @@ -70,17 +72,17 @@ impl<N: Network> Deployment<N> {
);
// Ensure the deployment contains verifying keys.
ensure!(
!self.verifying_keys.is_empty(),
!self.function_specs.is_empty(),
"No verifying keys present in the deployment for program '{program_id}'"
);

// Ensure the number of functions matches the number of verifying keys.
if self.program.functions().len() != self.verifying_keys.len() {
// Ensure the number of functions matches the number of function specifications.
if self.program.functions().len() != self.function_specs.len() {
bail!("Deployment has an incorrect number of verifying keys, according to the program.");
}

// Ensure the function and verifying keys correspond.
for ((function_name, function), (name, _)) in self.program.functions().iter().zip_eq(&self.verifying_keys) {
// Ensure the function and specs correspond.
for ((function_name, function), (name, _)) in self.program.functions().iter().zip_eq(&self.function_specs) {
// Ensure the function name is correct.
if function_name != function.name() {
bail!("The function key is '{function_name}', but the function name is '{}'", function.name())
Expand All @@ -92,7 +94,7 @@ impl<N: Network> Deployment<N> {
}

ensure!(
!has_duplicates(self.verifying_keys.iter().map(|(name, ..)| name)),
!has_duplicates(self.function_specs.iter().map(|(name, ..)| name)),
"A duplicate function name was found"
);

Expand All @@ -119,17 +121,17 @@ impl<N: Network> Deployment<N> {
self.program.id()
}

/// Returns the verifying keys.
pub const fn verifying_keys(&self) -> &Vec<(Identifier<N>, (VerifyingKey<N>, Certificate<N>))> {
&self.verifying_keys
/// Returns the function specifications.
pub const fn verifying_keys(&self) -> &Vec<(Identifier<N>, FunctionSpec<N>)> {
&self.function_specs
}

/// Returns the sum of the constraint counts for all functions in this deployment.
pub fn num_combined_constraints(&self) -> Result<u64> {
// Initialize the accumulator.
let mut num_combined_constraints = 0u64;
// Iterate over the functions.
for (_, (vk, _)) in &self.verifying_keys {
for (_, (vk, _, _)) in &self.function_specs {
// Add the number of constraints.
// Note: This method must be *checked* because the claimed constraint count
// is from the user, not the synthesizer.
Expand All @@ -141,6 +143,23 @@ impl<N: Network> Deployment<N> {
Ok(num_combined_constraints)
}

/// Returns the sum of the variable counts for all functions in this deployment.
pub fn num_combined_variables(&self) -> Result<u64> {
// Initialize the accumulator.
let mut num_combined_variables = 0u64;
// Iterate over the functions.
for (_, (_, _, variable_count)) in &self.function_specs {
// Add the number of variables.
// Note: This method must be *checked* because the claimed variable count
// is from the user, not the synthesizer.
num_combined_variables = num_combined_variables
.checked_add(*variable_count)
.ok_or_else(|| anyhow!("Overflow when counting variables for '{}'", self.program_id()))?;
}
// Return the number of combined constraints.
Ok(num_combined_variables)
}

/// Returns the deployment ID.
pub fn to_deployment_id(&self) -> Result<Field<N>> {
Ok(*Transaction::deployment_tree(self, None)?.root())
Expand Down
4 changes: 2 additions & 2 deletions ledger/block/src/transaction/deployment/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<N: Network> Serialize for Deployment<N> {
let mut deployment = serializer.serialize_struct("Deployment", 3)?;
deployment.serialize_field("edition", &self.edition)?;
deployment.serialize_field("program", &self.program)?;
deployment.serialize_field("verifying_keys", &self.verifying_keys)?;
deployment.serialize_field("function_specs", &self.function_specs)?;
deployment.end()
}
false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
Expand All @@ -45,7 +45,7 @@ impl<'de, N: Network> Deserialize<'de> for Deployment<N> {
// Retrieve the program.
DeserializeExt::take_from_value::<D>(&mut deployment, "program")?,
// Retrieve the verifying keys.
DeserializeExt::take_from_value::<D>(&mut deployment, "verifying_keys")?,
DeserializeExt::take_from_value::<D>(&mut deployment, "function_specs")?,
)
.map_err(de::Error::custom)?;

Expand Down
9 changes: 9 additions & 0 deletions ledger/store/src/helpers/memory/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub struct DeploymentMemory<N: Network> {
verifying_key_map: MemoryMap<(ProgramID<N>, Identifier<N>, u16), VerifyingKey<N>>,
/// The certificate map.
certificate_map: MemoryMap<(ProgramID<N>, Identifier<N>, u16), Certificate<N>>,
/// The variable count map.
variable_count_map: MemoryMap<(ProgramID<N>, Identifier<N>, u16), u64>,
/// The fee store.
fee_store: FeeStore<N, FeeMemory<N>>,
}
Expand All @@ -116,6 +118,7 @@ impl<N: Network> DeploymentStorage<N> for DeploymentMemory<N> {
type ProgramMap = MemoryMap<(ProgramID<N>, u16), Program<N>>;
type VerifyingKeyMap = MemoryMap<(ProgramID<N>, Identifier<N>, u16), VerifyingKey<N>>;
type CertificateMap = MemoryMap<(ProgramID<N>, Identifier<N>, u16), Certificate<N>>;
type VariableCountMap = MemoryMap<(ProgramID<N>, Identifier<N>, u16), u64>;
type FeeStorage = FeeMemory<N>;

/// Initializes the deployment storage.
Expand All @@ -128,6 +131,7 @@ impl<N: Network> DeploymentStorage<N> for DeploymentMemory<N> {
program_map: MemoryMap::default(),
verifying_key_map: MemoryMap::default(),
certificate_map: MemoryMap::default(),
variable_count_map: MemoryMap::default(),
fee_store,
})
}
Expand Down Expand Up @@ -167,6 +171,11 @@ impl<N: Network> DeploymentStorage<N> for DeploymentMemory<N> {
&self.certificate_map
}

/// Returns the variable count map.
fn variable_count_map(&self) -> &Self::VariableCountMap {
&self.variable_count_map
}

/// Returns the fee store.
fn fee_store(&self) -> &FeeStore<N, Self::FeeStorage> {
&self.fee_store
Expand Down
2 changes: 2 additions & 0 deletions ledger/store/src/helpers/rocksdb/internal/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub enum DeploymentMap {
Program = DataID::DeploymentProgramMap as u16,
VerifyingKey = DataID::DeploymentVerifyingKeyMap as u16,
Certificate = DataID::DeploymentCertificateMap as u16,
VariableCount = DataID::DeploymentVariableCountMap as u16,
}

/// The RocksDB map prefix for execution-related entries.
Expand Down Expand Up @@ -252,6 +253,7 @@ enum DataID {
DeploymentProgramMap,
DeploymentVerifyingKeyMap,
DeploymentCertificateMap,
DeploymentVariableCountMap,
// Execution
ExecutionIDMap,
ExecutionReverseIDMap,
Expand Down
9 changes: 9 additions & 0 deletions ledger/store/src/helpers/rocksdb/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ pub struct DeploymentDB<N: Network> {
verifying_key_map: DataMap<(ProgramID<N>, Identifier<N>, u16), VerifyingKey<N>>,
/// The certificate map.
certificate_map: DataMap<(ProgramID<N>, Identifier<N>, u16), Certificate<N>>,
/// The variable count map.
variable_count_map: DataMap<(ProgramID<N>, Identifier<N>, u16), u64>,
/// The fee store.
fee_store: FeeStore<N, FeeDB<N>>,
}
Expand All @@ -126,6 +128,7 @@ impl<N: Network> DeploymentStorage<N> for DeploymentDB<N> {
type ProgramMap = DataMap<(ProgramID<N>, u16), Program<N>>;
type VerifyingKeyMap = DataMap<(ProgramID<N>, Identifier<N>, u16), VerifyingKey<N>>;
type CertificateMap = DataMap<(ProgramID<N>, Identifier<N>, u16), Certificate<N>>;
type VariableCountMap = DataMap<(ProgramID<N>, Identifier<N>, u16), u64>;
type FeeStorage = FeeDB<N>;

/// Initializes the deployment storage.
Expand All @@ -140,6 +143,7 @@ impl<N: Network> DeploymentStorage<N> for DeploymentDB<N> {
program_map: rocksdb::RocksDB::open_map(N::ID, storage_mode.clone(), MapID::Deployment(DeploymentMap::Program))?,
verifying_key_map: rocksdb::RocksDB::open_map(N::ID, storage_mode.clone(), MapID::Deployment(DeploymentMap::VerifyingKey))?,
certificate_map: rocksdb::RocksDB::open_map(N::ID, storage_mode.clone(), MapID::Deployment(DeploymentMap::Certificate))?,
variable_count_map: rocksdb::RocksDB::open_map(N::ID, storage_mode.clone(), MapID::Deployment(DeploymentMap::VariableCount))?,
fee_store,
})
}
Expand Down Expand Up @@ -179,6 +183,11 @@ impl<N: Network> DeploymentStorage<N> for DeploymentDB<N> {
&self.certificate_map
}

/// Returns the variable count map.
fn variable_count_map(&self) -> &Self::VariableCountMap {
&self.variable_count_map
}

/// Returns the fee store.
fn fee_store(&self) -> &FeeStore<N, Self::FeeStorage> {
&self.fee_store
Expand Down
30 changes: 23 additions & 7 deletions ledger/store/src/transaction/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
type VerifyingKeyMap: for<'a> Map<'a, (ProgramID<N>, Identifier<N>, u16), VerifyingKey<N>>;
/// The mapping of `(program ID, function name, edition)` to `certificate`.
type CertificateMap: for<'a> Map<'a, (ProgramID<N>, Identifier<N>, u16), Certificate<N>>;
/// The mapping of `(program ID, function name, edition)` to `variable count`.
type VariableCountMap: for<'a> Map<'a, (ProgramID<N>, Identifier<N>, u16), u64>;
/// The fee storage.
type FeeStorage: FeeStorage<N>;

Expand All @@ -69,6 +71,8 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
fn verifying_key_map(&self) -> &Self::VerifyingKeyMap;
/// Returns the certificate map.
fn certificate_map(&self) -> &Self::CertificateMap;
/// Returns the variable count map.
fn variable_count_map(&self) -> &Self::VariableCountMap;
/// Returns the fee storage.
fn fee_store(&self) -> &FeeStore<N, Self::FeeStorage>;

Expand Down Expand Up @@ -196,11 +200,13 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
self.program_map().insert((program_id, edition), program.clone())?;

// Store the verifying keys and certificates.
for (function_name, (verifying_key, certificate)) in deployment.verifying_keys() {
for (function_name, (verifying_key, certificate, variable_count)) in deployment.verifying_keys() {
// Store the verifying key.
self.verifying_key_map().insert((program_id, *function_name, edition), verifying_key.clone())?;
// Store the certificate.
self.certificate_map().insert((program_id, *function_name, edition), certificate.clone())?;
// Store the variable count.
self.variable_count_map().insert((program_id, *function_name, edition), *variable_count)?;
}

// Store the fee transition.
Expand Down Expand Up @@ -400,27 +406,37 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
None => bail!("Failed to get the deployed program '{program_id}' (edition {edition})"),
};

// Initialize a vector for the verifying keys and certificates.
let mut verifying_keys = Vec::with_capacity(program.functions().len());
// Initialize a vector for the function_specs.
let mut function_specs = Vec::with_capacity(program.functions().len());

// Retrieve the verifying keys and certificates.
for function_name in program.functions().keys() {
// Retrieve the verifying key.
let verifying_key = match self.verifying_key_map().get_confirmed(&(program_id, *function_name, edition))? {
Some(verifying_key) => cow_to_cloned!(verifying_key),
None => bail!("Failed to get the verifying key for '{program_id}/{function_name}' (edition {edition})"),
None => {
bail!("Failed to get the verifying key for '{program_id}/{function_name}' (edition {edition})")
}
};
// Retrieve the certificate.
let certificate = match self.certificate_map().get_confirmed(&(program_id, *function_name, edition))? {
Some(certificate) => cow_to_cloned!(certificate),
None => bail!("Failed to get the certificate for '{program_id}/{function_name}' (edition {edition})"),
};
// Add the verifying key and certificate to the deployment.
verifying_keys.push((*function_name, (verifying_key, certificate)));
// Retrieve the variable count.
let variable_count =
match self.variable_count_map().get_confirmed(&(program_id, *function_name, edition))? {
Some(variable_count) => cow_to_cloned!(variable_count),
None => {
bail!("Failed to get the variable count for '{program_id}/{function_name}' (edition {edition})")
}
};
// Add the verifying key, certificate and variable_count to the deployment.
function_specs.push((*function_name, (verifying_key, certificate, variable_count)));
}

// Return the deployment.
Ok(Some(Deployment::new(edition, program, verifying_keys)?))
Ok(Some(Deployment::new(edition, program, function_specs)?))
}

/// Returns the fee for the given `transaction ID`.
Expand Down
Loading

0 comments on commit d2f8d1e

Please sign in to comment.