Skip to content

Commit

Permalink
core: add RecipientParameters to TxSkeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
Eduardo Leegwater Simões committed Jun 13, 2024
1 parent 89456f1 commit 98e1947
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 4 deletions.
3 changes: 3 additions & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Implement `rkyv` traits for `RecipientParameters`
- Implement `dusk_bytes::Serializable` for `RecipientParameters`
- Add `RecipientParameters`
- Add `elgamal::encrypt` and `elgamal::decrypt`
- Add `stealth_address` and `sync_address` functions directly to note [#208]
Expand All @@ -18,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Include `recipient_params` field in `TxSkeleton`
- Move `OUTPUT_NOTES` to crate root
- Change `owns` and `owns_unchecked` to take `&Note` [#208]
- Change `gen_note_sk` to take `&StealthAddress` [#208]
Expand Down
110 changes: 109 additions & 1 deletion core/src/recipient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@
#![allow(non_snake_case)]

use dusk_bls12_381::BlsScalar;
use dusk_bytes::{DeserializableSlice, Serializable};
use dusk_jubjub::{JubJubAffine, JubJubExtended, JubJubScalar};
use ff::Field;
use jubjub_schnorr::{SecretKey as SchnorrSecretKey, Signature};
use rand::{CryptoRng, RngCore};

#[cfg(feature = "rkyv-impl")]
use rkyv::{Archive, Deserialize, Serialize};

use crate::{encryption::elgamal, PublicKey, SecretKey, OUTPUT_NOTES};

/// Parameters needed to prove a recipient in-circuit
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(
feature = "rkyv-impl",
derive(Archive, Serialize, Deserialize),
archive_attr(derive(bytecheck::CheckBytes))
)]
pub struct RecipientParameters {
/// Public key of the transaction sender
pub sender_pk: PublicKey,
Expand Down Expand Up @@ -53,6 +62,105 @@ impl Default for RecipientParameters {
}
}

const PARAMS_SIZE: usize = PublicKey::SIZE
+ JubJubAffine::SIZE * OUTPUT_NOTES
+ Signature::SIZE * OUTPUT_NOTES
+ JubJubAffine::SIZE * 2 * OUTPUT_NOTES
+ JubJubAffine::SIZE * 2 * OUTPUT_NOTES
+ JubJubScalar::SIZE * OUTPUT_NOTES
+ JubJubScalar::SIZE * OUTPUT_NOTES;

impl Serializable<PARAMS_SIZE> for RecipientParameters {
type Error = dusk_bytes::Error;

fn from_bytes(buf: &[u8; PARAMS_SIZE]) -> Result<Self, Self::Error>
where
Self: Sized,
{
let mut reader = &buf[..];

let sender_pk = PublicKey::from_reader(&mut reader)?;

let output_npk_0 = JubJubAffine::from_reader(&mut reader)?;
let output_npk_1 = JubJubAffine::from_reader(&mut reader)?;

let sig_0 = Signature::from_reader(&mut reader)?;
let sig_1 = Signature::from_reader(&mut reader)?;

let enc_A_0_0 = JubJubAffine::from_reader(&mut reader)?;
let enc_A_1_0 = JubJubAffine::from_reader(&mut reader)?;
let enc_A_0_1 = JubJubAffine::from_reader(&mut reader)?;
let enc_A_1_1 = JubJubAffine::from_reader(&mut reader)?;

let enc_B_0_0 = JubJubAffine::from_reader(&mut reader)?;
let enc_B_1_0 = JubJubAffine::from_reader(&mut reader)?;
let enc_B_0_1 = JubJubAffine::from_reader(&mut reader)?;
let enc_B_1_1 = JubJubAffine::from_reader(&mut reader)?;

let r_A_0 = JubJubScalar::from_reader(&mut reader)?;
let r_A_1 = JubJubScalar::from_reader(&mut reader)?;

let r_B_0 = JubJubScalar::from_reader(&mut reader)?;
let r_B_1 = JubJubScalar::from_reader(&mut reader)?;

Ok(Self {
sender_pk,
output_npk: [output_npk_0, output_npk_1],
sig: [sig_0, sig_1],
enc_A: [
(enc_A_0_0.into(), enc_A_1_0.into()),
(enc_A_0_1.into(), enc_A_1_1.into()),
],
enc_B: [
(enc_B_0_0.into(), enc_B_1_0.into()),
(enc_B_0_1.into(), enc_B_1_1.into()),
],
r_A: [r_A_0, r_A_1],
r_B: [r_B_0, r_B_1],
})
}

fn to_bytes(&self) -> [u8; PARAMS_SIZE] {
let mut bytes = [0u8; PARAMS_SIZE];

bytes[0..64].copy_from_slice(&self.sender_pk.to_bytes());

bytes[64..96].copy_from_slice(&self.output_npk[0].to_bytes());
bytes[96..128].copy_from_slice(&self.output_npk[1].to_bytes());

bytes[128..192].copy_from_slice(&self.sig[0].to_bytes());
bytes[192..256].copy_from_slice(&self.sig[1].to_bytes());

let enc_A_0_0 = JubJubAffine::from(self.enc_A[0].0);
let enc_A_1_0 = JubJubAffine::from(self.enc_A[0].1);
let enc_A_0_1 = JubJubAffine::from(self.enc_A[1].0);
let enc_A_1_1 = JubJubAffine::from(self.enc_A[1].1);

bytes[256..288].copy_from_slice(&enc_A_0_0.to_bytes());
bytes[288..320].copy_from_slice(&enc_A_1_0.to_bytes());
bytes[320..352].copy_from_slice(&enc_A_0_1.to_bytes());
bytes[352..384].copy_from_slice(&enc_A_1_1.to_bytes());

let enc_B_0_0 = JubJubAffine::from(self.enc_B[0].0);
let enc_B_1_0 = JubJubAffine::from(self.enc_B[0].1);
let enc_B_0_1 = JubJubAffine::from(self.enc_B[1].0);
let enc_B_1_1 = JubJubAffine::from(self.enc_B[1].1);

bytes[384..416].copy_from_slice(&enc_B_0_0.to_bytes());
bytes[416..448].copy_from_slice(&enc_B_1_0.to_bytes());
bytes[448..480].copy_from_slice(&enc_B_0_1.to_bytes());
bytes[480..512].copy_from_slice(&enc_B_1_1.to_bytes());

bytes[512..544].copy_from_slice(&self.r_A[0].to_bytes());
bytes[544..576].copy_from_slice(&self.r_A[1].to_bytes());

bytes[576..608].copy_from_slice(&self.r_B[0].to_bytes());
bytes[608..640].copy_from_slice(&self.r_B[1].to_bytes());

bytes
}
}

impl RecipientParameters {
/// Create the recipient parameter
pub fn new(
Expand Down
10 changes: 8 additions & 2 deletions core/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use rkyv::{Archive, Deserialize, Serialize};
use dusk_bls12_381::BlsScalar;
use dusk_bytes::{DeserializableSlice, Error as BytesError, Serializable};

use crate::{Note, OUTPUT_NOTES};
use crate::{Note, RecipientParameters, OUTPUT_NOTES};

/// A phoenix transaction, referred to as tx-skeleton in the specs.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "rkyv-impl",
derive(Archive, Serialize, Deserialize),
Expand All @@ -37,6 +37,8 @@ pub struct TxSkeleton {
pub tx_max_fee: u64,
/// A deposit is used to transferring funds to a contract
pub deposit: u64,
/// Parameters needed to prove a recipient in-circuit
pub recipient_params: RecipientParameters,
}

impl TxSkeleton {
Expand All @@ -56,6 +58,7 @@ impl TxSkeleton {

bytes.extend(self.tx_max_fee.to_bytes());
bytes.extend(self.deposit.to_bytes());
bytes.extend(self.recipient_params.to_bytes());

bytes
}
Expand All @@ -80,6 +83,7 @@ impl TxSkeleton {

bytes.extend(self.tx_max_fee.to_bytes());
bytes.extend(self.deposit.to_bytes());
bytes.extend(self.recipient_params.to_bytes());

bytes
}
Expand All @@ -104,13 +108,15 @@ impl TxSkeleton {

let tx_max_fee = u64::from_reader(&mut buffer)?;
let deposit = u64::from_reader(&mut buffer)?;
let recipient_params = RecipientParameters::from_reader(&mut buffer)?;

Ok(Self {
root,
nullifiers,
outputs,
tx_max_fee,
deposit,
recipient_params,
})
}

Expand Down
6 changes: 5 additions & 1 deletion core/tests/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
use dusk_bls12_381::BlsScalar;
use dusk_jubjub::JubJubScalar;
use ff::Field;
use phoenix_core::{Error, Note, PublicKey, SecretKey, TxSkeleton};
use phoenix_core::{
Error, Note, PublicKey, RecipientParameters, SecretKey, TxSkeleton,
};
use rand::rngs::OsRng;

#[test]
Expand All @@ -28,13 +30,15 @@ fn transaction_parse() -> Result<(), Error> {
let outputs = [note.clone(), note];
let tx_max_fee = 0;
let deposit = 0;
let recipient_params = RecipientParameters::default();

let tx_skeleton = TxSkeleton {
root,
nullifiers,
outputs,
tx_max_fee,
deposit,
recipient_params,
};
let bytes_of_transaction = tx_skeleton.to_var_bytes();
assert_eq!(
Expand Down

0 comments on commit 98e1947

Please sign in to comment.