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

Transaction data methods #295

Merged
merged 14 commits into from
Jan 12, 2023
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
- [\#295](https://github.com/Manta-Network/manta-rs/pull/295) Transaction data retrieving methods for the signer.

### Changed
- [\#293](https://github.com/Manta-Network/manta-rs/pull/293) Add decimals argument to AssetMetadata display
Expand Down
91 changes: 86 additions & 5 deletions manta-accounting/src/transfer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
use crate::{
asset::{self, AssetMap, AssetMetadata, MetadataDisplay},
transfer::{
has_public_participants, internal_pair, requires_authorization, Address, Asset,
AssociatedData, Authorization, AuthorizationContext, Configuration, FullParametersRef,
Parameters, PreSender, ProofSystemError, ProofSystemPublicParameters, ProvingContext,
Receiver, Sender, Transfer, TransferLedger, TransferPost, TransferPostingKeyRef,
VerifyingContext,
has_public_participants, internal_pair, requires_authorization, utxo::UtxoReconstruct,
Address, Asset, AssociatedData, Authorization, AuthorizationContext, Configuration,
FullParametersRef, Identifier, Parameters, PreSender, ProofSystemError,
ProofSystemPublicParameters, ProvingContext, Receiver, Sender, Transfer, TransferLedger,
TransferPost, TransferPostingKeyRef, Utxo, VerifyingContext,
},
};
use alloc::{string::String, vec::Vec};
Expand Down Expand Up @@ -674,3 +674,84 @@ where
},
))
}

/// Transaction Data
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(
bound(
deserialize = "Asset<C>: Deserialize<'de>, Identifier<C>: Deserialize<'de>",
serialize = "Asset<C>: Serialize, Identifier<C>: Serialize",
),
crate = "manta_util::serde",
deny_unknown_fields
)
)]
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = "Asset<C>: Clone, Identifier<C>: Clone"),
Debug(bound = "Asset<C>: Debug, Identifier<C>: Debug"),
Eq(bound = "Asset<C>: Eq, Identifier<C>: Eq"),
Hash(bound = "Asset<C>: Hash, Identifier<C>: Hash"),
PartialEq(bound = "Asset<C>: PartialEq, Identifier<C>: PartialEq")
)]
pub enum TransactionData<C>
where
C: Configuration,
{
/// To Private Transaction Data
ToPrivate(Identifier<C>, Asset<C>),

/// Private Transfer Transaction Data
PrivateTransfer(Vec<(Identifier<C>, Asset<C>)>),

/// To Public Transaction Data
ToPublic(Identifier<C>, Asset<C>),
}

impl<C> TransactionData<C>
where
C: Configuration,
{
/// Returns a vector of [`Identifier`]-[`Asset`] pairs, consuming `self`.
#[inline]
pub fn open(&self) -> Vec<(Identifier<C>, Asset<C>)> {
match self {
TransactionData::ToPrivate(identifier, asset) => {
[(identifier.clone(), asset.clone())].to_vec()
}
TransactionData::PrivateTransfer(identified_assets) => identified_assets.clone(),
TransactionData::ToPublic(identifier, asset) => {
[(identifier.clone(), asset.clone())].to_vec()
}
}
}

/// Reconstructs the [`Utxo`] from `self` and `address`.
#[inline]
pub fn reconstruct_utxo(
&self,
parameters: &Parameters<C>,
address: &Address<C>,
) -> Vec<Utxo<C>> {
self.open()
.into_iter()
.map(|(identifier, asset)| parameters.utxo_reconstruct(&asset, &identifier, address))
.collect()
}

/// Checks the correctness of `self` against `utxos`.
#[inline]
pub fn check_transaction_data(
&self,
parameters: &Parameters<C>,
address: &Address<C>,
utxos: &Vec<Utxo<C>>,
) -> bool
where
Utxo<C>: PartialEq,
{
self.reconstruct_utxo(parameters, address).eq(utxos)
}
}
8 changes: 1 addition & 7 deletions manta-accounting/src/transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,19 +970,13 @@ where
asset_id: has_public_participants(SOURCES, SINKS)
.then(|| compiler.allocate_unknown::<Public, _>()),
sources: (0..SOURCES)
.into_iter()
.map(|_| compiler.allocate_unknown::<Public, _>())
.collect(),
senders: (0..SENDERS)
.into_iter()
.map(|_| compiler.allocate_unknown())
.collect(),
senders: (0..SENDERS).map(|_| compiler.allocate_unknown()).collect(),
receivers: (0..RECEIVERS)
.into_iter()
.map(|_| compiler.allocate_unknown())
.collect(),
sinks: (0..SINKS)
.into_iter()
.map(|_| compiler.allocate_unknown::<Public, _>())
.collect(),
}
Expand Down
19 changes: 18 additions & 1 deletion manta-accounting/src/transfer/utxo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,25 @@ pub trait NoteOpen: AssetType + DeriveDecryptionKey + IdentifierType + NoteType
}
}

/// Derive Address
pub trait DeriveAddress: AddressType {
/// Secret Key Type
type SecretKey;

/// Derives the address corresponding to `secret_key`.
fn derive_address(&self, secret_key: &Self::SecretKey) -> Self::Address;
}

/// Utxo Reconstruction
pub trait UtxoReconstruct: NoteOpen {
pub trait UtxoReconstruct: NoteOpen + DeriveAddress<SecretKey = Self::DecryptionKey> {
/// Builds a [`Utxo`] from `asset`, `identifier` and `address`.
fn utxo_reconstruct(
&self,
asset: &Self::Asset,
identifier: &Self::Identifier,
address: &Self::Address,
) -> Self::Utxo;

/// Checks if `utxo` is consistent with `asset` and `identifier`.
fn utxo_check(
&self,
Expand Down
55 changes: 41 additions & 14 deletions manta-accounting/src/transfer/utxo/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
transfer::utxo::{
self,
auth::{self, DeriveContext, SpendingKey},
DeriveAddress,
},
};
use alloc::vec::Vec;
Expand Down Expand Up @@ -1407,6 +1408,23 @@ where
}
}

impl<C> utxo::DeriveAddress for Parameters<C>
where
C: Configuration<Bool = bool>,
{
type SecretKey = C::Scalar;

#[inline]
fn derive_address(&self, decryption_key: &Self::SecretKey) -> Self::Address {
Address::new(
self.base
.group_generator
.generator()
.scalar_mul(decryption_key, &mut ()),
)
}
}

impl<C> utxo::UtxoReconstruct for Parameters<C>
where
C: Configuration<Bool = bool>,
Expand All @@ -1415,13 +1433,15 @@ where
Asset<C>: Clone + Default,
{
#[inline]
fn utxo_check(
fn utxo_reconstruct(
&self,
utxo: &Self::Utxo,
asset: &Self::Asset,
identifier: &Self::Identifier,
decryption_key: &Self::DecryptionKey,
) -> bool {
asset: &Asset<C>,
identifier: &Identifier<C>,
address: &Address<C>,
) -> Utxo<C>
where
Asset<C>: Clone + Default,
{
let associated_data = if identifier.is_transparent {
Visibility::Transparent
} else {
Expand All @@ -1431,19 +1451,26 @@ where
&identifier.utxo_commitment_randomness,
&associated_data.secret(asset).id,
&associated_data.secret(asset).value,
&self
.base
.group_generator
.generator()
.scalar_mul(decryption_key, &mut ()),
&address.receiving_key,
&mut (),
);
let new_utxo = Self::Utxo::new(
Utxo::new(
identifier.is_transparent,
associated_data.public(asset),
new_utxo_commitment,
);
new_utxo.eq(utxo, &mut ())
)
}

#[inline]
fn utxo_check(
&self,
utxo: &Self::Utxo,
asset: &Self::Asset,
identifier: &Self::Identifier,
decryption_key: &Self::DecryptionKey,
) -> bool {
self.utxo_reconstruct(asset, identifier, &self.derive_address(decryption_key))
.eq(utxo, &mut ())
}
}

Expand Down
14 changes: 13 additions & 1 deletion manta-accounting/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use crate::{
ledger::ReadResponse,
signer::{
BalanceUpdate, SignError, SignRequest, SignResponse, SyncData, SyncError, SyncRequest,
SyncResponse,
SyncResponse, TransactionDataRequest, TransactionDataResponse,
},
},
};
Expand Down Expand Up @@ -385,6 +385,18 @@ where
.map_err(Error::SignError)
}

/// Attempts to process TransferPosts and returns the corresponding TransactionData.
#[inline]
pub async fn transaction_data(
&mut self,
transfer_posts: Vec<TransferPost<C>>,
) -> Result<TransactionDataResponse<C>, Error<C, L, S>> {
self.signer
.transaction_data(TransactionDataRequest(transfer_posts))
.await
.map_err(Error::SignerConnectionError)
}

/// Posts a transaction to the ledger, returning a success [`Response`] if the `transaction`
/// was successfully posted to the ledger. This method automatically synchronizes with the
/// ledger before posting, _but not after_. To amortize the cost of future calls to [`post`],
Expand Down
Loading