diff --git a/Cargo.lock b/Cargo.lock index 073a910ca..8cf36388e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5160,8 +5160,8 @@ dependencies = [ [[package]] name = "manta-accounting" -version = "0.5.12" -source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.12#ba1a4b747456bc4f76a9cb18b515aaf0810b4c9c" +version = "0.5.13" +source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.13#0c36f42a26d3955712ae371bf1bf85a7e2849264" dependencies = [ "derivative", "derive_more", @@ -5204,8 +5204,8 @@ dependencies = [ [[package]] name = "manta-crypto" -version = "0.5.12" -source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.12#ba1a4b747456bc4f76a9cb18b515aaf0810b4c9c" +version = "0.5.13" +source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.13#0c36f42a26d3955712ae371bf1bf85a7e2849264" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -5230,8 +5230,8 @@ dependencies = [ [[package]] name = "manta-parameters" -version = "0.5.12" -source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.12#ba1a4b747456bc4f76a9cb18b515aaf0810b4c9c" +version = "0.5.13" +source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.13#0c36f42a26d3955712ae371bf1bf85a7e2849264" dependencies = [ "anyhow", "attohttpc", @@ -5243,8 +5243,8 @@ dependencies = [ [[package]] name = "manta-pay" -version = "0.5.12" -source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.12#ba1a4b747456bc4f76a9cb18b515aaf0810b4c9c" +version = "0.5.13" +source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.13#0c36f42a26d3955712ae371bf1bf85a7e2849264" dependencies = [ "aes-gcm", "bip32", @@ -5347,8 +5347,8 @@ dependencies = [ [[package]] name = "manta-util" -version = "0.5.12" -source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.12#ba1a4b747456bc4f76a9cb18b515aaf0810b4c9c" +version = "0.5.13" +source = "git+https://github.com/manta-network/manta-rs.git?tag=v0.5.13#0c36f42a26d3955712ae371bf1bf85a7e2849264" dependencies = [ "crossbeam-channel", "serde", diff --git a/pallets/manta-pay/Cargo.toml b/pallets/manta-pay/Cargo.toml index e59281d99..22871d0e1 100644 --- a/pallets/manta-pay/Cargo.toml +++ b/pallets/manta-pay/Cargo.toml @@ -107,17 +107,17 @@ sp-std = { git = 'https://github.com/paritytech/substrate.git', branch = "polkad jsonrpsee = { version = "0.15.0", features = ["server", "macros"], optional = true } # manta dependencies -manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } -manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } -manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false, features = ["groth16", "parameters", "scale"] } +manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } +manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } +manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false, features = ["groth16", "parameters", "scale"] } manta-primitives = { path = "../../primitives/manta", default-features = false } manta-support = { package = "pallet-manta-support", path = "../manta-support", default-features = false } -manta-util = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } +manta-util = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } [dev-dependencies] lazy_static = "1.4.0" -manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", features = ["getrandom"] } -manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", features = ["groth16", "parameters", "scale", "download", "test"] } +manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", features = ["getrandom"] } +manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", features = ["groth16", "parameters", "scale", "download", "test"] } pallet-asset-manager = { path = "../asset-manager" } pallet-assets = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.28" } pallet-balances = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.28" } diff --git a/pallets/manta-pay/src/lib.rs b/pallets/manta-pay/src/lib.rs index 6c96db3db..ae9e4704b 100644 --- a/pallets/manta-pay/src/lib.rs +++ b/pallets/manta-pay/src/lib.rs @@ -83,13 +83,13 @@ use manta_pay::{ use manta_primitives::assets::{self, AssetConfig, FungibleLedger as _}; use manta_support::manta_pay::{ asset_value_decode, asset_value_encode, fp_decode, fp_encode, id_from_field, AccountId, Asset, - AssetValue, FullIncomingNote, MTParametersError, NullifierCommitment, OutgoingNote, - ReceiverChunk, SenderChunk, StandardAssetId, TransferPost, Utxo, UtxoAccumulatorOutput, - UtxoItemHashError, UtxoMerkleTreePath, VerifyingContextError, Wrap, WrapPair, + AssetValue, Checkpoint, FullIncomingNote, InitialSyncResponse, MTParametersError, + NullifierCommitment, OutgoingNote, PullResponse, ReceiverChunk, SenderChunk, StandardAssetId, + TransferPost, Utxo, UtxoAccumulatorOutput, UtxoItemHashError, UtxoMerkleTreePath, + VerifyingContextError, Wrap, WrapPair, }; use manta_util::codec::Encode; -pub use manta_support::manta_pay::{Checkpoint, PullResponse, RawCheckpoint}; pub use pallet::*; pub use weights::WeightInfo; @@ -559,6 +559,25 @@ pub mod pallet { Shards::::contains_key(shard_index, max_receiver_index) } + /// Returns the diff of ledger state since the given `checkpoint` and `max_receivers` to + /// perform the initial synchronization. + #[inline] + pub fn initial_pull(checkpoint: Checkpoint, max_receivers: u64) -> InitialSyncResponse { + let (should_continue, receivers) = + Self::pull_receivers(*checkpoint.receiver_index, max_receivers); + let utxo_data = receivers.into_iter().map(|receiver| receiver.0).collect(); + let membership_proof_data = (0..=255) + .map(|i| ShardTrees::::get(i).current_path) + .collect(); + let nullifier_count = NullifierSetSize::::get() as u128; + InitialSyncResponse { + should_continue, + utxo_data, + membership_proof_data, + nullifier_count, + } + } + /// Pulls sender data from the ledger starting at the `sender_index`. #[inline] fn pull_senders(sender_index: usize, max_update_request: u64) -> (bool, SenderChunk) { diff --git a/pallets/manta-pay/src/rpc.rs b/pallets/manta-pay/src/rpc.rs index 311ef3145..e7af01a23 100644 --- a/pallets/manta-pay/src/rpc.rs +++ b/pallets/manta-pay/src/rpc.rs @@ -16,7 +16,7 @@ //! MantaPay RPC Interfaces -use crate::{runtime::PullLedgerDiffApi, Checkpoint, PullResponse}; +use crate::runtime::PullLedgerDiffApi; use alloc::sync::Arc; use core::marker::PhantomData; use jsonrpsee::{ @@ -24,7 +24,9 @@ use jsonrpsee::{ proc_macros::rpc, types::error::{CallError, ErrorObject}, }; -use manta_support::manta_pay::DensePullResponse; +use manta_support::manta_pay::{ + Checkpoint, DenseInitialSyncResponse, DensePullResponse, InitialSyncResponse, PullResponse, +}; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_runtime::{generic::BlockId, traits::Block}; @@ -52,6 +54,21 @@ pub trait PullApi { max_receivers: u64, max_senders: u64, ) -> RpcResult; + + /// Returns the update required for the initial synchronization with the ledger. + #[method(name = "mantaPay_initial_pull", blocking)] + fn initial_pull( + &self, + checkpoint: Checkpoint, + max_receivers: u64, + ) -> RpcResult; + + #[method(name = "mantaPay_dense_initial_pull", blocking)] + fn dense_initial_pull( + &self, + checkpoint: Checkpoint, + max_receivers: u64, + ) -> RpcResult; } /// Pull RPC API Implementation @@ -121,4 +138,43 @@ where .into() }) } + + #[inline] + fn initial_pull( + &self, + checkpoint: Checkpoint, + max_receivers: u64, + ) -> RpcResult { + let api = self.client.runtime_api(); + let at = BlockId::hash(self.client.info().finalized_hash); + api.initial_pull(&at, checkpoint.into(), max_receivers) + .map_err(|err| { + CallError::Custom(ErrorObject::owned( + PULL_LEDGER_DIFF_ERROR, + "Unable to compute state diff for initial pull", + Some(format!("{err:?}")), + )) + .into() + }) + } + + #[inline] + fn dense_initial_pull( + &self, + checkpoint: Checkpoint, + max_receivers: u64, + ) -> RpcResult { + let api = self.client.runtime_api(); + let at = BlockId::hash(self.client.info().finalized_hash); + api.initial_pull(&at, checkpoint.into(), max_receivers) + .map(Into::into) + .map_err(|err| { + CallError::Custom(ErrorObject::owned( + PULL_LEDGER_DIFF_ERROR, + "Unable to compute state diff for initial pull", + Some(format!("{err:?}")), + )) + .into() + }) + } } diff --git a/pallets/manta-pay/src/runtime.rs b/pallets/manta-pay/src/runtime.rs index 5d651431e..058ad5a46 100644 --- a/pallets/manta-pay/src/runtime.rs +++ b/pallets/manta-pay/src/runtime.rs @@ -16,10 +16,11 @@ //! MantaPay Runtime APIs -use crate::{PullResponse, RawCheckpoint}; +use manta_support::manta_pay::{InitialSyncResponse, PullResponse, RawCheckpoint}; sp_api::decl_runtime_apis! { pub trait PullLedgerDiffApi { fn pull_ledger_diff(checkpoint: RawCheckpoint, max_receivers: u64, max_senders: u64) -> PullResponse; + fn initial_pull(checkpoint: RawCheckpoint, max_receivers: u64) -> InitialSyncResponse; } } diff --git a/pallets/manta-sbt/Cargo.toml b/pallets/manta-sbt/Cargo.toml index e298970d3..dd20956e3 100644 --- a/pallets/manta-sbt/Cargo.toml +++ b/pallets/manta-sbt/Cargo.toml @@ -101,17 +101,17 @@ sp-std = { git = 'https://github.com/paritytech/substrate.git', branch = "polkad jsonrpsee = { version = "0.15.0", features = ["server", "macros"], optional = true } # manta dependencies -manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } -manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } -manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false, features = ["groth16", "parameters", "scale"] } +manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } +manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } +manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false, features = ["groth16", "parameters", "scale"] } manta-primitives = { path = "../../primitives/manta", default-features = false } manta-support = { package = "pallet-manta-support", path = "../manta-support", default-features = false } -manta-util = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } +manta-util = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } [dev-dependencies] lazy_static = "1.4.0" -manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", features = ["getrandom"] } -manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", features = ["groth16", "parameters", "scale", "download", "test"] } +manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", features = ["getrandom"] } +manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", features = ["groth16", "parameters", "scale", "download", "test"] } pallet-asset-manager = { path = "../asset-manager" } pallet-assets = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } pallet-balances = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.28" } diff --git a/pallets/manta-support/Cargo.toml b/pallets/manta-support/Cargo.toml index 3550a6238..370857bac 100644 --- a/pallets/manta-support/Cargo.toml +++ b/pallets/manta-support/Cargo.toml @@ -29,11 +29,11 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "po sp-std = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.28", default-features = false } # manta dependencies -manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } -manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } -manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false, features = ["groth16", "parameters", "scale"] } +manta-accounting = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } +manta-crypto = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } +manta-pay = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false, features = ["groth16", "parameters", "scale"] } manta-primitives = { path = "../../primitives/manta", default-features = false } -manta-util = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.12", default-features = false } +manta-util = { git = "https://github.com/manta-network/manta-rs.git", tag = "v0.5.13", default-features = false } [features] default = ["std"] diff --git a/pallets/manta-support/src/manta_pay.rs b/pallets/manta-support/src/manta_pay.rs index 1a63a5003..85028e19a 100644 --- a/pallets/manta-support/src/manta_pay.rs +++ b/pallets/manta-support/src/manta_pay.rs @@ -17,7 +17,6 @@ //! Type Definitions for Manta Pay use alloc::{boxed::Box, vec::Vec}; -use manta_crypto::merkle_tree; use manta_pay::{ config::{ self, @@ -26,6 +25,7 @@ use manta_pay::{ crypto::poseidon::encryption::{self, BlockArray, CiphertextBlock}, manta_crypto::{ encryption::{hybrid, EmptyHeader}, + merkle_tree, permutation::duplex, signature::schnorr, }, @@ -825,7 +825,12 @@ pub type LeafDigest = [u8; 32]; pub type InnerDigest = [u8; 32]; /// Merkle Tree Current Path -#[derive(Clone, Debug, Decode, Default, Encode, Eq, PartialEq, TypeInfo)] +#[cfg_attr( + feature = "serde", + derive(Deserialize, Serialize), + serde(crate = "manta_util::serde", deny_unknown_fields) +)] +#[derive(Clone, Debug, Decode, Default, Encode, Eq, Hash, PartialEq, TypeInfo)] pub struct CurrentPath { /// Sibling Digest pub sibling_digest: LeafDigest, @@ -899,9 +904,77 @@ pub struct UtxoMerkleTreePath { /// Receiver Chunk Data Type pub type ReceiverChunk = Vec<(Utxo, FullIncomingNote)>; +/// Utxo Chunk Data Type +pub type UtxoChunk = Vec; + +/// Merkle Tree [`CurrentPath`] Chunk Data Type +pub type CurrentPathChunk = Vec; + /// Sender Chunk Data Type pub type SenderChunk = Vec<(NullifierCommitment, OutgoingNote)>; +/// Initial Sync Response +#[cfg_attr( + feature = "serde", + derive(Deserialize, Serialize), + serde(crate = "manta_util::serde", deny_unknown_fields) +)] +#[derive(Clone, Debug, Decode, Default, Encode, Eq, Hash, PartialEq, TypeInfo)] +pub struct InitialSyncResponse { + /// Initial Sync Continuation Flag + /// + /// The `should_continue` flag is set to `true` if the client should request more data from the + /// ledger to finish the pull. + pub should_continue: bool, + + /// Ledger Utxo Chunk + pub utxo_data: UtxoChunk, + + /// Ledger [`CurrentPath`] Chunk + pub membership_proof_data: CurrentPathChunk, + + /// Nullifier Count + pub nullifier_count: u128, +} + +/// Ledger Source Dense Pull Response +#[cfg_attr( + feature = "serde", + derive(Deserialize, Serialize), + serde(crate = "manta_util::serde", deny_unknown_fields) +)] +#[derive(Clone, Debug, Encode, Default, Eq, Hash, Decode, PartialEq, TypeInfo)] +pub struct DenseInitialSyncResponse { + /// Pull Continuation Flag + /// + /// The `should_continue` flag is set to `true` if the client should request more data from the + /// ledger to finish the pull. + pub should_continue: bool, + + /// Ledger Utxo Chunk + #[codec(skip)] + pub utxo_data: alloc::string::String, + + /// Ledger [`CurrentPath`] Chunk + #[codec(skip)] + pub membership_proof_data: alloc::string::String, + + /// Nullifier Count + pub nullifier_count: u128, +} + +impl From for DenseInitialSyncResponse { + #[inline] + fn from(resp: InitialSyncResponse) -> DenseInitialSyncResponse { + Self { + should_continue: resp.should_continue, + utxo_data: base64::encode(resp.utxo_data.encode()), + membership_proof_data: base64::encode(resp.membership_proof_data.encode()), + nullifier_count: resp.nullifier_count, + } + } +} + /// Ledger Source Pull Response #[cfg_attr( feature = "serde", diff --git a/runtime/calamari/src/lib.rs b/runtime/calamari/src/lib.rs index 809e7e6ae..6624343e7 100644 --- a/runtime/calamari/src/lib.rs +++ b/runtime/calamari/src/lib.rs @@ -56,7 +56,7 @@ use manta_primitives::{ constants::{time::*, RocksDbWeight, STAKING_PALLET_ID, TREASURY_PALLET_ID, WEIGHT_PER_SECOND}, types::{AccountId, Balance, BlockNumber, Hash, Header, Index, Signature}, }; -use manta_support::manta_pay::{PullResponse, RawCheckpoint}; +use manta_support::manta_pay::{InitialSyncResponse, PullResponse, RawCheckpoint}; pub use pallet_parachain_staking::{InflationInfo, Range}; use pallet_session::ShouldEndSession; use runtime_common::{ @@ -1070,6 +1070,9 @@ impl_runtime_apis! { ) -> PullResponse { MantaPay::pull_ledger_diff(checkpoint.into(), max_receiver, max_sender) } + fn initial_pull(checkpoint: RawCheckpoint, max_receiver: u64) -> InitialSyncResponse { + MantaPay::initial_pull(checkpoint.into(), max_receiver) + } } impl pallet_manta_sbt::runtime::SBTPullLedgerDiffApi for Runtime { diff --git a/runtime/dolphin/src/lib.rs b/runtime/dolphin/src/lib.rs index 87965baf9..f39eaf770 100644 --- a/runtime/dolphin/src/lib.rs +++ b/runtime/dolphin/src/lib.rs @@ -59,7 +59,7 @@ use manta_primitives::{ }, types::{AccountId, Balance, BlockNumber, Hash, Header, Index, Signature}, }; -use manta_support::manta_pay::{PullResponse, RawCheckpoint}; +use manta_support::manta_pay::{InitialSyncResponse, PullResponse, RawCheckpoint}; use runtime_common::{ prod_or_fast, BlockExecutionWeight, BlockHashCount, ExtrinsicBaseWeight, SlowAdjustingFeeUpdate, }; @@ -997,6 +997,9 @@ impl_runtime_apis! { ) -> PullResponse { MantaPay::pull_ledger_diff(checkpoint.into(), max_receiver, max_sender) } + fn initial_pull(checkpoint: RawCheckpoint, max_receiver: u64) -> InitialSyncResponse { + MantaPay::initial_pull(checkpoint.into(), max_receiver) + } } impl pallet_manta_sbt::runtime::SBTPullLedgerDiffApi for Runtime {