Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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}

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));
}