Skip to content

Commit

Permalink
Curve25519 syscall group ops (#25071)
Browse files Browse the repository at this point in the history
* zk-token-sdk: implement group ops trait for curve25519

* zk-token-sdk: extend syscall trait implementation for group ops for ristretto

* zk-token-sdk: register curve25519 group ops to bpf loader

* zk-token-sdk: update curve25519_syscall_enabled address
  • Loading branch information
samkim-crypto committed May 8, 2022
1 parent e6c02f3 commit aba6a89
Show file tree
Hide file tree
Showing 6 changed files with 439 additions and 11 deletions.
24 changes: 21 additions & 3 deletions program-runtime/src/compute_budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,22 @@ pub struct ComputeBudget {
pub syscall_base_cost: u64,
/// Number of compute units consumed to call zktoken_crypto_op
pub zk_token_elgamal_op_cost: u64, // to be replaced by curve25519 operations
/// Number of compute units consumed to add/sub two edwards points
/// Number of compute units consumed to validate a curve25519 edwards point
pub curve25519_edwards_validate_point_cost: u64,
/// Number of compute units consumed to add/sub two ristretto points
/// Number of compute units consumed to add two curve25519 edwards points
pub curve25519_edwards_add_cost: u64,
/// Number of compute units consumed to subtract two curve25519 edwards points
pub curve25519_edwards_subtract_cost: u64,
/// Number of compute units consumed to multiply a curve25519 edwards point
pub curve25519_edwards_multiply_cost: u64,
/// Number of compute units consumed to validate a curve25519 ristretto point
pub curve25519_ristretto_validate_point_cost: u64,
/// Number of compute units consumed to add two curve25519 ristretto points
pub curve25519_ristretto_add_cost: u64,
/// Number of compute units consumed to subtract two curve25519 ristretto points
pub curve25519_ristretto_subtract_cost: u64,
/// Number of compute units consumed to multiply a curve25519 ristretto point
pub curve25519_ristretto_multiply_cost: u64,
/// Optional program heap region size, if `None` then loader default
pub heap_size: Option<usize>,
/// Number of compute units per additional 32k heap above the default (~.5
Expand Down Expand Up @@ -96,8 +108,14 @@ impl ComputeBudget {
secp256k1_recover_cost: 25_000,
syscall_base_cost: 100,
zk_token_elgamal_op_cost: 25_000,
curve25519_edwards_validate_point_cost: 25_000, // TODO: precisely determine cost
curve25519_edwards_validate_point_cost: 25_000, // TODO: precisely determine curve25519 costs
curve25519_edwards_add_cost: 25_000,
curve25519_edwards_subtract_cost: 25_000,
curve25519_edwards_multiply_cost: 25_000,
curve25519_ristretto_validate_point_cost: 25_000,
curve25519_ristretto_add_cost: 25_000,
curve25519_ristretto_subtract_cost: 25_000,
curve25519_ristretto_multiply_cost: 25_000,
heap_size: None,
heap_cost: 8,
mem_op_base_cost: 10,
Expand Down
265 changes: 265 additions & 0 deletions programs/bpf_loader/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,13 @@ pub fn register_syscalls(
SyscallCurvePointValidation::init,
SyscallCurvePointValidation::call,
)?;
register_feature_gated_syscall!(
syscall_registry,
curve25519_syscall_enabled,
b"sol_curve25519_point_validation",
SyscallCurveGroupOps::init,
SyscallCurveGroupOps::call,
)?;

// Sysvars
syscall_registry.register_syscall_by_name(
Expand Down Expand Up @@ -1979,6 +1986,264 @@ declare_syscall!(
}
);

declare_syscall!(
// Elliptic Curve Group Operations
//
// Currently, only curve25519 Edwards and Ristretto representations are supported
SyscallCurveGroupOps,
fn call(
&mut self,
curve_id: u64,
group_op: u64,
left_input_addr: u64,
right_input_addr: u64,
result_point_addr: u64,
memory_mapping: &MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
use solana_zk_token_sdk::curve25519::{
curve_syscall_traits::*, edwards, ristretto, scalar,
};

let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);

match curve_id {
CURVE25519_EDWARDS => match group_op {
ADD => {
let cost = invoke_context
.get_compute_budget()
.curve25519_edwards_add_cost;
question_mark!(invoke_context.get_compute_meter().consume(cost), result);

let left_point = question_mark!(
translate_type::<edwards::PodEdwardsPoint>(
memory_mapping,
left_input_addr,
invoke_context.get_check_aligned(),
),
result
);
let right_point = question_mark!(
translate_type::<edwards::PodEdwardsPoint>(
memory_mapping,
right_input_addr,
invoke_context.get_check_aligned(),
),
result
);

if let Some(result_point) = edwards::add_edwards(left_point, right_point) {
*question_mark!(
translate_type_mut::<edwards::PodEdwardsPoint>(
memory_mapping,
result_point_addr,
invoke_context.get_check_aligned(),
),
result
) = result_point;
*result = Ok(0);
}
}
SUB => {
let cost = invoke_context
.get_compute_budget()
.curve25519_edwards_subtract_cost;
question_mark!(invoke_context.get_compute_meter().consume(cost), result);

let left_point = question_mark!(
translate_type::<edwards::PodEdwardsPoint>(
memory_mapping,
left_input_addr,
invoke_context.get_check_aligned(),
),
result
);
let right_point = question_mark!(
translate_type::<edwards::PodEdwardsPoint>(
memory_mapping,
right_input_addr,
invoke_context.get_check_aligned(),
),
result
);

if let Some(result_point) = edwards::subtract_edwards(left_point, right_point) {
*question_mark!(
translate_type_mut::<edwards::PodEdwardsPoint>(
memory_mapping,
result_point_addr,
invoke_context.get_check_aligned(),
),
result
) = result_point;
*result = Ok(0);
}
}
MUL => {
let cost = invoke_context
.get_compute_budget()
.curve25519_edwards_multiply_cost;
question_mark!(invoke_context.get_compute_meter().consume(cost), result);

let scalar = question_mark!(
translate_type::<scalar::PodScalar>(
memory_mapping,
left_input_addr,
invoke_context.get_check_aligned(),
),
result
);
let input_point = question_mark!(
translate_type::<edwards::PodEdwardsPoint>(
memory_mapping,
right_input_addr,
invoke_context.get_check_aligned(),
),
result
);

if let Some(result_point) = edwards::multiply_edwards(scalar, input_point) {
*question_mark!(
translate_type_mut::<edwards::PodEdwardsPoint>(
memory_mapping,
result_point_addr,
invoke_context.get_check_aligned(),
),
result
) = result_point;
*result = Ok(0);
}
}
_ => {
*result = Ok(1);
}
},

CURVE25519_RISTRETTO => match group_op {
ADD => {
let cost = invoke_context
.get_compute_budget()
.curve25519_ristretto_add_cost;
question_mark!(invoke_context.get_compute_meter().consume(cost), result);

let left_point = question_mark!(
translate_type::<ristretto::PodRistrettoPoint>(
memory_mapping,
left_input_addr,
invoke_context.get_check_aligned(),
),
result
);
let right_point = question_mark!(
translate_type::<ristretto::PodRistrettoPoint>(
memory_mapping,
right_input_addr,
invoke_context.get_check_aligned(),
),
result
);

if let Some(result_point) = ristretto::add_ristretto(left_point, right_point) {
*question_mark!(
translate_type_mut::<ristretto::PodRistrettoPoint>(
memory_mapping,
result_point_addr,
invoke_context.get_check_aligned(),
),
result
) = result_point;
*result = Ok(0);
}
}
SUB => {
let cost = invoke_context
.get_compute_budget()
.curve25519_ristretto_subtract_cost;
question_mark!(invoke_context.get_compute_meter().consume(cost), result);

let left_point = question_mark!(
translate_type::<ristretto::PodRistrettoPoint>(
memory_mapping,
left_input_addr,
invoke_context.get_check_aligned(),
),
result
);
let right_point = question_mark!(
translate_type::<ristretto::PodRistrettoPoint>(
memory_mapping,
right_input_addr,
invoke_context.get_check_aligned(),
),
result
);

if let Some(result_point) =
ristretto::subtract_ristretto(left_point, right_point)
{
*question_mark!(
translate_type_mut::<ristretto::PodRistrettoPoint>(
memory_mapping,
result_point_addr,
invoke_context.get_check_aligned(),
),
result
) = result_point;
*result = Ok(0);
}
}
MUL => {
let cost = invoke_context
.get_compute_budget()
.curve25519_ristretto_multiply_cost;
question_mark!(invoke_context.get_compute_meter().consume(cost), result);

let scalar = question_mark!(
translate_type::<scalar::PodScalar>(
memory_mapping,
left_input_addr,
invoke_context.get_check_aligned(),
),
result
);
let input_point = question_mark!(
translate_type::<ristretto::PodRistrettoPoint>(
memory_mapping,
right_input_addr,
invoke_context.get_check_aligned(),
),
result
);

if let Some(result_point) = ristretto::multiply_ristretto(scalar, input_point) {
*question_mark!(
translate_type_mut::<ristretto::PodRistrettoPoint>(
memory_mapping,
result_point_addr,
invoke_context.get_check_aligned(),
),
result
) = result_point;
*result = Ok(0);
}
}
_ => {
*result = Ok(1);
}
},

_ => {
*result = Ok(1);
}
}
}
);

declare_syscall!(
// Blake3
SyscallBlake3,
Expand Down
3 changes: 1 addition & 2 deletions sdk/src/feature_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,8 @@ pub mod zk_token_sdk_enabled {
solana_sdk::declare_id!("zk1snxsc6Fh3wsGNbbHAJNHiJoYgF29mMnTSusGx5EJ");
}

// TODO: temporary address for now
pub mod curve25519_syscall_enabled {
solana_sdk::declare_id!("curve25519111111111111111111111111111111111");
solana_sdk::declare_id!("7rcw5UtqgDTBBv2EcynNfYckgdAaH1MAsCjKgXMkN7Ri");
}

pub mod versioned_tx_message_enabled {
Expand Down
17 changes: 14 additions & 3 deletions zk-token-sdk/src/curve25519/curve_syscall_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,20 @@ pub const MUL: u64 = 2;
extern "C" {
pub fn sol_curve_validate_point(curve_id: u64, point: *const u8, result: *mut u8) -> u64;

pub fn sol_curve_op(curve_id: u64, op_id: u64, point: *const u8, result: *mut u8) -> u64;

pub fn sol_curve_multiscalar_mul(curve_id: u64, point: *const u8, result: *mut u8) -> u64;
pub fn sol_curve_op(
curve_id: u64,
op_id: u64,
left_point: *const u8,
right_point: *const u8,
result: *mut u8,
) -> u64;

pub fn sol_curve_multiscalar_mul(
curve_id: u64,
scalars: *const u8,
points: *const u8,
result: *mut u8,
) -> u64;

pub fn sol_curve_pairing_map(curve_id: u64, point: *const u8, result: *mut u8) -> u64;
}
Loading

0 comments on commit aba6a89

Please sign in to comment.