Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial signer sync #329

Merged
merged 36 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ae47774
checkpoint
SupremoUGH Mar 14, 2023
df6edd4
checkpoint
SupremoUGH Mar 15, 2023
164057a
checkpoint
SupremoUGH Mar 15, 2023
629bdec
Merge branch 'main' into signer_initial_sync_checkout
SupremoUGH Mar 15, 2023
60c5eb8
merkle tree functions
SupremoUGH Mar 15, 2023
6496e48
accumulator trait
SupremoUGH Mar 15, 2023
e6d73f9
signer functions
SupremoUGH Mar 15, 2023
8444d01
signer initial sync
SupremoUGH Mar 15, 2023
1c18f58
wallet has method as well
SupremoUGH Mar 15, 2023
091eb31
tests
SupremoUGH Mar 16, 2023
0c78f26
change dep
SupremoUGH Mar 16, 2023
be369ad
fixed dep
SupremoUGH Mar 16, 2023
8053258
dep
SupremoUGH Mar 16, 2023
ca0ad1d
rearranged tests
SupremoUGH Mar 17, 2023
9cc2e1f
restored cargo.toml
SupremoUGH Mar 17, 2023
68ce7ac
clippy
SupremoUGH Mar 17, 2023
d9c2a77
changed nullifier data and batched the initial sync
SupremoUGH Mar 17, 2023
e57d2b6
final design
SupremoUGH Mar 20, 2023
1d83f3c
export type CurrentPath
SupremoUGH Mar 20, 2023
976ae74
small error
SupremoUGH Mar 20, 2023
e16c651
debugging
SupremoUGH Mar 21, 2023
0c1506d
debug
SupremoUGH Mar 21, 2023
bcd0aff
debugging
SupremoUGH Mar 21, 2023
69a088b
changed default impl
SupremoUGH Mar 21, 2023
087e7b6
first round of corrections
SupremoUGH Mar 22, 2023
09b5969
debug removed
SupremoUGH Mar 22, 2023
aa4b43b
unused imports
SupremoUGH Mar 22, 2023
30fe0d8
simplified initial sync. added reset to initial sync
SupremoUGH Mar 22, 2023
c2a4610
simulation restored
SupremoUGH Mar 22, 2023
c3bd754
testing fixed
SupremoUGH Mar 22, 2023
c99cf89
test fixed
SupremoUGH Mar 22, 2023
8bd829c
fixed feature issue
SupremoUGH Mar 22, 2023
c87f67b
changelog
SupremoUGH Mar 22, 2023
91901de
signer method in wallet
SupremoUGH Mar 22, 2023
fe4ed12
Merge branch 'main' into signer_initial_sync_checkout
SupremoUGH Mar 23, 2023
090b67e
comments addressed
SupremoUGH Mar 24, 2023
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]
### Added
- [\#329](https://github.com/Manta-Network/manta-rs/pull/329) Signer initial synchronization method.
- [\#328](https://github.com/Manta-Network/manta-rs/pull/328) Expose reset wallet method.

### Changed
Expand Down
3 changes: 2 additions & 1 deletion manta-accounting/src/transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ pub trait Configuration {
type UtxoAccumulatorItemHash: ItemHashFunction<Utxo<Self>, Item = UtxoAccumulatorItem<Self>>;

/// Parameters Type
type Parameters: auth::DeriveContext
type Parameters: Clone
+ auth::DeriveContext
+ auth::ProveAuthorization
+ auth::VerifyAuthorization
+ auth::DeriveSigningKey
Expand Down
103 changes: 92 additions & 11 deletions manta-accounting/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ use crate::{
balance::{BTreeMapBalanceState, BalanceState},
ledger::ReadResponse,
signer::{
BalanceUpdate, IdentityRequest, IdentityResponse, SignError, SignRequest, SignResponse,
BalanceUpdate, Checkpoint, IdentityRequest, IdentityResponse, InitialSyncData,
InitialSyncRequest, SignError, SignRequest, SignResponse,
SignWithTransactionDataResponse, SyncData, SyncError, SyncRequest, SyncResponse,
TransactionDataRequest, TransactionDataResponse,
SyncResult, TransactionDataRequest, TransactionDataResponse,
},
},
};
Expand Down Expand Up @@ -144,6 +145,12 @@ where
Self::new_unchecked(ledger, Default::default(), signer, Default::default())
}

/// Returns the [`Connection`](signer::Connection).
#[inline]
pub fn signer(&self) -> &S {
&self.signer
}

/// Returns a mutable reference to the [`Connection`](signer::Connection).
///
/// # Crypto Safety
Expand Down Expand Up @@ -265,6 +272,57 @@ where
Ok(())
}

/// Pulls data from the ledger, synchronizing the wallet and balance state. This method
/// builds a [`InitialSyncRequest`] by continuously calling [`read`](ledger::Read::read)
/// until all the ledger data has arrived. Once the request is built, it executes
/// synchronizes the signer against it.
///
/// # Implementation Note
///
/// Using this method to synchronize a signer will make it impossibile to spend any
/// [`Utxo`](crate::transfer::Utxo)s already on the ledger at the time of synchronization.
/// Therefore, this method should only be used for the initial synchronization of a
/// new signer.
///
/// # Failure Conditions
///
/// This method returns an element of type [`Error`] on failure, which can result from any
/// number of synchronization issues between the wallet, the ledger, and the signer. See the
/// [`InconsistencyError`] type for more information on the kinds of errors that can occur and
/// how to resolve them.
#[inline]
pub async fn initial_sync(&mut self) -> Result<(), Error<C, L, S>>
where
L: ledger::Read<InitialSyncData<C>, Checkpoint = S::Checkpoint>,
C: signer::Configuration,
S::Checkpoint: signer::Checkpoint<C>,
{
let mut is_continue = true;
let mut checkpoint = Default::default();
let mut request = InitialSyncRequest::<C>::default();
let parameters = self
.signer
.transfer_parameters()
.await
.map_err(Error::SignerConnectionError)?;
while is_continue {
let ReadResponse {
should_continue,
data,
} = self
.ledger
.read(&checkpoint)
.await
.map_err(Error::LedgerConnectionError)?;
is_continue = should_continue;
request.extend_with_data(&parameters, data);
checkpoint
.update_from_utxo_count(request.utxo_data.iter().map(|utxos| utxos.len()).collect())
}
self.signer_initial_sync(request).await?;
Ok(())
}

/// Pulls data from the ledger, synchronizing the wallet and balance state. This method returns
/// a [`ControlFlow`] for matching against to determine if the wallet requires more
/// synchronization.
Expand Down Expand Up @@ -305,18 +363,13 @@ where
Ok(ControlFlow::should_continue(should_continue))
}

/// Performs a synchronization with the signer against the given `request`.
/// Updates `self` from `response`.
#[inline]
async fn signer_sync(
fn process_sync_response(
&mut self,
request: SyncRequest<C, S::Checkpoint>,
response: SyncResult<C, S::Checkpoint>,
) -> Result<(), Error<C, L, S>> {
match self
.signer
.sync(request)
.await
.map_err(Error::SignerConnectionError)?
{
match response {
Ok(SyncResponse {
checkpoint,
balance_update,
Expand Down Expand Up @@ -350,6 +403,34 @@ where
}
}

/// Performs a synchronization with the signer against the given `request`.
#[inline]
async fn signer_sync(
&mut self,
request: SyncRequest<C, S::Checkpoint>,
) -> Result<(), Error<C, L, S>> {
let response = self
.signer
.sync(request)
.await
.map_err(Error::SignerConnectionError)?;
self.process_sync_response(response)
}

/// Performs an initial synchronization with the signer against the given `request`.
#[inline]
async fn signer_initial_sync(
&mut self,
request: InitialSyncRequest<C>,
) -> Result<(), Error<C, L, S>> {
let response = self
.signer
.initial_sync(request)
.await
.map_err(Error::SignerConnectionError)?;
self.process_sync_response(response)
}

/// Checks if `transaction` can be executed on the balance state of `self`, returning the
/// kind of update that should be performed on the balance state if the transaction is
/// successfully posted to the ledger.
Expand Down
77 changes: 71 additions & 6 deletions manta-accounting/src/wallet/signer/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ use crate::{
Address, Asset, AssociatedData, Authorization, AuthorizationContext, FullParametersRef,
IdentifiedAsset, Identifier, IdentityProof, Note, Nullifier, Parameters, PreSender,
ProvingContext, Receiver, Sender, Shape, SpendingKey, Transfer, TransferPost, Utxo,
UtxoAccumulatorItem, UtxoAccumulatorModel,
UtxoAccumulatorItem, UtxoAccumulatorModel, UtxoAccumulatorWitness,
},
wallet::signer::{
AccountTable, BalanceUpdate, Checkpoint, Configuration, SignError, SignResponse,
SignWithTransactionDataResponse, SignWithTransactionDataResult, SignerParameters, SyncData,
SyncError, SyncRequest, SyncResponse,
AccountTable, BalanceUpdate, Checkpoint, Configuration, InitialSyncRequest, SignError,
SignResponse, SignWithTransactionDataResponse, SignWithTransactionDataResult,
SignerParameters, SyncData, SyncError, SyncRequest, SyncResponse,
},
};
use alloc::{vec, vec::Vec};
use manta_crypto::{
accumulator::{Accumulator, ItemHashFunction, OptimizedAccumulator},
accumulator::{Accumulator, FromItemsAndWitnesses, ItemHashFunction, OptimizedAccumulator},
rand::Rand,
};
use manta_util::{
Expand Down Expand Up @@ -110,7 +110,7 @@ where
/// Hashes `utxo` using the [`UtxoAccumulatorItemHash`](transfer::Configuration::UtxoAccumulatorItemHash)
/// in the transfer [`Configuration`](transfer::Configuration).
#[inline]
fn item_hash<C>(parameters: &C::Parameters, utxo: &Utxo<C>) -> UtxoAccumulatorItem<C>
pub fn item_hash<C>(parameters: &C::Parameters, utxo: &Utxo<C>) -> UtxoAccumulatorItem<C>
where
C: Configuration,
{
Expand Down Expand Up @@ -933,3 +933,68 @@ where
.collect(),
))
}

/// Updates `assets`, `checkpoint` and `utxo_accumulator`, returning the new asset distribution.
#[inline]
pub fn intial_sync<C>(
assets: &mut C::AssetMap,
checkpoint: &mut C::Checkpoint,
utxo_accumulator: &mut C::UtxoAccumulator,
request: InitialSyncRequest<C>,
) -> Result<SyncResponse<C, C::Checkpoint>, SyncError<C::Checkpoint>>
where
C: Configuration,
C::AssetMap: Default,
C::Checkpoint: Default,
{
let InitialSyncRequest {
utxo_data,
membership_proof_data,
nullifier_count,
} = request;
*checkpoint = Default::default();
*assets = Default::default();
let (accumulator, response) = initial_sync_with::<C>(
assets,
checkpoint,
utxo_accumulator.model(),
utxo_data,
membership_proof_data,
nullifier_count,
);
*utxo_accumulator = accumulator;
utxo_accumulator.commit();
Ok(response)
}

/// Updates the internal ledger state from `utxos`, `membership_proof_data`
/// and `nullifier_count`.
#[inline]
fn initial_sync_with<C>(
assets: &C::AssetMap,
checkpoint: &mut C::Checkpoint,
utxo_accumulator_model: &UtxoAccumulatorModel<C>,
utxos: Vec<Vec<UtxoAccumulatorItem<C>>>,
membership_proof_data: Vec<UtxoAccumulatorWitness<C>>,
nullifier_count: u128,
) -> (C::UtxoAccumulator, SyncResponse<C, C::Checkpoint>)
where
C: Configuration,
{
let accumulator = C::UtxoAccumulator::from_items_and_witnesses(
utxo_accumulator_model,
utxos,
membership_proof_data,
);
checkpoint.update_from_nullifiers(nullifier_count as usize);
checkpoint.update_from_utxo_accumulator(&accumulator);
(
accumulator,
SyncResponse {
checkpoint: checkpoint.clone(),
balance_update: BalanceUpdate::Full {
assets: assets.assets().into(),
},
},
)
}
Loading