Skip to content

Commit 85380cf

Browse files
committed
Improve deployment store API
1 parent a0f254b commit 85380cf

File tree

1 file changed

+126
-9
lines changed

1 file changed

+126
-9
lines changed

ledger/store/src/transaction/deployment.rs

Lines changed: 126 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
3939
/// The mapping of `transaction ID` to `program ID`.
4040
type IDMap: for<'a> Map<'a, N::TransactionID, ProgramID<N>>;
4141
/// The mapping of `transaction ID` to `edition`.
42-
/// Note: The `IDEditionMap` stores the non-zero editions for deployment transactions.
4342
type IDEditionMap: for<'a> Map<'a, N::TransactionID, u16>;
44-
/// The mapping of `program ID` to `edition`.
43+
/// The mapping of `program ID` to the **latest** `edition`.
4544
type EditionMap: for<'a> Map<'a, ProgramID<N>, u16>;
4645
/// The mapping of `(program ID, edition)` to `transaction ID`.
4746
type ReverseIDMap: for<'a> Map<'a, (ProgramID<N>, u16), N::TransactionID>;
@@ -200,7 +199,7 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
200199
self.id_map().insert(*transaction_id, program_id)?;
201200
// Store the edition for the transaction ID.
202201
self.id_edition_map().insert(*transaction_id, edition)?;
203-
// Store the edition for the program ID.
202+
// Store the latest edition for the program ID.
204203
self.edition_map().insert(program_id, edition)?;
205204

206205
// Store the reverse program ID.
@@ -227,19 +226,18 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
227226

228227
/// Removes the deployment transaction for the given `transaction ID`.
229228
fn remove(&self, transaction_id: &N::TransactionID) -> Result<()> {
230-
// Retrieve the program ID.
229+
// Retrieve the program ID for the transaction ID.
231230
let Some(program_id) = self.get_program_id(transaction_id)? else {
232231
bail!("Failed to get the program ID for transaction '{transaction_id}'");
233232
};
234-
// Retrieve the edition for the transaction.
233+
// Retrieve the edition for the transaction ID.
235234
let Some(edition) = self.get_edition_for_transaction(transaction_id)? else {
236235
bail!("Failed to locate the edition for transaction '{transaction_id}'");
237236
};
238-
// Retrieve the latest edition for the program.
237+
// Retrieve the latest edition for the program ID.
239238
let Some(latest_edition) = self.get_edition_for_program(&program_id)? else {
240239
bail!("Failed to locate the latest edition for program '{program_id}'");
241240
};
242-
243241
// Retrieve the program.
244242
let program = match self.program_map().get_confirmed(&(program_id, edition))? {
245243
Some(program) => cow_to_cloned!(program),
@@ -253,8 +251,8 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
253251
self.id_edition_map().remove(transaction_id)?;
254252
// Update the latest edition.
255253
match (edition, latest_edition) {
256-
// If the removed edition is 0, remove the program ID from the latest edition map.
257-
(0, _) => self.edition_map().remove(&program_id)?,
254+
// If the removed and latest edition are 0, remove the program ID from the latest edition map.
255+
(0, 0) => self.edition_map().remove(&program_id)?,
258256
// If the removed edition is the latest one, update the latest edition map by decrementing the edition.
259257
(edition, latest_edition) if edition == latest_edition => {
260258
self.edition_map().insert(program_id, edition.saturating_sub(1))?
@@ -387,6 +385,22 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
387385
}
388386
}
389387

388+
/// Returns the program for the given `program ID` and `edition`.
389+
fn get_program_with_edition(&self, program_id: &ProgramID<N>, edition: u16) -> Result<Option<Program<N>>> {
390+
// Check if the program ID is for 'credits.aleo'.
391+
// This case is handled separately, as it is a default program of the VM.
392+
// TODO (howardwu): After we update 'fee' rules and 'Ratify' in genesis, we can remove this.
393+
if program_id == &ProgramID::from_str("credits.aleo")? {
394+
return Ok(Some(Program::credits()?));
395+
}
396+
397+
// Retrieve the program.
398+
match self.program_map().get_confirmed(&(*program_id, edition))? {
399+
Some(program) => Ok(Some(cow_to_cloned!(program))),
400+
None => bail!("Failed to get program '{program_id}' (edition {edition})"),
401+
}
402+
}
403+
390404
/// Returns the latest verifying key for the given `program ID` and `function name`.
391405
fn get_verifying_key(
392406
&self,
@@ -419,6 +433,34 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
419433
}
420434
}
421435

436+
/// Returns the verifying key for the given `program ID`, `function name` and `edition`.
437+
fn get_verifying_key_with_edition(
438+
&self,
439+
program_id: &ProgramID<N>,
440+
function_name: &Identifier<N>,
441+
edition: u16,
442+
) -> Result<Option<VerifyingKey<N>>> {
443+
// Check if the program ID is for 'credits.aleo'.
444+
// This case is handled separately, as it is a default program of the VM.
445+
// TODO (howardwu): After we update 'fee' rules and 'Ratify' in genesis, we can remove this.
446+
if program_id == &ProgramID::from_str("credits.aleo")? {
447+
// Load the verifying key.
448+
let verifying_key = N::get_credits_verifying_key(function_name.to_string())?;
449+
// Retrieve the number of public and private variables.
450+
// Note: This number does *NOT* include the number of constants. This is safe because
451+
// this program is never deployed, as it is a first-class citizen of the protocol.
452+
let num_variables = verifying_key.circuit_info.num_public_and_private_variables as u64;
453+
// Return the verifying key.
454+
return Ok(Some(VerifyingKey::new(verifying_key.clone(), num_variables)));
455+
}
456+
457+
// Retrieve the verifying key.
458+
match self.verifying_key_map().get_confirmed(&(*program_id, *function_name, edition))? {
459+
Some(verifying_key) => Ok(Some(cow_to_cloned!(verifying_key))),
460+
None => bail!("Failed to get the verifying key for '{program_id}/{function_name}' (edition {edition})"),
461+
}
462+
}
463+
422464
/// Returns the latest certificate for the given `program ID` and `function name`.
423465
fn get_certificate(
424466
&self,
@@ -444,6 +486,27 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
444486
}
445487
}
446488

489+
/// Returns the certificate for the given `program ID`, `function name`, and `edition`.
490+
fn get_certificate_with_edition(
491+
&self,
492+
program_id: &ProgramID<N>,
493+
function_name: &Identifier<N>,
494+
edition: u16,
495+
) -> Result<Option<Certificate<N>>> {
496+
// Check if the program ID is for 'credits.aleo'.
497+
// This case is handled separately, as it is a default program of the VM.
498+
// TODO (howardwu): After we update 'fee' rules and 'Ratify' in genesis, we can remove this.
499+
if program_id == &ProgramID::from_str("credits.aleo")? {
500+
return Ok(None);
501+
}
502+
503+
// Retrieve the certificate.
504+
match self.certificate_map().get_confirmed(&(*program_id, *function_name, edition))? {
505+
Some(certificate) => Ok(Some(cow_to_cloned!(certificate))),
506+
None => bail!("Failed to get the certificate for '{program_id}/{function_name}' (edition {edition})"),
507+
}
508+
}
509+
447510
/// Returns the deployment for the given `transaction ID`.
448511
fn get_deployment(&self, transaction_id: &N::TransactionID) -> Result<Option<Deployment<N>>> {
449512
// Retrieve the program ID.
@@ -513,6 +576,22 @@ pub trait DeploymentStorage<N: Network>: Clone + Send + Sync {
513576
}
514577
}
515578

579+
/// Returns the owner for the given `program ID` and `edition`.
580+
fn get_owner_with_edition(&self, program_id: &ProgramID<N>, edition: u16) -> Result<Option<ProgramOwner<N>>> {
581+
// Check if the program ID is for 'credits.aleo'.
582+
// This case is handled separately, as it is a default program of the VM.
583+
// TODO (howardwu): After we update 'fee' rules and 'Ratify' in genesis, we can remove this.
584+
if program_id == &ProgramID::from_str("credits.aleo")? {
585+
return Ok(None);
586+
}
587+
588+
// Retrieve the owner.
589+
match self.owner_map().get_confirmed(&(*program_id, edition))? {
590+
Some(owner) => Ok(Some(cow_to_copied!(owner))),
591+
None => bail!("Failed to find the Owner for program '{program_id}' (edition {edition})"),
592+
}
593+
}
594+
516595
/// Returns the transaction for the given `transaction ID`.
517596
fn get_transaction(&self, transaction_id: &N::TransactionID) -> Result<Option<Transaction<N>>> {
518597
// Retrieve the deployment.
@@ -647,6 +726,11 @@ impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
647726
self.storage.get_program(program_id)
648727
}
649728

729+
/// Returns the program for the given `program ID` and `edition`.
730+
pub fn get_program_with_edition(&self, program_id: &ProgramID<N>, edition: u16) -> Result<Option<Program<N>>> {
731+
self.storage.get_program_with_edition(program_id, edition)
732+
}
733+
650734
/// Returns the latest verifying key for the given `(program ID, function name)`.
651735
pub fn get_verifying_key(
652736
&self,
@@ -656,6 +740,16 @@ impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
656740
self.storage.get_verifying_key(program_id, function_name)
657741
}
658742

743+
/// Returns the verifying key for the given `(program ID, function name, edition)`.
744+
pub fn get_verifying_key_with_edition(
745+
&self,
746+
program_id: &ProgramID<N>,
747+
function_name: &Identifier<N>,
748+
edition: u16,
749+
) -> Result<Option<VerifyingKey<N>>> {
750+
self.storage.get_verifying_key_with_edition(program_id, function_name, edition)
751+
}
752+
659753
/// Returns the latest certificate for the given `(program ID, function name)`.
660754
pub fn get_certificate(
661755
&self,
@@ -665,6 +759,16 @@ impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
665759
self.storage.get_certificate(program_id, function_name)
666760
}
667761

762+
/// Returns the certificate for the given `(program ID, function name, edition)`.
763+
pub fn get_certificate_with_edition(
764+
&self,
765+
program_id: &ProgramID<N>,
766+
function_name: &Identifier<N>,
767+
edition: u16,
768+
) -> Result<Option<Certificate<N>>> {
769+
self.storage.get_certificate_with_edition(program_id, function_name, edition)
770+
}
771+
668772
/// Returns the fee for the given `transaction ID`.
669773
pub fn get_fee(&self, transaction_id: &N::TransactionID) -> Result<Option<Fee<N>>> {
670774
self.storage.get_fee(transaction_id)
@@ -707,6 +811,7 @@ impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
707811
}
708812
}
709813

814+
type ProgramIDEdition<N> = (ProgramID<N>, u16);
710815
type ProgramTriplet<N> = (ProgramID<N>, Identifier<N>, u16);
711816

712817
impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
@@ -724,6 +829,11 @@ impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
724829
})
725830
}
726831

832+
/// Returns an iterator over the program IDs and latest editions.
833+
pub fn program_ids_and_editions(&self) -> impl '_ + Iterator<Item = (Cow<'_, ProgramID<N>>, Cow<'_, u16>)> {
834+
self.storage.edition_map().iter_confirmed()
835+
}
836+
727837
/// Returns an iterator over the programs, for all deployments.
728838
/// If a program has been updated, multiple versions of the program will be returned.
729839
pub fn programs(&self) -> impl '_ + Iterator<Item = Cow<'_, Program<N>>> {
@@ -733,6 +843,13 @@ impl<N: Network, D: DeploymentStorage<N>> DeploymentStore<N, D> {
733843
})
734844
}
735845

846+
/// Returns an iterator over the programs and editions, for all deployments.
847+
pub fn programs_and_editions(
848+
&self,
849+
) -> impl '_ + Iterator<Item = (Cow<'_, ProgramIDEdition<N>>, Cow<'_, Program<N>>)> {
850+
self.storage.program_map().iter_confirmed()
851+
}
852+
736853
/// Returns an iterator over the `((program ID, function name, edition), verifying key)`, for all deployments.
737854
pub fn verifying_keys(&self) -> impl '_ + Iterator<Item = (Cow<'_, ProgramTriplet<N>>, Cow<'_, VerifyingKey<N>>)> {
738855
self.storage.verifying_key_map().iter_confirmed()

0 commit comments

Comments
 (0)