1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2024 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//! This module implements the client-side API for this contract's interaction.
//! What we basically do here is implement an API that creates the necessary
//! structures and is able to export them to create a DarkFi transaction
//! object that can be broadcasted to the network when we want to make a
//! payment with some coins in our wallet.
//!
//! Note that this API does not involve any wallet interaction, but only takes
//! the necessary objects provided by the caller. This is intentional, so we
//! are able to abstract away any wallet interfaces to client implementations.
use std::hash::{Hash, Hasher};
use darkfi_sdk::{
bridgetree,
crypto::{
pasta_prelude::{Field, PrimeField},
poseidon_hash, BaseBlind, Blind, FuncId, ScalarBlind, SecretKey,
},
pasta::pallas,
};
use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
use crate::model::{Coin, Nullifier, TokenId};
/// `Money::FeeV1` API
pub mod fee_v1;
/// `Money::GenesisMintV1` API
pub mod genesis_mint_v1;
/// `Money::PoWRewardV1` API
pub mod pow_reward_v1;
/// `Money::TransferV1` API
pub mod transfer_v1;
/// `Money::OtcSwapV1` API
pub mod swap_v1;
/// `Money::AuthTokenMintV1` API
pub mod auth_token_mint_v1;
/// `Money::AuthTokenFreezeV1` API
pub mod auth_token_freeze_v1;
/// `Money::TokenMintV1` API
pub mod token_mint_v1;
/// `MoneyNote` holds the inner attributes of a `Coin`.
///
/// It does not store the public key since it's encrypted for that key,
/// and so is not needed to infer the coin attributes.
/// All other coin attributes must be present.
#[derive(Debug, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
pub struct MoneyNote {
/// Value of the coin
pub value: u64,
/// Token ID of the coin
pub token_id: TokenId,
/// Spend hook used for protocol-owned liquidity.
/// Specifies which contract owns this coin.
pub spend_hook: FuncId,
/// User data used by protocol when spend hook is enabled
pub user_data: pallas::Base,
/// Blinding factor for the coin
pub coin_blind: BaseBlind,
// TODO: look into removing these fields. We potentially don't need them [
/// Blinding factor for the value pedersen commitment
pub value_blind: ScalarBlind,
/// Blinding factor for the token ID pedersen commitment
pub token_blind: BaseBlind,
// ] ^ the receiver is not interested in the value commit / token commits.
// we just want to examine the coins in the outputs. The money::transfer() contract
// should ensure everything else is correct.
/// Attached memo (arbitrary data)
pub memo: Vec<u8>,
}
/// `OwnCoin` is a representation of `Coin` with its respective metadata.
#[derive(Debug, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
pub struct OwnCoin {
/// The coin hash
pub coin: Coin,
/// The attached `MoneyNote`
pub note: MoneyNote,
/// Coin's secret key
pub secret: SecretKey,
/// Coin's leaf position in the Merkle tree of coins
pub leaf_position: bridgetree::Position,
}
impl OwnCoin {
/// Derive the [`Nullifier`] for this [`OwnCoin`]
pub fn nullifier(&self) -> Nullifier {
Nullifier::from(poseidon_hash([self.secret.inner(), self.coin.inner()]))
}
}
impl Hash for OwnCoin {
fn hash<H: Hasher>(&self, state: &mut H) {
self.coin.inner().to_repr().hash(state);
}
}
pub fn compute_remainder_blind(
input_blinds: &[ScalarBlind],
output_blinds: &[ScalarBlind],
) -> ScalarBlind {
let mut total = pallas::Scalar::ZERO;
for input_blind in input_blinds {
total += input_blind.inner();
}
for output_blind in output_blinds {
total -= output_blind.inner();
}
Blind(total)
}