Skip to content

Commit

Permalink
feat: improve ledger API flexibility and encoding (#59)
Browse files Browse the repository at this point in the history
* feat: separate pull configuration from ledger connection

* feat: add raw checkpoint

* feat: expose serde_with in public API for manta-util
  • Loading branch information
bhgomes authored May 5, 2022
1 parent ec4470b commit c1e46ad
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 15 deletions.
34 changes: 23 additions & 11 deletions manta-accounting/src/wallet/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@

//! Ledger Connection

// TODO: Report a more meaningful error on `push` failure. In some way, it must match the
// `TransferPostError` variants.

use crate::transfer::{Configuration, EncryptedNote, TransferPost, Utxo, VoidNumber};
use alloc::vec::Vec;
use core::{fmt::Debug, hash::Hash};
Expand All @@ -28,16 +25,20 @@ use manta_util::future::LocalBoxFutureResult;
use manta_util::serde::{Deserialize, Serialize};

/// Ledger Checkpoint
///
/// The checkpoint type is responsible for keeping the ledger, signer, and wallet in sync with each
/// other making sure that they all have the same view of the ledger state. Checkpoints should
/// be orderable with a bottom element returned by [`Default::default`].
pub trait Checkpoint: Default + PartialOrd {
/// Returns the index into the receiver set for the ledger.
///
/// This index is used to ensure that wallets are synchronized even during connection failures
/// or other errors during synchronization.
fn receiver_index(&self) -> usize;

/// Returns the index into the sender set for the ledger.
fn sender_index(&self) -> usize;
}

/// Ledger Source Connection
pub trait Connection<C>
/// Ledger Pull Configuration
pub trait PullConfiguration<C>
where
C: Configuration,
{
Expand All @@ -49,7 +50,13 @@ where

/// Sender Chunk Iterator Type
type SenderChunk: IntoIterator<Item = VoidNumber<C>>;
}

/// Ledger Source Connection
pub trait Connection<C>: PullConfiguration<C>
where
C: Configuration,
{
/// Push Response Type
///
/// This is the return type of the [`push`](Self::push) method. Use this type to customize the
Expand All @@ -60,10 +67,15 @@ where
type PushResponse;

/// Error Type
///
/// This error type corresponds to the communication channel itself setup by the [`Connection`]
/// rather than any errors introduced by the [`pull`](Self::pull) or [`push`](Self::push)
/// methods themselves which would correspond to an empty [`PullResponse`] or whatever error
/// variants are stored in [`PushResponse`](Self::PushResponse).
type Error;

/// Pulls receiver data from the ledger starting from `checkpoint`, returning the current
/// [`Checkpoint`](Self::Checkpoint).
/// [`Checkpoint`](PullConfiguration::Checkpoint).
fn pull<'s>(
&'s mut self,
checkpoint: &'s Self::Checkpoint,
Expand Down Expand Up @@ -116,7 +128,7 @@ where
pub struct PullResponse<C, L>
where
C: Configuration,
L: Connection<C> + ?Sized,
L: PullConfiguration<C> + ?Sized,
{
/// Pull Continuation Flag
///
Expand All @@ -127,7 +139,7 @@ where
/// Ledger Checkpoint
///
/// If the `should_continue` flag is set to `true` then `checkpoint` is the next
/// [`Checkpoint`](Connection::Checkpoint) to request data from the ledger. Otherwise, it
/// [`Checkpoint`](PullConfiguration::Checkpoint) to request data from the ledger. Otherwise, it
/// represents the current ledger state.
pub checkpoint: L::Checkpoint,

Expand Down
4 changes: 2 additions & 2 deletions manta-accounting/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ where
&self.ledger
}

/// Returns the [`Checkpoint`](ledger::Connection::Checkpoint) representing the current state
/// of this wallet.
/// Returns the [`Checkpoint`](ledger::PullConfiguration::Checkpoint) representing the current
/// state of this wallet.
#[inline]
pub fn checkpoint(&self) -> &L::Checkpoint {
&self.checkpoint
Expand Down
113 changes: 113 additions & 0 deletions manta-pay/src/signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,122 @@ impl Default for Checkpoint {
}
}

impl From<RawCheckpoint> for Checkpoint {
#[inline]
fn from(checkpoint: RawCheckpoint) -> Self {
Self::new(
checkpoint.receiver_index.map(|i| i as usize).into(),
checkpoint.sender_index as usize,
)
}
}

impl ledger::Checkpoint for Checkpoint {
#[inline]
fn receiver_index(&self) -> usize {
self.receiver_index.iter().sum()
}

#[inline]
fn sender_index(&self) -> usize {
self.sender_index
}
}

#[cfg(feature = "scale")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "scale")))]
impl scale_codec::Decode for Checkpoint {
#[inline]
fn decode<I>(input: &mut I) -> Result<Self, scale_codec::Error>
where
I: scale_codec::Input,
{
RawCheckpoint::decode(input).map(Into::into)
}
}

#[cfg(feature = "scale")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "scale")))]
impl scale_codec::Encode for Checkpoint {
#[inline]
fn using_encoded<R, Encoder>(&self, f: Encoder) -> R
where
Encoder: FnOnce(&[u8]) -> R,
{
RawCheckpoint::from(*self).using_encoded(f)
}
}

#[cfg(feature = "scale")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "scale")))]
impl scale_codec::EncodeLike for Checkpoint {}

#[cfg(feature = "scale")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "scale")))]
impl scale_codec::MaxEncodedLen for Checkpoint {
#[inline]
fn max_encoded_len() -> usize {
RawCheckpoint::max_encoded_len()
}
}

#[cfg(feature = "scale")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "scale")))]
impl scale_info::TypeInfo for Checkpoint {
type Identity = RawCheckpoint;

#[inline]
fn type_info() -> scale_info::Type {
Self::Identity::type_info()
}
}

/// Raw Checkpoint for Encoding and Decoding
#[cfg_attr(
feature = "scale",
derive(
scale_codec::Decode,
scale_codec::Encode,
scale_codec::MaxEncodedLen,
scale_info::TypeInfo
)
)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct RawCheckpoint {
/// Receiver Index
pub receiver_index: [u64; MerkleTreeConfiguration::FOREST_WIDTH],

/// Sender Index
pub sender_index: u64,
}

impl RawCheckpoint {
/// Builds a new [`RawCheckpoint`] from `receiver_index` and `sender_index`.
#[inline]
pub fn new(
receiver_index: [u64; MerkleTreeConfiguration::FOREST_WIDTH],
sender_index: u64,
) -> Self {
Self {
receiver_index,
sender_index,
}
}
}

impl Default for RawCheckpoint {
#[inline]
fn default() -> Self {
Self::new([0; MerkleTreeConfiguration::FOREST_WIDTH], 0)
}
}

impl From<Checkpoint> for RawCheckpoint {
#[inline]
fn from(checkpoint: Checkpoint) -> Self {
Self::new(
(*checkpoint.receiver_index).map(|i| i as u64),
checkpoint.sender_index as u64,
)
}
}
5 changes: 4 additions & 1 deletion manta-pay/src/simulation/ledger/http/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,13 @@ impl Client {
}
}

impl ledger::Connection<Config> for Client {
impl ledger::PullConfiguration<Config> for Client {
type Checkpoint = Checkpoint;
type ReceiverChunk = Vec<(Utxo, EncryptedNote)>;
type SenderChunk = Vec<VoidNumber>;
}

impl ledger::Connection<Config> for Client {
type PushResponse = bool;
type Error = Error;

Expand Down
5 changes: 4 additions & 1 deletion manta-pay/src/simulation/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,13 @@ impl LedgerConnection {
}
}

impl ledger::Connection<Config> for LedgerConnection {
impl ledger::PullConfiguration<Config> for LedgerConnection {
type Checkpoint = Checkpoint;
type ReceiverChunk = Vec<(Utxo, EncryptedNote)>;
type SenderChunk = Vec<VoidNumber>;
}

impl ledger::Connection<Config> for LedgerConnection {
type PushResponse = bool;
type Error = Infallible;

Expand Down
5 changes: 5 additions & 0 deletions manta-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ pub use sealed::*;
#[doc(inline)]
pub use serde;

#[cfg(feature = "serde_with")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "serde_with")))]
#[doc(inline)]
pub use serde_with;

/// Implements [`From`]`<$from>` for an enum `$to`, choosing the `$kind` variant.
// TODO: add `where` clauses
#[macro_export]
Expand Down

0 comments on commit c1e46ad

Please sign in to comment.