diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7894709d..796964a3b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Added
### Changed
+- [\#282](https://github.com/Manta-Network/manta-rs/pull/282) Upgrade key system.
### Deprecated
diff --git a/manta-accounting/src/key.rs b/manta-accounting/src/key.rs
index 858dbf3d8..03f878fd5 100644
--- a/manta-accounting/src/key.rs
+++ b/manta-accounting/src/key.rs
@@ -14,34 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with manta-rs. If not, see .
-//! Hierarchical Key Derivation Schemes
-//!
-//! This module defines a Hierarchical Key Derivation Scheme similar to the one defined in the
-//! [`BIP-0044`] specification.
-//!
-//! [`BIP-0044`]: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
+//! Key Accounting
use alloc::vec::Vec;
use core::{
- cmp,
fmt::{self, Debug},
hash::Hash,
- iter,
marker::PhantomData,
};
-use manta_crypto::{
- key::kdf::KeyDerivationFunction,
- rand::{RngCore, Sample},
-};
-use manta_util::collections::btree_map::{self, BTreeMap};
#[cfg(feature = "serde")]
use manta_util::serde::{Deserialize, Serialize};
-/// Hierarchical Key Derivation Parameter Type
+/// Base Index Type
pub type IndexType = u32;
-/// Hierarchical Key Derivation Parameter
+/// Index
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
@@ -49,7 +37,7 @@ pub type IndexType = u32;
)]
#[derive(derivative::Derivative)]
#[derivative(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct HierarchicalKeyDerivationParameter {
+pub struct Index {
/// Index
index: IndexType,
@@ -57,8 +45,8 @@ pub struct HierarchicalKeyDerivationParameter {
__: PhantomData,
}
-impl HierarchicalKeyDerivationParameter {
- /// Builds a new [`HierarchicalKeyDerivationParameter`] from `index`.
+impl Index {
+ /// Builds a new [`Index`] from `index`.
#[inline]
pub const fn new(index: IndexType) -> Self {
Self {
@@ -69,7 +57,7 @@ impl HierarchicalKeyDerivationParameter {
/// Increments the index of `self` by one unit.
#[inline]
- fn increment(&mut self) {
+ pub fn increment(&mut self) {
self.index += 1;
}
@@ -80,7 +68,7 @@ impl HierarchicalKeyDerivationParameter {
}
}
-/// Implements the [`HierarchicalKeyDerivationParameter`] subtype for `$type` and `$index`.
+/// Implements the [`Index`] subtype for `$type` and `$index`.
macro_rules! impl_index_type {
($doc:expr, $fmt:expr, $type:ident, $index:ident) => {
#[doc = $doc]
@@ -89,7 +77,7 @@ macro_rules! impl_index_type {
pub struct $type;
#[doc = $doc]
- pub type $index = HierarchicalKeyDerivationParameter<$type>;
+ pub type $index = Index<$type>;
impl Debug for $index {
#[inline]
@@ -97,6 +85,20 @@ macro_rules! impl_index_type {
f.debug_tuple($fmt).field(&self.index).finish()
}
}
+
+ impl From for $index {
+ #[inline]
+ fn from(index: IndexType) -> Self {
+ Self::new(index)
+ }
+ }
+
+ impl From<$index> for IndexType {
+ #[inline]
+ fn from(index: $index) -> Self {
+ index.index()
+ }
+ }
};
}
@@ -107,679 +109,202 @@ impl_index_type!(
AccountIndex
);
-impl_index_type!("Key Index", "KeyIndex", KeyIndexType, KeyIndex);
-
-/// Key Kind
-#[cfg_attr(
- feature = "serde",
- derive(Deserialize, Serialize),
- serde(crate = "manta_util::serde", deny_unknown_fields)
-)]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum Kind {
- /// Spend Key
- Spend,
-
- /// View Key
- View,
-}
-
-/// Hierarchical Key Derivation Scheme
-pub trait HierarchicalKeyDerivationScheme {
- /// [`KeyIndex`] Gap Limit
- const GAP_LIMIT: IndexType;
-
- /// Secret Key Type
- type SecretKey;
-
- /// Derives a secret key for `account` with `kind` and `index`.
- fn derive(&self, account: AccountIndex, kind: Kind, index: KeyIndex) -> Self::SecretKey;
-
- /// Derives a spend secret key for `account` using the spend `index`.
- #[inline]
- fn derive_spend(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey {
- self.derive(account, Kind::Spend, index)
- }
-
- /// Derives a view secret key for `account` using the view `index`.
- #[inline]
- fn derive_view(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey {
- self.derive(account, Kind::View, index)
- }
+/// Account Collection
+pub trait AccountCollection {
+ /// Spending Key Type
+ type SpendingKey;
- /// Derives a spend-view pair of secret keys for `account` and `index`.
- #[inline]
- fn derive_pair(&self, account: AccountIndex, index: KeyIndex) -> SecretKeyPair {
- SecretKeyPair::new(
- self.derive_spend(account, index),
- self.derive_view(account, index),
- )
- }
-
- /// Borrows `self` rather than consuming it, returning an implementation of
- /// [`HierarchicalKeyDerivationScheme`].
- #[inline]
- fn by_ref(&self) -> &Self {
- self
- }
-
- /// Maps `self` along a key derivation function.
- #[inline]
- fn map(self, key_derivation_function: F) -> Map
- where
- Self: Sized,
- F: KeyDerivationFunction,
- {
- Map::new(self, key_derivation_function)
- }
+ /// Returns the [`SpendingKey`] corresponding to `index`.
+ fn spending_key(&self, index: &AccountIndex) -> Self::SpendingKey;
}
-impl HierarchicalKeyDerivationScheme for &H
+impl AccountCollection for &A
where
- H: HierarchicalKeyDerivationScheme + ?Sized,
+ A: AccountCollection,
{
- const GAP_LIMIT: IndexType = H::GAP_LIMIT;
-
- type SecretKey = H::SecretKey;
+ type SpendingKey = A::SpendingKey;
#[inline]
- fn derive(&self, account: AccountIndex, kind: Kind, index: KeyIndex) -> Self::SecretKey {
- (*self).derive(account, kind, index)
- }
-
- #[inline]
- fn derive_spend(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey {
- (*self).derive_spend(account, index)
- }
-
- #[inline]
- fn derive_view(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey {
- (*self).derive_view(account, index)
+ fn spending_key(&self, index: &AccountIndex) -> Self::SpendingKey {
+ (**self).spending_key(index)
}
}
-/// Mapping Hierarchical Key Derivation Scheme
-#[cfg_attr(
- feature = "serde",
- derive(Deserialize, Serialize),
- serde(crate = "manta_util::serde", deny_unknown_fields)
-)]
-#[derive(derivative::Derivative)]
-#[derivative(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
-pub struct Map
-where
- H: HierarchicalKeyDerivationScheme,
- F: KeyDerivationFunction,
-{
- /// Base Derivation Scheme
- base: H,
+/// Spending Key Type
+pub type SpendingKey = ::SpendingKey;
- /// Key Derivation Function
- key_derivation_function: F,
-}
-
-impl Map
-where
- H: HierarchicalKeyDerivationScheme,
- F: KeyDerivationFunction,
-{
- /// Builds a new [`Map`] from `base` and `key_derivation_function`.
- #[inline]
- pub fn new(base: H, key_derivation_function: F) -> Self {
- Self {
- base,
- key_derivation_function,
- }
- }
+/// Account Map
+pub trait AccountMap {
+ /// Account Type
+ type Account;
- /// Returns the base [`HierarchicalKeyDerivationScheme`] for `self`.
- #[inline]
- pub fn base(&self) -> &H {
- &self.base
- }
-}
+ /// Builds a new [`AccountMap`] with a starting account.
+ fn new() -> Self;
-impl HierarchicalKeyDerivationScheme for Map
-where
- H: HierarchicalKeyDerivationScheme,
- F: KeyDerivationFunction,
-{
- const GAP_LIMIT: IndexType = H::GAP_LIMIT;
+ /// Returns the last account index stored in the map.
+ fn last_account(&self) -> AccountIndex;
- type SecretKey = F::Output;
+ /// Adds a new account to the map, returning the new account index.
+ fn create_account(&mut self) -> AccountIndex;
- #[inline]
- fn derive(&self, account: AccountIndex, kind: Kind, index: KeyIndex) -> Self::SecretKey {
- self.key_derivation_function
- .derive(&self.base.derive(account, kind, index), &mut ())
- }
+ /// Returns a shared reference to the [`Account`](Self::Account) associated to `account`.
+ fn get(&self, account: AccountIndex) -> Option<&Self::Account>;
+ /// Returns a shared referece to the default [`Account`](Self::Account) for this map.
#[inline]
- fn derive_spend(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey {
- self.key_derivation_function
- .derive(&self.base.derive_spend(account, index), &mut ())
+ fn get_default(&self) -> &Self::Account {
+ self.get(Default::default())
+ .expect("The default account must always exist.")
}
- #[inline]
- fn derive_view(&self, account: AccountIndex, index: KeyIndex) -> Self::SecretKey {
- self.key_derivation_function
- .derive(&self.base.derive_view(account, index), &mut ())
- }
-}
+ /// Returns a mutable reference to the [`Account`](Self::Account) associated to `account`.
+ fn get_mut(&mut self, account: AccountIndex) -> Option<&mut Self::Account>;
-impl Sample<(D, F)> for Map
-where
- H: HierarchicalKeyDerivationScheme + Sample,
- F: KeyDerivationFunction,
-{
+ /// Returns a mutable reference to the default [`Account`](Self::Account) for this map.
#[inline]
- fn sample(distribution: (D, F), rng: &mut R) -> Self
- where
- R: RngCore + ?Sized,
- {
- Self::new(H::sample(distribution.0, rng), distribution.1)
+ fn get_mut_default(&mut self) -> &mut Self::Account {
+ self.get_mut(Default::default())
+ .expect("The default account must always exist.")
}
}
-/// Hierarchical Key Derivation Secret Key Pair
-pub struct SecretKeyPair
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Spend Part of the Key Pair
- pub spend: H::SecretKey,
-
- /// View Part of the Key Pair
- pub view: H::SecretKey,
-}
-
-impl SecretKeyPair
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Builds a new [`SecretKeyPair`] from `spend` and `view`.
- #[inline]
- pub fn new(spend: H::SecretKey, view: H::SecretKey) -> Self {
- Self { spend, view }
- }
-}
-
-/// Account Keys
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Debug(bound = "H: Debug"),
- Eq(bound = "H: Eq"),
- Hash(bound = "H: Hash"),
- PartialEq(bound = "H: PartialEq")
-)]
-pub struct AccountKeys<'h, H>
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Hierarchical Key Derivation Scheme
- keys: &'h H,
-
- /// Account Index
- index: AccountIndex,
-
- /// Account Information
- account: Account,
-}
+/// [`Vec`] Account Map Type
+pub type VecAccountMap = Vec;
-impl<'h, H> AccountKeys<'h, H>
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Builds a new [`AccountKeys`] from `keys`, `index`, and `account`.
- #[inline]
- fn new(keys: &'h H, index: AccountIndex, account: Account) -> Self {
- Self {
- keys,
- index,
- account,
- }
- }
+impl AccountMap for VecAccountMap {
+ type Account = AccountIndex;
- /// Performs the bounds check on `index` and then runs `f`.
#[inline]
- fn with_bounds_check(&self, index: KeyIndex, f: F) -> Option
- where
- F: FnOnce(&Self, KeyIndex) -> T,
- {
- (index <= self.account.maximum_index).then(|| f(self, index))
+ fn new() -> Self {
+ let mut this = Self::new();
+ this.create_account();
+ this
}
- /// Derives the spend key for this account at `index` without performing bounds checks.
#[inline]
- fn derive_spend(&self, index: KeyIndex) -> H::SecretKey {
- self.keys.derive_spend(self.index, index)
+ fn last_account(&self) -> AccountIndex {
+ AccountIndex::new(
+ (self.len() - 1)
+ .try_into()
+ .expect("AccountIndex is not allowed to exceed IndexType::MAX."),
+ )
}
- /// Returns the default spend key for this account.
#[inline]
- pub fn default_spend_key(&self) -> H::SecretKey {
- self.derive_spend(Default::default())
+ fn create_account(&mut self) -> AccountIndex {
+ let index = AccountIndex::new(
+ self.len()
+ .try_into()
+ .expect("AccountIndex is not allowed to exceed IndexType::MAX."),
+ );
+ self.push(Default::default());
+ index
}
- /// Returns the spend key for this account at `index`, if it does not exceed the maximum index.
#[inline]
- pub fn spend_key(&self, index: KeyIndex) -> Option {
- self.with_bounds_check(index, Self::derive_spend)
+ fn get(&self, account: AccountIndex) -> Option<&Self::Account> {
+ self.as_slice().get(account.index() as usize)
}
- /// Derives the view key for this account at `index` without performing bounds checks.
#[inline]
- fn derive_view(&self, index: KeyIndex) -> H::SecretKey {
- self.keys.derive_view(self.index, index)
+ fn get_mut(&mut self, account: AccountIndex) -> Option<&mut Self::Account> {
+ self.as_mut_slice().get_mut(account.index() as usize)
}
+}
- /// Returns the default view key for this account.
- #[inline]
- pub fn default_view_key(&self) -> H::SecretKey {
- self.derive_view(Default::default())
- }
+/// Derive Address Trait
+pub trait DeriveAddress {
+ /// Address Generation Parameters
+ type Parameters;
- /// Returns the view key for this account at `index`, if it does not exceed the maximum index.
- #[inline]
- pub fn view_key(&self, index: KeyIndex) -> Option {
- self.with_bounds_check(index, Self::derive_view)
- }
+ /// Address Type
+ type Address;
- /// Derives the secret key pair for this account at `index` without performing bounds checks.
- #[inline]
- fn derive_pair(&self, index: KeyIndex) -> SecretKeyPair {
- self.keys.derive_pair(self.index, index)
- }
+ /// Returns the [`Address`](Self::Address) corresponding to `self`.
+ fn address(&self, parameters: &Self::Parameters) -> Self::Address;
+}
- /// Returns the default secret key pair for this account.
- #[inline]
- pub fn default_keypair(&self) -> SecretKeyPair {
- self.derive_pair(Default::default())
- }
+/// Derive Addresses Trait
+pub trait DeriveAddresses {
+ /// Address Generation Parameters
+ type Parameters;
- /// Returns the key pair for this account at the `spend` and `view` indices, if those indices
- /// do not exceed the maximum indices.
- #[inline]
- pub fn keypair(&self, index: KeyIndex) -> Option> {
- self.with_bounds_check(index, Self::derive_pair)
- }
+ /// Address Type
+ type Address;
- /// Returns an iterator over all the key pairs associated to `self`.
- #[inline]
- pub fn keypairs(&self) -> impl '_ + Iterator- > {
- let mut index = KeyIndex::default();
- iter::from_fn(move || {
- let next = self.keypair(index);
- index.increment();
- next
- })
- }
+ /// Returns the [`Address`](Self::Address) corresponding to `index`.
+ fn address(&self, parameters: &Self::Parameters, index: AccountIndex) -> Self::Address;
}
-/// Account Keys with Mutable Access to the Account Table
+/// Account
+#[cfg_attr(
+ feature = "serde",
+ derive(Deserialize, Serialize),
+ serde(
+ bound(deserialize = "H: Deserialize<'de>", serialize = "H: Serialize",),
+ crate = "manta_util::serde",
+ deny_unknown_fields
+ )
+)]
#[derive(derivative::Derivative)]
#[derivative(
+ Clone(bound = "H: Clone"),
+ Copy(bound = "H: Copy"),
Debug(bound = "H: Debug"),
Eq(bound = "H: Eq"),
Hash(bound = "H: Hash"),
PartialEq(bound = "H: PartialEq")
)]
-pub struct AccountKeysMut<'h, H>
+pub struct Account
where
- H: HierarchicalKeyDerivationScheme + ?Sized,
+ H: AccountCollection,
{
- /// Hierarchical Key Derivation Scheme
- keys: &'h H,
+ /// Account Collection
+ key: H,
- /// Account Index
+ /// Index
index: AccountIndex,
-
- /// Account Information
- account: &'h mut Account,
-}
-
-impl<'h, H> AccountKeysMut<'h, H>
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Builds a new [`AccountKeysMut`] from `keys`, `index`, and `account`.
- #[inline]
- fn new(keys: &'h H, index: AccountIndex, account: &'h mut Account) -> Self {
- Self {
- keys,
- index,
- account,
- }
- }
-
- /// Performs the bounds check on `index` and then runs `f`.
- #[inline]
- fn with_bounds_check(&self, index: KeyIndex, f: F) -> Option
- where
- F: FnOnce(&Self, KeyIndex) -> T,
- {
- (index <= self.account.maximum_index).then(|| f(self, index))
- }
-
- /// Derives the spend key for this account at `index` without performing bounds checks.
- #[inline]
- fn derive_spend(&self, index: KeyIndex) -> H::SecretKey {
- self.keys.derive_spend(self.index, index)
- }
-
- /// Returns the default spend key for this account.
- #[inline]
- pub fn default_spend_key(&self) -> H::SecretKey {
- self.derive_spend(Default::default())
- }
-
- /// Returns the spend key for this account at `index`, if it does not exceed the maximum index.
- #[inline]
- pub fn spend_key(&self, index: KeyIndex) -> Option {
- self.with_bounds_check(index, Self::derive_spend)
- }
-
- /// Derives the view key for this account at `index` without performing bounds checks.
- #[inline]
- fn derive_view(&self, index: KeyIndex) -> H::SecretKey {
- self.keys.derive_view(self.index, index)
- }
-
- /// Returns the default view key for this account.
- #[inline]
- pub fn default_view_key(&self) -> H::SecretKey {
- self.derive_view(Default::default())
- }
-
- /// Returns the view key for this account at `index`, if it does not exceed the maximum index.
- #[inline]
- pub fn view_key(&self, index: KeyIndex) -> Option {
- self.with_bounds_check(index, Self::derive_view)
- }
-
- /// Derives the secret key pair for this account at `index` without performing bounds checks.
- #[inline]
- fn derive_pair(&self, index: KeyIndex) -> SecretKeyPair {
- self.keys.derive_pair(self.index, index)
- }
-
- /// Returns the default secret key pair for this account.
- #[inline]
- pub fn default_keypair(&self) -> SecretKeyPair {
- self.derive_pair(Default::default())
- }
-
- /// Returns the key pair for this account at the `spend` and `view` indices, if those indices
- /// do not exceed the maximum indices.
- #[inline]
- pub fn keypair(&self, index: KeyIndex) -> Option> {
- self.with_bounds_check(index, Self::derive_pair)
- }
-
- /// Returns an iterator over all the key pairs associated to `self`.
- #[inline]
- pub fn keypairs(&self) -> impl '_ + Iterator
- > {
- let mut index = KeyIndex::default();
- iter::from_fn(move || {
- let next = self.keypair(index);
- index.increment();
- next
- })
- }
-
- /// Returns a new [`ViewKeyTable`] for `self`.
- #[inline]
- pub fn view_key_table(self) -> ViewKeyTable<'h, H> {
- ViewKeyTable::new(self)
- }
-}
-
-/// View Key Table
-pub struct ViewKeyTable<'h, H>
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Account Keys
- keys: AccountKeysMut<'h, H>,
-
- /// Pre-computed View Keys
- view_keys: BTreeMap,
}
-impl<'h, H> ViewKeyTable<'h, H>
+impl Account
where
- H: HierarchicalKeyDerivationScheme + ?Sized,
+ H: AccountCollection,
{
- /// View Key Buffer Maximum Size Limit
- pub const VIEW_KEY_BUFFER_LIMIT: usize = 16 * (H::GAP_LIMIT as usize);
-
- /// Builds a new [`ViewKeyTable`] over the account `keys`.
+ /// Builds a new [`Account`] from `key` and `index`.
#[inline]
- pub fn new(keys: AccountKeysMut<'h, H>) -> Self {
- Self {
- keys,
- view_keys: Default::default(),
- }
+ pub fn new(key: H, index: AccountIndex) -> Self {
+ Self { key, index }
}
- /// Returns the account keys associated to `self`.
+ /// Returns the [`SpendingKey`] corresponding to `self`.
#[inline]
- pub fn into_keys(self) -> AccountKeysMut<'h, H> {
- self.keys
+ pub fn spending_key(&self) -> SpendingKey {
+ self.key.spending_key(&self.index)
}
- /// Returns the view key for this account at `index`, if it does not exceed the maximum index.
- ///
- /// # Limits
- ///
- /// This function uses a view key buffer that stores the computed keys to reduce the number of
- /// times a re-compute of the view keys is needed while searching. The buffer only grows past
- /// the current key bounds with a call to [`find_index_with_gap`](Self::find_index_with_gap)
- /// which extends the buffer by at most [`GAP_LIMIT`]-many keys per round. To prevent allocating
- /// too much memory, the internal buffer is capped at [`VIEW_KEY_BUFFER_LIMIT`]-many elements.
- ///
- /// [`GAP_LIMIT`]: HierarchicalKeyDerivationScheme::GAP_LIMIT
- /// [`VIEW_KEY_BUFFER_LIMIT`]: Self::VIEW_KEY_BUFFER_LIMIT
+ /// Returns the [`AccountCollection`] corresponding to `self`.
#[inline]
- pub fn view_key(&mut self, index: KeyIndex) -> Option<&H::SecretKey> {
- btree_map::get_or_mutate(&mut self.view_keys, &index, |map| {
- let next_key = self.keys.view_key(index)?;
- if map.len() == Self::VIEW_KEY_BUFFER_LIMIT {
- btree_map::pop_last(map);
- }
- Some(btree_map::insert_then_get(map, index, next_key))
- })
- }
-
- /// Applies `f` to the view keys generated by `self` returning the first non-`None` result with
- /// it's key index and key attached, or returns `None` if every application of `f` returned
- /// `None`.
- #[inline]
- pub fn find_index(&mut self, mut f: F) -> Option>
- where
- F: FnMut(&H::SecretKey) -> Option,
- {
- let mut index = KeyIndex::default();
- loop {
- if let Some(item) = f(self.view_key(index)?) {
- self.keys.account.last_used_index =
- cmp::max(self.keys.account.last_used_index, index);
- return Some(ViewKeySelection {
- index,
- keypair: self.keys.derive_pair(index),
- item,
- });
- }
- index.increment();
- }
- }
-
- /// Applies `f` to the view keys generated by `self` returning the first non-`None` result with
- /// it's key index and key attached, or returns `None` if every application pf `f` returned
- /// `None`.
- ///
- /// # Gap Limit
- ///
- /// This method extends the current maximum index by [`GAP_LIMIT`]-many indices while searching
- /// and then sets the new maximum to the previous maximum or the located index, whichever is
- /// larger.
- ///
- /// [`GAP_LIMIT`]: HierarchicalKeyDerivationScheme::GAP_LIMIT
- #[inline]
- pub fn find_index_with_gap(&mut self, f: F) -> Option>
- where
- F: FnMut(&H::SecretKey) -> Option,
- {
- let previous_maximum = self.keys.account.maximum_index;
- self.keys.account.maximum_index.index += H::GAP_LIMIT;
- match self.find_index(f) {
- Some(result) => {
- self.keys.account.maximum_index = cmp::max(previous_maximum, result.index);
- Some(result)
- }
- _ => {
- self.keys.account.maximum_index = previous_maximum;
- None
- }
- }
- }
-
- /// Runs one of the index search algorithms depending on the value of `use_gap_limit`, where
- /// [`find_index_with_gap`](Self::find_index_with_gap) is used in the case that `use_gap_limit`
- /// is `true`, and [`find_index`](Self::find_index) is used otherwise.
- #[inline]
- pub fn find_index_with_maybe_gap(
- &mut self,
- use_gap_limit: bool,
- f: F,
- ) -> Option>
- where
- F: FnMut(&H::SecretKey) -> Option,
- {
- if use_gap_limit {
- self.find_index_with_gap(f)
- } else {
- self.find_index(f)
- }
+ pub fn keys(&self) -> &H {
+ &self.key
}
}
-/// View Key Selection
-pub struct ViewKeySelection
+impl DeriveAddress for Account
where
- H: HierarchicalKeyDerivationScheme + ?Sized,
+ H: AccountCollection + DeriveAddresses,
{
- /// Selection Index
- pub index: KeyIndex,
+ type Address = H::Address;
+ type Parameters = H::Parameters;
- /// Selection Key Pair
- pub keypair: SecretKeyPair,
-
- /// Selection Item
- pub item: T,
-}
-
-impl ViewKeySelection
-where
- H: HierarchicalKeyDerivationScheme + ?Sized,
-{
- /// Computes `f` on `self.item` returning a new [`ViewKeySelection`] with the same `index` and
- /// `keypair`.
#[inline]
- pub fn map(self, f: F) -> ViewKeySelection
- where
- F: FnOnce(T) -> U,
- {
- ViewKeySelection {
- index: self.index,
- keypair: self.keypair,
- item: f(self.item),
- }
- }
-}
-
-/// Account
-#[cfg_attr(
- feature = "serde",
- derive(Deserialize, Serialize),
- serde(crate = "manta_util::serde", deny_unknown_fields)
-)]
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
-pub struct Account {
- /// Last Used Index
- ///
- /// This index is used to enforce limits when generating new keys beyond the `maximum_index`.
- pub last_used_index: KeyIndex,
-
- /// Maximum Index
- pub maximum_index: KeyIndex,
-}
-
-/// Account Map Trait
-pub trait AccountMap {
- /// Builds a new [`AccountMap`] with a starting account with the default maximum index.
- fn new() -> Self;
-
- /// Returns the last account index stored in the map.
- fn last_account(&self) -> AccountIndex;
-
- /// Adds a new account to the map, returning the new account index.
- fn create_account(&mut self) -> AccountIndex;
-
- /// Returns the [`Account`] associated to `account`.
- fn get(&self, account: AccountIndex) -> Option;
-
- /// Returns the [`Account`] associated to `account`.
- fn get_mut(&mut self, account: AccountIndex) -> Option<&mut Account>;
-}
-
-/// [`Vec`] Account Map Type
-pub type VecAccountMap = Vec;
-
-impl AccountMap for VecAccountMap {
- #[inline]
- fn new() -> Self {
- let mut this = Self::new();
- this.create_account();
- this
- }
-
- #[inline]
- fn last_account(&self) -> AccountIndex {
- AccountIndex::new(
- (self.len() - 1)
- .try_into()
- .expect("AccountIndex is not allowed to exceed IndexType::MAX."),
- )
- }
-
- #[inline]
- fn create_account(&mut self) -> AccountIndex {
- let index = AccountIndex::new(
- self.len()
- .try_into()
- .expect("AccountIndex is not allowed to exceed IndexType::MAX."),
- );
- self.push(Default::default());
- index
- }
-
- #[inline]
- fn get(&self, account: AccountIndex) -> Option {
- self.as_slice().get(account.index() as usize).copied()
- }
-
- #[inline]
- fn get_mut(&mut self, account: AccountIndex) -> Option<&mut Account> {
- self.as_mut_slice().get_mut(account.index() as usize)
+ fn address(&self, parameters: &Self::Parameters) -> Self::Address {
+ self.key.address(parameters, self.index)
}
}
/// Account Table
///
-/// The account table stores an underlying [`HierarchicalKeyDerivationScheme`] for key generation
+/// The account table stores an underlying [`AccountCollection`] for key generation
/// and a set of accounts defined by an [`AccountMap`] which can be queried to get the set of
/// existing keys and for generating new keys.
#[cfg_attr(
@@ -798,10 +323,10 @@ impl AccountMap for VecAccountMap {
)]
pub struct AccountTable
where
- H: HierarchicalKeyDerivationScheme,
- M: AccountMap,
+ H: AccountCollection,
+ M: AccountMap,
{
- /// Hierarchical Key Derivation Scheme
+ /// Account Collection
keys: H,
/// Account Map
@@ -810,8 +335,8 @@ where
impl AccountTable
where
- H: HierarchicalKeyDerivationScheme,
- M: AccountMap,
+ H: AccountCollection,
+ M: AccountMap,
{
/// Builds a new [`AccountTable`] using `keys` and the default account map.
#[inline]
@@ -825,115 +350,42 @@ where
Self { keys, accounts }
}
- /// Returns the underlying [`HierarchicalKeyDerivationScheme`] of `self`.
+ /// Returns the [`AccountCollection`] corresponding to `self`.
#[inline]
pub fn keys(&self) -> &H {
&self.keys
}
- /// Returns the secret key pair associated to `account` if it exists, using `index` if it does
- /// not exceed the maximum key index.
- #[inline]
- pub fn keypair(
- &self,
- account: AccountIndex,
- index: KeyIndex,
- ) -> Option