Module 0x1::sigma_protocol_registration
The registration NP relation ($\mathcal{R}_\mathsf{dl}$)
A ZKPoK that the user knows the decryption key corresponding to their encryption key.
\begin{align} \mathcal{R}_\mathsf{dl}\left(\mathsf{ek}; \mathsf{dk}\right) = 1 \Leftrightarrow H = \mathsf{dk} \cdot \mathsf{ek} \end{align}
This is a Schnorr-like proof framed as a homomorphism check:
\begin{align} \underbrace{H}{\mathsf{f}\mathsf{dl}(\mathsf{ek})}
\underbrace{\mathsf{dk} \cdot \mathsf{ek}}{\psi\mathsf{dl}(\mathsf{dk} \mid \mathsf{ek})} \end{align}
- The registration NP relation ($\mathcal{R}_\mathsf{dl}$)
- Struct
Registration - Struct
RegistrationSession - Constants
- Function
assert_registration_statement_is_well_formed - Function
new_session - Function
new_registration_statement - Function
psi - Function
f - Function
assert_verifies
use 0x1::bcs;
use 0x1::chain_id;
use 0x1::confidential_balance;
use 0x1::error;
use 0x1::fungible_asset;
use 0x1::object;
use 0x1::ristretto255;
use 0x1::sigma_protocol_fiat_shamir;
use 0x1::sigma_protocol_proof;
use 0x1::sigma_protocol_representation;
use 0x1::sigma_protocol_representation_vec;
use 0x1::sigma_protocol_statement;
use 0x1::sigma_protocol_statement_builder;
use 0x1::sigma_protocol_utils;
use 0x1::sigma_protocol_witness;
use 0x1::signer;
use 0x1::vector;
Struct Registration
Phantom marker type for registration statements.
struct Registration has drop
Fields
-
dummy_field: bool
Struct RegistrationSession
Used for domain separation in the Fiat-Shamir transform.
struct RegistrationSession has drop
Fields
-
sender: address -
asset_type: object::Object<fungible_asset::Metadata>
Constants
The number of scalars $k$ in a $\mathcal{R}_\mathsf{dl}$ secret witness. WARNING: Crucial for security.
const K: u64 = 1;
The homomorphism or transformation function implementation is not inserting points at the expected positions.
const E_STATEMENT_BUILDER_INCONSISTENCY: u64 = 6;
Index of $\mathsf{dk}$ (the user’s decryption key) in the witness’s scalars vector.
const IDX_DK: u64 = 0;
Index of $\mathsf{ek}$ (the user’s encryption key) in the statement’s points vector.
const IDX_EK: u64 = 1;
Index of $H$ (the encryption key basepoint) in the statement’s points vector.
const IDX_H: u64 = 0;
Protocol ID used for domain separation
const PROTOCOL_ID: vector<u8> = [65, 112, 116, 111, 115, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 65, 115, 115, 101, 116, 47, 82, 101, 103, 105, 115, 116, 114, 97, 116, 105, 111, 110, 86, 49];
The registration proof was invalid
const E_INVALID_REGISTRATION_PROOF: u64 = 5;
The number of points $m$ in the image of the $\mathcal{R}_\mathsf{dl}$ homomorphism and transformation function. WARNING: Crucial for security.
const M: u64 = 1;
The number of points $n_1$ in a $\mathcal{R}_\mathsf{dl}$ public statement. WARNING: Crucial for security.
const N_1: u64 = 2;
The number of scalars $n_2$ in a $\mathcal{R}_\mathsf{dl}$ public statement. WARNING: Crucial for security.
const N_2: u64 = 0;
Function assert_registration_statement_is_well_formed
Ensures the statement has N_1 points and N_2 scalars.
fun assert_registration_statement_is_well_formed(stmt: &sigma_protocol_statement::Statement<sigma_protocol_registration::Registration>)
Implementation
fun assert_registration_statement_is_well_formed(stmt: &Statement<Registration>) {
assert!(stmt.get_points().length() == N_1, e_wrong_num_points());
assert!(stmt.get_scalars().length() == N_2, e_wrong_num_scalars());
}
Function new_session
public(friend) fun new_session(sender: &signer, asset_type: object::Object<fungible_asset::Metadata>): sigma_protocol_registration::RegistrationSession
Implementation
public(friend) fun new_session(sender: &signer, asset_type: Object<Metadata>): RegistrationSession {
RegistrationSession {
sender: signer::address_of(sender),
asset_type,
}
}
Function new_registration_statement
Creates a new registration statement: $(H, \mathsf{ek})$.
H is computed internally via get_encryption_key_basepoint_compressed().
ek is decompressed internally from compressed_ek.
public(friend) fun new_registration_statement(compressed_ek: ristretto255::CompressedRistretto): sigma_protocol_statement::Statement<sigma_protocol_registration::Registration>
Implementation
public(friend) fun new_registration_statement(
compressed_ek: CompressedRistretto,
): Statement<Registration> {
let b = new_builder();
assert!(b.add_point(get_encryption_key_basepoint_compressed()) == IDX_H, error::internal(E_STATEMENT_BUILDER_INCONSISTENCY)); // H
assert!(b.add_point(compressed_ek) == IDX_EK, error::internal(E_STATEMENT_BUILDER_INCONSISTENCY)); // ek
let stmt = b.build();
assert_registration_statement_is_well_formed(&stmt);
stmt
}
Function psi
The homomorphism $\psi_\mathsf{dl}(\mathsf{dk} \mid \mathsf{ek}) = \mathsf{dk} \cdot \mathsf{ek}$.
fun psi(stmt: &sigma_protocol_statement::Statement<sigma_protocol_registration::Registration>, w: &sigma_protocol_witness::Witness): sigma_protocol_representation_vec::RepresentationVec
Implementation
fun psi(stmt: &Statement<Registration>, w: &Witness): RepresentationVec {
// WARNING: Crucial for security
assert_registration_statement_is_well_formed(stmt);
// WARNING: Crucial for security
assert!(w.length() == K, e_wrong_witness_len());
let dk = *w.get(IDX_DK);
let reprs = (vector[
// dk * ek
repr_scaled(IDX_EK, dk),
]);
// WARNING: Crucial for security
assert!(reprs.length() == M, e_wrong_output_len());
new_representation_vec(reprs)
}
Function f
The transformation function $\mathsf{f}_\mathsf{dl}(\mathsf{ek}) = H$.
fun f(_stmt: &sigma_protocol_statement::Statement<sigma_protocol_registration::Registration>): sigma_protocol_representation_vec::RepresentationVec
Implementation
fun f(_stmt: &Statement<Registration>): RepresentationVec {
// We do not re-assert well-formedness since wherever f is called, psi is also called.
new_representation_vec(vector[
// H
repr_point(IDX_H),
])
}
Function assert_verifies
Asserts that a registration proof verifies.
public(friend) fun assert_verifies(self: &sigma_protocol_registration::RegistrationSession, stmt: &sigma_protocol_statement::Statement<sigma_protocol_registration::Registration>, proof: &sigma_protocol_proof::Proof)
Implementation
public(friend) fun assert_verifies(self: &RegistrationSession, stmt: &Statement<Registration>, proof: &Proof) {
let success = sigma_protocol::verify(
new_domain_separator(@aptos_framework, chain_id::get(), PROTOCOL_ID, bcs::to_bytes(self)),
|_X, w| psi(_X, w),
|_X| f(_X),
stmt,
proof
);
assert!(success, error::invalid_argument(E_INVALID_REGISTRATION_PROOF));
}