Skip to content

Commit

Permalink
Add 'phoenix-core` to a workspace called phoenix
Browse files Browse the repository at this point in the history
Resolves #171
  • Loading branch information
moCello committed May 16, 2024
1 parent b6c51a1 commit f4e7696
Show file tree
Hide file tree
Showing 35 changed files with 197 additions and 116 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
/target
**/*.rs.bk
/src/main.rs
**/target
Cargo.lock
55 changes: 5 additions & 50 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,51 +1,6 @@
[package]
name = "phoenix-core"
version = "0.27.0"
authors = ["zer0 <matteo@dusk.network>", "Victor Lopez <victor@dusk.network"]
edition = "2021"
repository = "https://github.com/dusk-network/phoenix-core"
description = "Anonymity-preserving zero-knowledge proof-powered transaction model"
license = "MPL-2.0"
exclude = [".github/workflows/dusk-ci.yml", ".gitignore"]

[dependencies]
rand_core = { version = "0.6", default-features = false }
dusk-bytes = "0.1"
dusk-plonk = { version = "0.19", default-features = false, optional = true }
dusk-bls12_381 = { version = "0.13", default-features = false }
bls12_381-bls = { version = "0.3", default-features = false }
dusk-jubjub = { version = "0.14", default-features = false, features = ["zeroize"] }
dusk-poseidon = { version = "0.33", default-features = false }
jubjub-schnorr = { version = "0.3", default-features = false }
subtle = { version = "^2.2.1", default-features = false }
ff = { version = "0.13", default-features = false }
aes-gcm = "0.10"
zeroize = { version = "1", default-features = false, features = ["derive"] }
rkyv = { version = "0.7", optional = true, default-features = false }
bytecheck = { version = "0.6", optional = true, default-features = false }

[dev-dependencies]
assert_matches = "1.3"
rand = "0.8"
rkyv = { version = "0.7", default-features = false, features = ["size_32"] }

[features]
default = [] # "alloc" is suggested as default feature but would be breaking change
alloc = []
rkyv-impl = [
"dusk-poseidon/rkyv-impl",
"dusk-jubjub/rkyv-impl",
"jubjub-schnorr/rkyv-impl",
"dusk-bls12_381/rkyv-impl",
"bls12_381-bls/rkyv-impl",
"rkyv",
"bytecheck"
[workspace]
members = [
"core",
"circuits",
]
zk = [
"dusk-plonk",
]

[[test]]
name = "gadgets"
path = "tests/gadgets.rs"
required-features = ["zk"]
resolver = "2"
30 changes: 7 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
# Phoenix Core
# Phoenix

Phoenix is an anonymity-preserving zero-knowledge proof-powered transaction model formalized and developed by Dusk Network.
Phoenix is the transaction model used by Dusk, an open-source public blockchain with a UTXO-based architecture that allows the execution of obfuscated transactions and confidential smart contracts.

# General

Although somewhat based on the UTXO model utilized in the [Zcash protocol](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf), Phoenix is uniquely capable to enable privacy-preserving smart contract by allowing confidential spending of public output (gas and coinbase transactions).
In privacy-preserving blockchains, there are no accounts or wallets at the protocol layer. Instead, coins are stored as a list of UTXOs with a quantity and some criteria for spending it. In this approach, transactions are created by consuming existing UTXOs and producing new ones in their place. Dusk follows this system, and UTXOs are called notes.

Unlike Zcash, in which transactions can be potentially linked [\[1\]](https://arxiv.org/pdf/1712.01210)[\[2\]](https://orbilu.uni.lu/bitstream/10993/39996/1/Zcash_Miner_Linking%20%282%29.pdf), Phoenix guarantees transaction unlinkability through combining the so-called "obfuscated notes" (i.e. outputs containing encrypted values) with "transparent notes" (i.e. outputs containing plain values) into a single Merkle Tree.
Unlike transparent transaction models, where it is easy to monitor which notes were spent, this task is much harder in a privacy-preserving network, since the details of the notes must be kept hidden. In this case, the network must keep track of all notes ever created by storing their hashes in the leaves of a Merkle tree (called Merkle tree of notes). That is, when a transaction is validated, the network includes the hashes of the new notes to the leaves of this tree.
To prevent double spending, transactions include a list of deterministic values called nullifiers, one for each note being spent, which invalidates these notes.
The idea here is that the nullifier is computed in such a way that an external observer cannot link it to any specific note. This way, when a transaction is accepted, the network knows that some notes are nullified and can no longer be spent, but does not know which ones.

All the transactions utilize one-time keys. It is totally up to the user how he wants to manage his secret key: he could have one or many secret keys for many unspent outputs. The inner Diffie-Hellman key exchange randomness mechanism guarantees the note public key will not repeat for the same spender public key, which causes the identification of the spender to be unfeasible.

For further details, check out the technical paper to be published soon.

# Concepts

## Zero-knowledge

Phoenix uses zero-knowledge proofs to guarantee:

- Transaction balance consistency
- Prevent double-spending attacks
- Prove the ownership of unspent outputs

The set of unspent outputs is a union of obfuscated and transparent note sets. Both notes share a similar structure aside from the obfuscated containing encrypted values and transparent notes containing plain values.

The owner of a note can share his/her `View Key`, allowing a third-party (e.g. a wallet provider) to detect the outputs belonging to the owner as well as the value of the encrypted in the note, in case of an obfuscated note.

The spending of a note can be done only via a `Secret Key`, known only to the owner of the note.
Please refer to the [docs]("docs/protocol-description.pdf") for more detail.
52 changes: 52 additions & 0 deletions circuits/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Add elgamal encryption and decryption gadgets [#171]

### Changed

- Turn `phoenix` into a workspace [#171]

<!-- ISSUES -->
[#171]: https://github.com/dusk-network/phoenix-core/issues/171

<!-- VERSIONS -->
[Unreleased]: https://github.com/dusk-network/phoenix-core/compare/v0.27.0...HEAD
[0.27.0]: https://github.com/dusk-network/phoenix-core/compare/v0.26.0...v0.27.0
[0.26.0]: https://github.com/dusk-network/phoenix-core/compare/v0.25.0...v0.26.0
[0.25.0]: https://github.com/dusk-network/phoenix-core/compare/v0.24.0...v0.25.0
[0.24.0]: https://github.com/dusk-network/phoenix-core/compare/v0.23.0...v0.24.0
[0.23.0]: https://github.com/dusk-network/phoenix-core/compare/v0.22.0...v0.23.0
[0.22.0]: https://github.com/dusk-network/phoenix-core/compare/v0.21.0...v0.22.0
[0.21.0]: https://github.com/dusk-network/phoenix-core/compare/v0.19.0...v0.21.0
[0.19.0]: https://github.com/dusk-network/phoenix-core/compare/v0.18.1...v0.19.0
[0.18.1]: https://github.com/dusk-network/phoenix-core/compare/v0.18.0...v0.18.1
[0.18.0]: https://github.com/dusk-network/phoenix-core/compare/v0.17.1...v0.18.0
[0.17.1]: https://github.com/dusk-network/phoenix-core/compare/v0.17.0...v0.17.1
[0.17.0]: https://github.com/dusk-network/phoenix-core/compare/v0.12.0...v0.17.0
[0.12.0]: https://github.com/dusk-network/phoenix-core/compare/v0.11.0...v0.12.0
[0.11.0]: https://github.com/dusk-network/phoenix-core/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/dusk-network/phoenix-core/compare/v0.9.1...v0.10.0
[0.9.1]: https://github.com/dusk-network/phoenix-core/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/dusk-network/phoenix-core/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/dusk-network/phoenix-core/compare/v0.7.4...v0.8.0
[0.7.4]: https://github.com/dusk-network/phoenix-core/compare/v0.7.3...v0.7.4
[0.7.3]: https://github.com/dusk-network/phoenix-core/compare/v0.7.2...v0.7.3
[0.7.2]: https://github.com/dusk-network/phoenix-core/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/dusk-network/phoenix-core/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/dusk-network/phoenix-core/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/dusk-network/phoenix-core/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/dusk-network/phoenix-core/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/dusk-network/phoenix-core/compare/v0.3.1...v0.5.0
[0.3.1]: https://github.com/dusk-network/phoenix-core/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/dusk-network/phoenix-core/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/dusk-network/phoenix-core/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/dusk-network/phoenix-core/releases/tag/v0.1.0
15 changes: 15 additions & 0 deletions circuits/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "phoenix-circuits"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
phoenix-core = { path = "../core" }
dusk-plonk = { version = "0.19", default-features = false }
dusk-jubjub = { version = "0.14", default-features = false }

[dev-dependencies]
ff = { version = "0.13", default-features = false }
rand_core = { version = "0.6", default-features = false }
11 changes: 11 additions & 0 deletions circuits/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Phoenix Circuits

Phoenix is the transaction model used by Dusk, an open-source public blockchain with a UTXO-based architecture that allows the execution of obfuscated transactions and confidential smart contracts.

This library contains the implementation of the Phoenix-circuits, to prove, in zero-knowledge, that the following conditions hold true:

1. Membership: every note that is about to be spent is included in the Merkle tree of notes.
2. Ownership: the sender holds the note secret key for every note that is about to be spent.
3. Nullification: the nullifier is calculated correctly.
4. Minting: the value commitment for the newly minted notes are computed correctly.
5. Balance integrity: the sum of the value of all spent notes is equal to the value of the sum of all minted notes + the gas fee + a crossover, where a crossover refers to funds being transfered to a contract.
12 changes: 4 additions & 8 deletions src/encryption/elgamal.rs → circuits/src/encryption/elgamal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
//! Reference: https://link.springer.com/chapter/10.1007/3-540-39568-7_2

use dusk_jubjub::{JubJubExtended, JubJubScalar, GENERATOR};

#[cfg(feature = "zk")]
use dusk_plonk::prelude::*;

/// Encrypts a JubJubExtended plaintext given a public key and a fresh random
Expand All @@ -27,8 +25,8 @@ pub fn encrypt(
(ciphertext_1, ciphertext_2)
}

/// Decrypts a ciphertext given a secret key,
/// returning a JubJubExtended plaintext
/// Decrypts a ciphertext given a secret key, returning a JubJubExtended
/// plaintext
pub fn decrypt(
secret_key: &JubJubScalar,
ciphertext_1: &JubJubExtended,
Expand All @@ -38,9 +36,8 @@ pub fn decrypt(
ciphertext_2 - ciphertext_1 * secret_key
}

/// Encrypt in-circuit a plaintext WitnessPoint, returning
/// a ciphertext (WitnessPoint, WitnessPoint)
#[cfg(feature = "zk")]
/// Encrypt in-circuit a plaintext WitnessPoint, returning a ciphertext
/// (WitnessPoint, WitnessPoint)
pub fn encrypt_gadget(
composer: &mut Composer,
public_key: WitnessPoint,
Expand All @@ -56,7 +53,6 @@ pub fn encrypt_gadget(

/// Decrypt in-circuit a ciphertext (WitnessPoint, WitnessPoint),
/// returning a plaintext WitnessPoint
#[cfg(feature = "zk")]
pub fn decrypt_gadget(
composer: &mut Composer,
secret_key: Witness,
Expand Down
3 changes: 0 additions & 3 deletions src/encryption/mod.rs → circuits/src/encryption/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,5 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

/// AES symmetric cipher
pub mod aes;

/// ElGamal asymmetric cipher
pub mod elgamal;
17 changes: 17 additions & 0 deletions circuits/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

//! Phoenix's circuits and gadgets.

#![allow(non_snake_case)]
#![deny(missing_docs)]
#![no_std]

/// Encryption algorithm
mod encryption;

/// ElGamal asymmetric cipher
pub use encryption::elgamal;
23 changes: 21 additions & 2 deletions tests/gadgets.rs → circuits/tests/elgamal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,31 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use dusk_jubjub::{JubJubAffine, JubJubScalar, GENERATOR_EXTENDED};
use dusk_plonk::prelude::*;
use ff::Field;
use phoenix_circuits::elgamal;
use phoenix_core::{PublicKey, SecretKey};
use rand_core::OsRng;

use phoenix_core::{elgamal, PublicKey, SecretKey};
#[test]
fn test_elgamal_encrypt_and_decrypt() {
let sk = SecretKey::random(&mut OsRng);
let pk = PublicKey::from(&sk);

use dusk_plonk::prelude::*;
let message = GENERATOR_EXTENDED * JubJubScalar::from(1234u64);

// Encrypt using a fresh random value 'r'
let r = JubJubScalar::random(&mut OsRng);
let (c1, c2) = elgamal::encrypt(pk.A(), &message, &r);

// Assert decryption
let dec_message = elgamal::decrypt(sk.a(), &c1, &c2);
assert_eq!(message, dec_message);

// Assert decryption using an incorrect key
let dec_message_wrong = elgamal::decrypt(sk.b(), &c1, &c2);
assert_ne!(message, dec_message_wrong);
}

static LABEL: &[u8; 12] = b"dusk-network";
const CAPACITY: usize = 13; // capacity required for the setup
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md → core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Restructure `Encryption` module.
- Move phoenix-core into a phoenix workspace [#171]

### Removed

- Remove 'encryption::elgamal' module as it has been added to the 'phoenix-circuits' lib in the same workspace [#171]

## [0.27.0] - 2024-04-24

Expand Down Expand Up @@ -294,9 +299,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Canonical implementation shielded by feature.

<!-- ISSUES -->
[#162]: https://github.com/dusk-network/phoenix-core/issues/162
[#171]: https://github.com/dusk-network/phoenix-core/issues/171
[#166]: https://github.com/dusk-network/phoenix-core/issues/166
[#165]: https://github.com/dusk-network/phoenix-core/issues/165
[#162]: https://github.com/dusk-network/phoenix-core/issues/162
[#156]: https://github.com/dusk-network/phoenix-core/issues/156
[#155]: https://github.com/dusk-network/phoenix-core/issues/155
[#152]: https://github.com/dusk-network/phoenix-core/issues/152
Expand Down
42 changes: 42 additions & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[package]
name = "phoenix-core"
version = "0.27.0"
authors = ["zer0 <matteo@dusk.network>", "Victor Lopez <victor@dusk.network"]
edition = "2021"
repository = "https://github.com/dusk-network/phoenix-core"
description = "Anonymity-preserving zero-knowledge proof-powered transaction model"
license = "MPL-2.0"
exclude = [".github/workflows/dusk-ci.yml", ".gitignore"]

[dependencies]
rand_core = { version = "0.6", default-features = false }
dusk-bytes = "0.1"
dusk-bls12_381 = { version = "0.13", default-features = false }
bls12_381-bls = { version = "0.3", default-features = false }
dusk-jubjub = { version = "0.14", default-features = false, features = ["zeroize"] }
dusk-poseidon = { version = "0.33", default-features = false }
jubjub-schnorr = { version = "0.3", default-features = false }
subtle = { version = "^2.2.1", default-features = false }
ff = { version = "0.13", default-features = false }
aes-gcm = "0.10"
zeroize = { version = "1", default-features = false, features = ["derive"] }
rkyv = { version = "0.7", optional = true, default-features = false }
bytecheck = { version = "0.6", optional = true, default-features = false }

[dev-dependencies]
assert_matches = "1.3"
rand = "0.8"
rkyv = { version = "0.7", default-features = false, features = ["size_32"] }

[features]
default = [] # "alloc" is suggested as default feature but would be breaking change
alloc = []
rkyv-impl = [
"dusk-poseidon/rkyv-impl",
"dusk-jubjub/rkyv-impl",
"jubjub-schnorr/rkyv-impl",
"dusk-bls12_381/rkyv-impl",
"bls12_381-bls/rkyv-impl",
"rkyv",
"bytecheck"
]
5 changes: 5 additions & 0 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Phoenix Core

Phoenix is the transaction model used by Dusk, an open-source public blockchain with a UTXO-based architecture that allows the execution of obfuscated transactions and confidential smart contracts.

This library contains the cryptographic primitives, types and functionalities used in phoenix, except for the zero-knowledge circuits.
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 8 additions & 0 deletions core/src/encryption/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

/// AES symmetric cipher
pub mod aes;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 0 additions & 2 deletions src/lib.rs → core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ mod encryption;

/// AES symmetric cipher
pub use encryption::aes;
/// ElGamal asymmetric cipher
pub use encryption::elgamal;
/// Hash function
pub use keys::hash;
/// Public (Spend) Key
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit f4e7696

Please sign in to comment.