New Native Operation PublicKeyOf (#355)
* wrote some initial code * added way to input private key into circuit * TypedValue::SecretKey hashed as 10 32-bit limbs * Check PublicKeyOf in Frontend and Middleware * Diff review * PR review * Finish utest * Fix bounds check * added giving secret key witness to circuit * Test & doc improvements * added private key comparison to circuit and added test cases * cargo fmt * Add frontend tests for PublicKeyOf * Add public_key_of and hash_of to op! macro * Add ownership check to ticket example * Group order checking in tests * More negative test cases at circuit level * Cleanups after self review * clippy fixes * Fixes after merge. Temporarily remove plonky2 commit hash * Add a nullifier to the ticket test example * Test PublicKeyOf with a real prover (not mock) * plonky-u32 dependency * feat: optimize operation checks Skip the circuits that verify operation checks other than None, Copy or NewEntry for the public statements. This works because public statements are created by copying private statements, so we never use the other operation checks in those slots. --------- Co-authored-by: Andrew Twyman <artwyman@gmail.com> Co-authored-by: Eduard S. <eduardsanou@posteo.net>
This commit is contained in:
parent
9f8335756c
commit
5b04b2a360
15 changed files with 958 additions and 76 deletions
|
|
@ -1,6 +1,7 @@
|
|||
use std::{array, iter, sync::Arc};
|
||||
|
||||
use itertools::{izip, zip_eq, Itertools};
|
||||
use num::{BigUint, One};
|
||||
use plonky2::{
|
||||
field::types::Field,
|
||||
hash::{
|
||||
|
|
@ -14,6 +15,7 @@ use plonky2::{
|
|||
},
|
||||
plonk::config::AlgebraicHasher,
|
||||
};
|
||||
use plonky2_u32::gadgets::multiple_comparison::list_le_circuit;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -31,9 +33,15 @@ use crate::{
|
|||
},
|
||||
emptypod::{cache_get_standard_empty_pod_circuit_data, EmptyPod},
|
||||
error::Result,
|
||||
mainpod::{self, pad_statement},
|
||||
primitives::merkletree::{
|
||||
verify_merkle_proof_circuit, MerkleClaimAndProof, MerkleClaimAndProofTarget,
|
||||
mainpod::{self, pad_statement, OperationArg},
|
||||
primitives::{
|
||||
ec::{
|
||||
bits::{BigUInt320Target, CircuitBuilderBits},
|
||||
curve::{CircuitBuilderElliptic, Point, WitnessWriteCurve, GROUP_ORDER},
|
||||
},
|
||||
merkletree::{
|
||||
verify_merkle_proof_circuit, MerkleClaimAndProof, MerkleClaimAndProofTarget,
|
||||
},
|
||||
},
|
||||
recursion::{InnerCircuit, VerifiedProofTarget},
|
||||
signedpod::SignedPod,
|
||||
|
|
@ -41,11 +49,10 @@ use crate::{
|
|||
measure_gates_begin, measure_gates_end,
|
||||
middleware::{
|
||||
AnchoredKey, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, NativeOperation,
|
||||
NativePredicate, Params, PodType, PredicatePrefix, Statement, StatementArg, ToFields,
|
||||
Value, ValueRef, F, HASH_SIZE, KEY_TYPE, SELF, VALUE_SIZE,
|
||||
NativePredicate, OperationType, Params, PodType, PredicatePrefix, Statement, StatementArg,
|
||||
ToFields, TypedValue, Value, ValueRef, F, HASH_SIZE, KEY_TYPE, SELF, VALUE_SIZE,
|
||||
},
|
||||
};
|
||||
|
||||
//
|
||||
// MainPod verification
|
||||
//
|
||||
|
|
@ -137,6 +144,47 @@ impl StatementCache {
|
|||
}
|
||||
}
|
||||
|
||||
/// Specialized implementation of `verify_operation_circuit` for operations that generate public
|
||||
/// statement. This only allows operations to be None, NewEntry or Copy and accounts for the fact
|
||||
/// that public statements in the current implementation are always generated by copying private
|
||||
/// statements (or NewEntry for the `KEY_TYPE` public entry).
|
||||
fn verify_operation_public_statement_circuit(
|
||||
params: &Params,
|
||||
builder: &mut CircuitBuilder,
|
||||
st: &StatementTarget,
|
||||
op: &OperationTarget,
|
||||
prev_statements: &[StatementTarget],
|
||||
input_statements_offset: usize,
|
||||
) -> Result<()> {
|
||||
let measure = measure_gates_begin!(builder, "OpVerify");
|
||||
|
||||
// Verify that the operation `op` correctly generates the statement `st`. The operation
|
||||
// can reference any of the `prev_statements`.
|
||||
// TODO: Clean this up.
|
||||
let measure_resolve_op_args = measure_gates_begin!(builder, "ResolveOpArgs");
|
||||
let cache = StatementCache::new(params, builder, op, st, prev_statements);
|
||||
measure_gates_end!(builder, measure_resolve_op_args);
|
||||
|
||||
let op_checks = vec![
|
||||
verify_none_circuit(params, builder, st, &op.op_type),
|
||||
verify_new_entry_circuit(
|
||||
params,
|
||||
builder,
|
||||
st,
|
||||
&op.op_type,
|
||||
prev_statements,
|
||||
input_statements_offset,
|
||||
),
|
||||
verify_copy_circuit(builder, st, &op.op_type, &cache.op_args),
|
||||
];
|
||||
|
||||
let ok = builder.any(op_checks);
|
||||
builder.assert_one(ok.target);
|
||||
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn verify_operation_circuit(
|
||||
params: &Params,
|
||||
|
|
@ -146,6 +194,7 @@ fn verify_operation_circuit(
|
|||
prev_statements: &[StatementTarget],
|
||||
input_statements_offset: usize,
|
||||
merkle_claims: &[MerkleClaimTarget],
|
||||
secret_key: &BigUInt320Target,
|
||||
custom_predicate_verification_table: &[HashOutTarget],
|
||||
) -> Result<()> {
|
||||
let measure = measure_gates_begin!(builder, "OpVerify");
|
||||
|
|
@ -218,6 +267,7 @@ fn verify_operation_circuit(
|
|||
verify_transitive_eq_circuit(params, builder, st, &op.op_type, &cache.op_args),
|
||||
verify_lt_to_neq_circuit(params, builder, st, &op.op_type, &cache.op_args),
|
||||
verify_hash_of_circuit(params, builder, st, &op.op_type, &cache),
|
||||
verify_public_key_of_circuit(params, builder, st, &op.op_type, secret_key, &cache),
|
||||
verify_sum_of_circuit(params, builder, st, &op.op_type, &cache),
|
||||
verify_product_of_circuit(params, builder, st, &op.op_type, &cache),
|
||||
verify_max_of_circuit(params, builder, st, &op.op_type, &cache),
|
||||
|
|
@ -539,6 +589,69 @@ fn verify_hash_of_circuit(
|
|||
ok
|
||||
}
|
||||
|
||||
fn verify_public_key_of_circuit(
|
||||
params: &Params,
|
||||
builder: &mut CircuitBuilder,
|
||||
st: &StatementTarget,
|
||||
op_type: &OperationTypeTarget,
|
||||
secret_key: &BigUInt320Target,
|
||||
cache: &StatementCache,
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpPublicKeyOf");
|
||||
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::PublicKeyOf);
|
||||
let (arg_types_ok, [arg1_value, arg2_value]) = cache.first_n_args_as_values();
|
||||
// inputting public_key, secret_key
|
||||
let public_key_hash = arg1_value.elements;
|
||||
let secret_key_hash = arg2_value.elements;
|
||||
|
||||
let secret_key_hash_v =
|
||||
builder.hash_n_to_hash_no_pad::<PoseidonHash>(secret_key.limbs.to_vec());
|
||||
let skey_hash_ok = builder.is_equal_slice(&secret_key_hash, &secret_key_hash_v.elements);
|
||||
let invgenerator = builder.constant_point(Point::generator().inverse());
|
||||
let secret_key_bits = secret_key.bits;
|
||||
let group_orderm1 = &*GROUP_ORDER - BigUint::one();
|
||||
let group_orderm1target = builder.constant_biguint320(&group_orderm1);
|
||||
let compare_ok = list_le_circuit(
|
||||
builder,
|
||||
secret_key.limbs.to_vec(),
|
||||
group_orderm1target.limbs.to_vec(),
|
||||
32,
|
||||
);
|
||||
// public_key = g^-secret key
|
||||
let public_key = builder.multiply_point(&secret_key_bits, &invgenerator);
|
||||
let public_key_hash_v = builder.hash_n_to_hash_no_pad::<PoseidonHash>(
|
||||
public_key
|
||||
.x
|
||||
.components
|
||||
.into_iter()
|
||||
.chain(public_key.u.components)
|
||||
.collect(),
|
||||
);
|
||||
let pkey_hash_ok = builder.is_equal_slice(&public_key_hash, &public_key_hash_v.elements);
|
||||
|
||||
let arg1_expected = cache.equations[0].lhs.clone();
|
||||
let arg2_expected = cache.equations[1].lhs.clone();
|
||||
let expected_statement = StatementTarget::new_native(
|
||||
builder,
|
||||
params,
|
||||
NativePredicate::PublicKeyOf,
|
||||
&[arg1_expected, arg2_expected],
|
||||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
let ok = builder.all([
|
||||
op_code_ok,
|
||||
arg_types_ok,
|
||||
pkey_hash_ok,
|
||||
skey_hash_ok,
|
||||
compare_ok,
|
||||
st_ok,
|
||||
]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn verify_sum_of_circuit(
|
||||
params: &Params,
|
||||
builder: &mut CircuitBuilder,
|
||||
|
|
@ -1239,8 +1352,8 @@ fn verify_main_pod_circuit(
|
|||
for statement in &main_pod.input_statements {
|
||||
statements.push(statement.clone());
|
||||
}
|
||||
let pub_statements = &main_pod.input_statements
|
||||
[main_pod.input_statements.len() - params.max_public_statements..];
|
||||
let public_statements_offset = main_pod.input_statements.len() - params.max_public_statements;
|
||||
let pub_statements = &main_pod.input_statements[public_statements_offset..];
|
||||
|
||||
// Verify Merkle claim/proof targets
|
||||
let merkle_claims = main_pod
|
||||
|
|
@ -1288,16 +1401,28 @@ fn verify_main_pod_circuit(
|
|||
// 5. Verify input statements
|
||||
for (i, (st, op)) in izip!(&main_pod.input_statements, &main_pod.operations).enumerate() {
|
||||
let prev_statements = &statements[..input_statements_offset + i];
|
||||
verify_operation_circuit(
|
||||
params,
|
||||
builder,
|
||||
st,
|
||||
op,
|
||||
prev_statements,
|
||||
input_statements_offset,
|
||||
&merkle_claims,
|
||||
&custom_predicate_verification_table,
|
||||
)?;
|
||||
if i < public_statements_offset {
|
||||
verify_operation_circuit(
|
||||
params,
|
||||
builder,
|
||||
st,
|
||||
op,
|
||||
prev_statements,
|
||||
input_statements_offset,
|
||||
&merkle_claims,
|
||||
&main_pod.secret_keys[i],
|
||||
&custom_predicate_verification_table,
|
||||
)?;
|
||||
} else {
|
||||
verify_operation_public_statement_circuit(
|
||||
params,
|
||||
builder,
|
||||
st,
|
||||
op,
|
||||
prev_statements,
|
||||
input_statements_offset,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
measure_gates_end!(builder, measure);
|
||||
|
|
@ -1315,6 +1440,7 @@ pub struct MainPodVerifyTarget {
|
|||
input_statements: Vec<StatementTarget>,
|
||||
operations: Vec<OperationTarget>,
|
||||
merkle_proofs: Vec<MerkleClaimAndProofTarget>,
|
||||
secret_keys: Vec<BigUInt320Target>,
|
||||
custom_predicate_batches: Vec<CustomPredicateBatchTarget>,
|
||||
custom_predicate_verifications: Vec<CustomPredicateVerifyEntryTarget>,
|
||||
}
|
||||
|
|
@ -1348,6 +1474,9 @@ impl MainPodVerifyTarget {
|
|||
MerkleClaimAndProofTarget::new_virtual(params.max_depth_mt_containers, builder)
|
||||
})
|
||||
.collect(),
|
||||
secret_keys: (0..params.max_statements)
|
||||
.map(|_| builder.add_virtual_biguint320_target())
|
||||
.collect(),
|
||||
custom_predicate_batches: (0..params.max_custom_predicate_batches)
|
||||
.map(|_| builder.add_virtual_custom_predicate_batch(params))
|
||||
.collect(),
|
||||
|
|
@ -1484,6 +1613,41 @@ impl InnerCircuit for MainPodVerifyTarget {
|
|||
for (i, (st, op)) in zip_eq(&input.statements, &input.operations).enumerate() {
|
||||
self.input_statements[i].set_targets(pw, &self.params, st)?;
|
||||
self.operations[i].set_targets(pw, &self.params, op)?;
|
||||
if matches!(
|
||||
op.op_type(),
|
||||
OperationType::Native(NativeOperation::PublicKeyOf)
|
||||
) {
|
||||
if let StatementArg::Literal(value) = &st.1[1] {
|
||||
if let TypedValue::SecretKey(sk) = value.typed() {
|
||||
pw.set_biguint320_target(&self.secret_keys[i], &sk.0)?;
|
||||
} else {
|
||||
panic!("SecretKey literal of incorrect type!")
|
||||
}
|
||||
} else if let OperationArg::Index(ind) = op.1[1] {
|
||||
// TODO: This adjustment only works if the secret key came
|
||||
// from a statement in the current POD, which is the most
|
||||
// common case. A more general solution needs to be able
|
||||
// index across the virtual array of statements from all
|
||||
// input PODs, similar to what's done in
|
||||
// plonky2::mainpod::layout_statements.
|
||||
let adjusted_index = ind
|
||||
- (1 + self.params.max_input_signed_pods
|
||||
* self.params.max_signed_pod_values
|
||||
+ self.params.max_input_recursive_pods
|
||||
* self.params.max_public_statements);
|
||||
if let StatementArg::Literal(value) = &input.statements[adjusted_index].1[1] {
|
||||
if let TypedValue::SecretKey(sk) = value.typed() {
|
||||
pw.set_biguint320_target(&self.secret_keys[i], &sk.0)?;
|
||||
} else {
|
||||
panic!("SecretKey literal of incorrect type!")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("SecretKey arg not found!")
|
||||
}
|
||||
} else {
|
||||
pw.set_biguint320_target(&self.secret_keys[i], &BigUint::ZERO)?;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(input.merkle_proofs.len() <= self.params.max_merkle_proofs_containers);
|
||||
|
|
@ -1556,7 +1720,10 @@ mod tests {
|
|||
basetypes::C,
|
||||
circuits::common::tests::I64_TEST_PAIRS,
|
||||
mainpod::{calculate_id, OperationArg, OperationAux},
|
||||
primitives::merkletree::{MerkleClaimAndProof, MerkleTree},
|
||||
primitives::{
|
||||
ec::schnorr::SecretKey,
|
||||
merkletree::{MerkleClaimAndProof, MerkleTree},
|
||||
},
|
||||
},
|
||||
frontend::{self, literal, CustomPredicateBatchBuilder, StatementTmplBuilder},
|
||||
middleware::{
|
||||
|
|
@ -1570,6 +1737,7 @@ mod tests {
|
|||
op: mainpod::Operation,
|
||||
prev_statements: Vec<mainpod::Statement>,
|
||||
merkle_proofs: Vec<MerkleClaimAndProof>,
|
||||
secret_key: &SecretKey,
|
||||
) -> Result<()> {
|
||||
let params = Params {
|
||||
max_custom_predicate_batches: 0,
|
||||
|
|
@ -1601,6 +1769,7 @@ mod tests {
|
|||
.into_iter()
|
||||
.map(|pf| pf.into())
|
||||
.collect();
|
||||
let secret_key_target = builder.constant_biguint320(&secret_key.0);
|
||||
let custom_predicate_verification_table = vec![];
|
||||
|
||||
verify_operation_circuit(
|
||||
|
|
@ -1611,6 +1780,7 @@ mod tests {
|
|||
&prev_statements_target,
|
||||
0,
|
||||
&merkle_claims_target,
|
||||
&secret_key_target,
|
||||
&custom_predicate_verification_table,
|
||||
)?;
|
||||
|
||||
|
|
@ -1771,7 +1941,13 @@ mod tests {
|
|||
.into_iter()
|
||||
.for_each(|(op, st)| {
|
||||
let check = std::panic::catch_unwind(|| {
|
||||
operation_verify(st, op, prev_statements.to_vec(), vec![])
|
||||
operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements.to_vec(),
|
||||
vec![],
|
||||
&SecretKey(BigUint::ZERO),
|
||||
)
|
||||
});
|
||||
match check {
|
||||
Err(e) => {
|
||||
|
|
@ -1836,7 +2012,14 @@ mod tests {
|
|||
]
|
||||
.into_iter()
|
||||
.for_each(|(op, st)| {
|
||||
assert!(operation_verify(st, op, prev_statements.to_vec(), vec![]).is_err())
|
||||
assert!(operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements.to_vec(),
|
||||
vec![],
|
||||
&SecretKey(BigUint::ZERO)
|
||||
)
|
||||
.is_err())
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1849,7 +2032,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![Statement::None.into()];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1867,7 +2050,7 @@ mod tests {
|
|||
vec![],
|
||||
OperationAux::None,
|
||||
);
|
||||
operation_verify(st1, op, prev_statements, vec![])
|
||||
operation_verify(st1, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1879,7 +2062,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![Statement::None.into()];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1902,7 +2085,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1925,7 +2108,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1948,7 +2131,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2.clone()];
|
||||
operation_verify(st, op, prev_statements, vec![])?;
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))?;
|
||||
|
||||
// Also check negative < negative
|
||||
let st3: mainpod::Statement = Statement::equal(
|
||||
|
|
@ -1972,7 +2155,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st3.clone(), st4];
|
||||
operation_verify(st, op, prev_statements, vec![])?;
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))?;
|
||||
|
||||
// Also check negative < positive
|
||||
let st: mainpod::Statement = Statement::lt(
|
||||
|
|
@ -1986,7 +2169,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st3, st2];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2009,7 +2192,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2.clone()];
|
||||
operation_verify(st, op, prev_statements, vec![])?;
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))?;
|
||||
|
||||
// Also check negative <= negative
|
||||
let st3: mainpod::Statement = Statement::equal(
|
||||
|
|
@ -2033,7 +2216,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st3.clone(), st4];
|
||||
operation_verify(st, op, prev_statements, vec![])?;
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))?;
|
||||
|
||||
// Also check negative <= positive
|
||||
let st: mainpod::Statement = Statement::lt_eq(
|
||||
|
|
@ -2047,7 +2230,13 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st3, st2];
|
||||
operation_verify(st, op, prev_statements.clone(), vec![])?;
|
||||
operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements.clone(),
|
||||
vec![],
|
||||
&SecretKey(BigUint::ZERO),
|
||||
)?;
|
||||
|
||||
// Also check equality, both positive and negative.
|
||||
let st: mainpod::Statement = Statement::lt_eq(
|
||||
|
|
@ -2060,7 +2249,13 @@ mod tests {
|
|||
vec![OperationArg::Index(0), OperationArg::Index(0)],
|
||||
OperationAux::None,
|
||||
);
|
||||
operation_verify(st, op, prev_statements.clone(), vec![])?;
|
||||
operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements.clone(),
|
||||
vec![],
|
||||
&SecretKey(BigUint::ZERO),
|
||||
)?;
|
||||
let st: mainpod::Statement = Statement::lt_eq(
|
||||
AnchoredKey::from((PodId(RawValue::from(88).into()), "hello")),
|
||||
AnchoredKey::from((PodId(RawValue::from(88).into()), "hello")),
|
||||
|
|
@ -2071,7 +2266,7 @@ mod tests {
|
|||
vec![OperationArg::Index(1), OperationArg::Index(1)],
|
||||
OperationAux::None,
|
||||
);
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2120,7 +2315,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2, st3];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2166,7 +2361,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2, st3];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2213,7 +2408,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2, st3];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2255,7 +2450,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2, st3];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2300,7 +2495,13 @@ mod tests {
|
|||
let prev_statements = [st1, st2, st3];
|
||||
|
||||
let check = std::panic::catch_unwind(|| {
|
||||
operation_verify(st, op, prev_statements.to_vec(), vec![])
|
||||
operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements.to_vec(),
|
||||
vec![],
|
||||
&SecretKey(BigUint::ZERO),
|
||||
)
|
||||
});
|
||||
match check {
|
||||
Err(e) => {
|
||||
|
|
@ -2333,7 +2534,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2359,7 +2560,7 @@ mod tests {
|
|||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![st1, st2];
|
||||
operation_verify(st, op, prev_statements, vec![])
|
||||
operation_verify(st, op, prev_statements, vec![], &SecretKey(BigUint::ZERO))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2399,7 +2600,13 @@ mod tests {
|
|||
no_key_pf,
|
||||
)];
|
||||
let prev_statements = vec![root_st, key_st];
|
||||
operation_verify(st, op, prev_statements, merkle_proofs)
|
||||
operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements,
|
||||
merkle_proofs,
|
||||
&SecretKey(BigUint::ZERO),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2446,7 +2653,138 @@ mod tests {
|
|||
key_pf,
|
||||
)];
|
||||
let prev_statements = vec![root_st, key_st, value_st];
|
||||
operation_verify(st, op, prev_statements, merkle_proofs)
|
||||
operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements,
|
||||
merkle_proofs,
|
||||
&SecretKey(BigUint::ZERO),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operation_verify_publickeyof() -> Result<()> {
|
||||
[
|
||||
&SecretKey(BigUint::one()),
|
||||
&SecretKey::new_rand(),
|
||||
&SecretKey(&*GROUP_ORDER - BigUint::one()),
|
||||
]
|
||||
.into_iter()
|
||||
.try_for_each(|secret_key| {
|
||||
let public_key = secret_key.public_key();
|
||||
let public_key_value = Value::from(TypedValue::from(public_key));
|
||||
let secret_key_value = Value::from(TypedValue::from(secret_key.clone()));
|
||||
let public_key_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "public key"));
|
||||
let secret_key_ak = AnchoredKey::from((PodId(RawValue::from(70).into()), "secret key"));
|
||||
let public_key_st: mainpod::Statement =
|
||||
Statement::equal(public_key_ak.clone(), public_key_value.clone()).into();
|
||||
let secret_key_st: mainpod::Statement =
|
||||
Statement::equal(secret_key_ak.clone(), secret_key_value.clone()).into();
|
||||
let st: mainpod::Statement =
|
||||
Statement::public_key_of(public_key_ak, secret_key_ak).into();
|
||||
let op = mainpod::Operation(
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
vec![OperationArg::Index(0), OperationArg::Index(1)],
|
||||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![public_key_st, secret_key_st];
|
||||
operation_verify(st, op, prev_statements, vec![], secret_key)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operation_verify_publickeyof_failure_wrong_key() {
|
||||
let secret_key = SecretKey(BigUint::one());
|
||||
let public_key = SecretKey(BigUint::ZERO).public_key();
|
||||
let public_key_value = Value::from(TypedValue::from(public_key));
|
||||
let secret_key_value = Value::from(TypedValue::from(secret_key.clone()));
|
||||
let public_key_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "public key"));
|
||||
let secret_key_ak = AnchoredKey::from((PodId(RawValue::from(70).into()), "secret key"));
|
||||
let public_key_st: mainpod::Statement =
|
||||
Statement::equal(public_key_ak.clone(), public_key_value.clone()).into();
|
||||
let secret_key_st: mainpod::Statement =
|
||||
Statement::equal(secret_key_ak.clone(), secret_key_value.clone()).into();
|
||||
let st: mainpod::Statement = Statement::public_key_of(public_key_ak, secret_key_ak).into();
|
||||
let op = mainpod::Operation(
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
vec![OperationArg::Index(0), OperationArg::Index(1)],
|
||||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![public_key_st, secret_key_st];
|
||||
assert!(operation_verify(st, op, prev_statements, vec![], &secret_key).is_err())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operation_verify_publickeyof_failure_pk_type() {
|
||||
let secret_key = SecretKey(BigUint::one());
|
||||
let public_key = 123i64;
|
||||
let public_key_value = Value::from(TypedValue::from(public_key));
|
||||
let secret_key_value = Value::from(TypedValue::from(secret_key.clone()));
|
||||
let public_key_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "public key"));
|
||||
let secret_key_ak = AnchoredKey::from((PodId(RawValue::from(70).into()), "secret key"));
|
||||
let public_key_st: mainpod::Statement =
|
||||
Statement::equal(public_key_ak.clone(), public_key_value.clone()).into();
|
||||
let secret_key_st: mainpod::Statement =
|
||||
Statement::equal(secret_key_ak.clone(), secret_key_value.clone()).into();
|
||||
let st: mainpod::Statement = Statement::public_key_of(public_key_ak, secret_key_ak).into();
|
||||
let op = mainpod::Operation(
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
vec![OperationArg::Index(0), OperationArg::Index(1)],
|
||||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![public_key_st, secret_key_st];
|
||||
assert!(operation_verify(st, op, prev_statements, vec![], &secret_key).is_err())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operation_verify_publickeyof_failure_sk_type() {
|
||||
let secret_key = 123i64;
|
||||
let public_key = SecretKey(BigUint::from(123u32)).public_key();
|
||||
let public_key_value = Value::from(TypedValue::from(public_key));
|
||||
let secret_key_value = Value::from(TypedValue::from(secret_key));
|
||||
let public_key_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "public key"));
|
||||
let secret_key_ak = AnchoredKey::from((PodId(RawValue::from(70).into()), "secret key"));
|
||||
let public_key_st: mainpod::Statement =
|
||||
Statement::equal(public_key_ak.clone(), public_key_value.clone()).into();
|
||||
let secret_key_st: mainpod::Statement =
|
||||
Statement::equal(secret_key_ak.clone(), secret_key_value.clone()).into();
|
||||
let st: mainpod::Statement = Statement::public_key_of(public_key_ak, secret_key_ak).into();
|
||||
let op = mainpod::Operation(
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
vec![OperationArg::Index(0), OperationArg::Index(1)],
|
||||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![public_key_st, secret_key_st];
|
||||
assert!(operation_verify(
|
||||
st,
|
||||
op,
|
||||
prev_statements,
|
||||
vec![],
|
||||
&SecretKey(BigUint::from(123u32))
|
||||
)
|
||||
.is_err())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operation_verify_publickeyof_failure_sk_size() {
|
||||
let secret_key = SecretKey(&*GROUP_ORDER - BigUint::ZERO);
|
||||
let public_key = secret_key.public_key();
|
||||
let public_key_value = Value::from(TypedValue::from(public_key));
|
||||
let secret_key_value = Value::from(TypedValue::from(secret_key.clone()));
|
||||
let public_key_ak = AnchoredKey::from((PodId(RawValue::from(88).into()), "public key"));
|
||||
let secret_key_ak = AnchoredKey::from((PodId(RawValue::from(70).into()), "secret key"));
|
||||
let public_key_st: mainpod::Statement =
|
||||
Statement::equal(public_key_ak.clone(), public_key_value.clone()).into();
|
||||
let secret_key_st: mainpod::Statement =
|
||||
Statement::equal(secret_key_ak.clone(), secret_key_value.clone()).into();
|
||||
let st: mainpod::Statement = Statement::public_key_of(public_key_ak, secret_key_ak).into();
|
||||
let op = mainpod::Operation(
|
||||
OperationType::Native(NativeOperation::PublicKeyOf),
|
||||
vec![OperationArg::Index(0), OperationArg::Index(1)],
|
||||
OperationAux::None,
|
||||
);
|
||||
let prev_statements = vec![public_key_st, secret_key_st];
|
||||
assert!(operation_verify(st, op, prev_statements, vec![], &secret_key).is_err())
|
||||
}
|
||||
|
||||
fn helper_statement_arg_from_template(
|
||||
|
|
|
|||
|
|
@ -739,7 +739,10 @@ pub mod tests {
|
|||
primitives::ec::schnorr::SecretKey,
|
||||
signedpod::Signer,
|
||||
},
|
||||
examples::{attest_eth_friend, zu_kyc_pod_builder, zu_kyc_sign_pod_builders, EthDosHelper},
|
||||
examples::{
|
||||
attest_eth_friend, tickets_pod_full_flow, zu_kyc_pod_builder, zu_kyc_sign_pod_builders,
|
||||
EthDosHelper,
|
||||
},
|
||||
frontend::{
|
||||
self, literal, CustomPredicateBatchBuilder, MainPodBuilder, StatementTmplBuilder as STB,
|
||||
},
|
||||
|
|
@ -789,6 +792,19 @@ pub mod tests {
|
|||
Ok(pod.verify()?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_main_tickets() -> frontend::Result<()> {
|
||||
let params = Params::default();
|
||||
|
||||
let ticket_builder = tickets_pod_full_flow(¶ms, &DEFAULT_VD_SET)?;
|
||||
let prover = Prover {};
|
||||
let kyc_pod = ticket_builder.prove(&prover, ¶ms)?;
|
||||
crate::measure_gates_print!();
|
||||
let pod = (kyc_pod.pod as Box<dyn Any>).downcast::<MainPod>().unwrap();
|
||||
|
||||
Ok(pod.verify()?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mini_0() {
|
||||
let params = middleware::Params {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@ impl TryFrom<Statement> for middleware::Statement {
|
|||
(NP::MaxOf, &[a1, a2, a3]) => {
|
||||
S::MaxOf(a1.try_into()?, a2.try_into()?, a3.try_into()?)
|
||||
}
|
||||
(NP::HashOf, &[a1, a2, a3]) => {
|
||||
S::HashOf(a1.try_into()?, a2.try_into()?, a3.try_into()?)
|
||||
}
|
||||
(NP::PublicKeyOf, &[a1, a2]) => S::PublicKeyOf(a1.try_into()?, a2.try_into()?),
|
||||
_ => Err(Error::custom(format!(
|
||||
"Ill-formed statement expression {:?}",
|
||||
s
|
||||
|
|
|
|||
|
|
@ -430,8 +430,7 @@ pub mod tests {
|
|||
great_boy_pod_full_flow, tickets_pod_full_flow, zu_kyc_pod_builder,
|
||||
zu_kyc_sign_pod_builders, MOCK_VD_SET,
|
||||
},
|
||||
frontend,
|
||||
middleware::{self},
|
||||
frontend, middleware,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
@ -486,7 +485,7 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_mock_main_tickets() -> frontend::Result<()> {
|
||||
let params = middleware::Params::default();
|
||||
let tickets_builder = tickets_pod_full_flow()?;
|
||||
let tickets_builder = tickets_pod_full_flow(¶ms, &MOCK_VD_SET)?;
|
||||
let prover = MockProver {};
|
||||
let proof_pod = tickets_builder.prove(&prover, ¶ms)?;
|
||||
let pod = (proof_pod.pod as Box<dyn Any>)
|
||||
|
|
|
|||
|
|
@ -552,6 +552,7 @@ pub trait CircuitBuilderElliptic {
|
|||
|
||||
fn add_point(&mut self, p1: &PointTarget, p2: &PointTarget) -> PointTarget;
|
||||
fn double_point(&mut self, p: &PointTarget) -> PointTarget;
|
||||
fn multiply_point(&mut self, p1_scalar: &[BoolTarget; 320], p1: &PointTarget) -> PointTarget;
|
||||
fn linear_combination_points(
|
||||
&mut self,
|
||||
p1_scalar: &[BoolTarget; 320],
|
||||
|
|
@ -654,6 +655,17 @@ impl CircuitBuilderElliptic for CircuitBuilder<GoldilocksField, 2> {
|
|||
*/
|
||||
}
|
||||
|
||||
fn multiply_point(&mut self, p1_scalar: &[BoolTarget; 320], p1: &PointTarget) -> PointTarget {
|
||||
let zero = self.identity_point();
|
||||
let mut ans = zero.clone();
|
||||
for i in (0..320).rev() {
|
||||
ans = self.double_point(&ans);
|
||||
let maybe_p1 = self.if_point(p1_scalar[i], p1, &zero);
|
||||
ans = self.add_point(&ans, &maybe_p1);
|
||||
}
|
||||
ans
|
||||
}
|
||||
|
||||
fn linear_combination_points(
|
||||
&mut self,
|
||||
p1_scalar: &[BoolTarget; 320],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::array;
|
||||
use std::{array, fmt, str::FromStr};
|
||||
|
||||
use num::BigUint;
|
||||
use num_bigint::RandBigInt;
|
||||
|
|
@ -6,7 +6,7 @@ use plonky2::{
|
|||
field::{
|
||||
extension::FieldExtension,
|
||||
goldilocks_field::GoldilocksField,
|
||||
types::{Field, PrimeField},
|
||||
types::{Field, PrimeField, PrimeField64},
|
||||
},
|
||||
hash::{
|
||||
hash_types::HashOutTarget,
|
||||
|
|
@ -173,6 +173,94 @@ impl SecretKey {
|
|||
let s = (nonce + &self.0 * &e) % &*GROUP_ORDER;
|
||||
Signature { s, e }
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
let bytes = self.0.to_bytes_le();
|
||||
assert!(bytes.len() <= 40);
|
||||
bytes
|
||||
.into_iter()
|
||||
.chain(std::iter::repeat(0u8))
|
||||
.take(40)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn from_bytes(sk_bytes: &[u8]) -> Result<Self, Error> {
|
||||
if sk_bytes.len() != 40 {
|
||||
return Err(Error::custom(
|
||||
"Invalid byte encoding of Schnorr secret key.".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let big_uint = BigUint::from_bytes_le(sk_bytes);
|
||||
|
||||
if big_uint >= *GROUP_ORDER {
|
||||
return Err(Error::custom(
|
||||
"Invalid Schnorr secret key - not less than group order.".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self(big_uint))
|
||||
}
|
||||
|
||||
pub fn to_limbs(&self) -> [GoldilocksField; 10] {
|
||||
assert!(self.0.bits() <= 320);
|
||||
let digits = self.0.to_u32_digits();
|
||||
array::from_fn(|i| {
|
||||
let d = digits.get(i).copied().unwrap_or(0);
|
||||
GoldilocksField::from_canonical_u32(d)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_limbs(limbs: [GoldilocksField; 10]) -> Result<Self, Error> {
|
||||
let mut limb_vec = vec![];
|
||||
for gl in limbs.iter() {
|
||||
let g64 = gl.to_canonical_u64();
|
||||
if g64 >= (1 << 32) {
|
||||
return Err(Error::custom(
|
||||
"Invalid limb value in Schnorr secret key.".to_string(),
|
||||
));
|
||||
}
|
||||
limb_vec.push(g64 as u32);
|
||||
}
|
||||
|
||||
Ok(Self(BigUint::from_slice(&limb_vec)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SecretKey {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let sk_b64 = serialize_bytes(&self.as_bytes());
|
||||
serializer.serialize_str(&sk_b64)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SecretKey {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let sk_b64 = String::deserialize(deserializer)?;
|
||||
let sk_bytes = deserialize_bytes(&sk_b64).map_err(serde::de::Error::custom)?;
|
||||
SecretKey::from_bytes(&sk_bytes).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SecretKey {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", serialize_bytes(self.as_bytes().as_slice()))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for SecretKey {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let sk_bytes = deserialize_bytes(s)?;
|
||||
SecretKey::from_bytes(&sk_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl SignatureTarget {
|
||||
|
|
@ -218,9 +306,14 @@ fn hash_array_circuit(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use itertools::Itertools;
|
||||
use num::BigUint;
|
||||
use num_bigint::RandBigInt;
|
||||
use plonky2::{
|
||||
field::{goldilocks_field::GoldilocksField, types::Sample},
|
||||
field::{
|
||||
goldilocks_field::GoldilocksField,
|
||||
types::{Field, Sample},
|
||||
},
|
||||
iop::{
|
||||
target::Target,
|
||||
witness::{PartialWitness, WitnessWrite},
|
||||
|
|
@ -253,6 +346,29 @@ mod test {
|
|||
(public_key, msg, sig)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key_pairs() -> Result<(), anyhow::Error> {
|
||||
let fixed_sk = SecretKey(BigUint::from(0x1234567890abcdefu64));
|
||||
let fixed_sk_expected_str = "782rkHhWNBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==";
|
||||
assert_eq!(fixed_sk.to_string(), fixed_sk_expected_str);
|
||||
let parsed_sk = fixed_sk_expected_str.parse::<SecretKey>()?;
|
||||
assert_eq!(fixed_sk, parsed_sk);
|
||||
|
||||
let fixed_pk = fixed_sk.public_key();
|
||||
let fixed_pk_expected_str = "8sctoHc2aduKbYtZwo7Z3v7YugSuimLUMAhE95V18CWU55tWMvZxEqA";
|
||||
assert_eq!(fixed_pk.to_string(), fixed_pk_expected_str);
|
||||
let parsed_pk = fixed_pk_expected_str.parse::<Point>()?;
|
||||
assert_eq!(fixed_pk, parsed_pk);
|
||||
|
||||
let rand_sk = SecretKey::new_rand();
|
||||
assert_ne!(fixed_sk, rand_sk);
|
||||
assert_eq!(rand_sk, rand_sk.to_string().parse::<SecretKey>()?);
|
||||
let rand_pk = rand_sk.public_key();
|
||||
assert_ne!(fixed_pk, rand_pk);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_signature() {
|
||||
let (public_key, msg, sig) = gen_signed_message();
|
||||
|
|
@ -352,4 +468,67 @@ mod test {
|
|||
data.verify(proof)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_secret_key_serialization() -> Result<(), anyhow::Error> {
|
||||
let sk_123 = SecretKey(BigUint::from(123u32));
|
||||
let str_123 = serde_json::to_string(&sk_123).unwrap();
|
||||
let deser_123 = serde_json::from_str(&str_123).unwrap();
|
||||
assert_eq!(sk_123, deser_123);
|
||||
|
||||
let sk_rand = SecretKey::new_rand();
|
||||
assert_ne!(sk_123, sk_rand);
|
||||
let str_rand = serde_json::to_string(&sk_rand).unwrap();
|
||||
let deser_rand = serde_json::from_str(&str_rand).unwrap();
|
||||
assert_eq!(sk_rand, deser_rand);
|
||||
|
||||
let sk_max = SecretKey(&*GROUP_ORDER - 1u32);
|
||||
assert_ne!(sk_123, sk_max);
|
||||
let str_max = serde_json::to_string(&sk_max).unwrap();
|
||||
let deser_max = serde_json::from_str(&str_max).unwrap();
|
||||
assert_eq!(sk_max, deser_max);
|
||||
|
||||
// Value is too big for group but fits within 320 bits. Thus it
|
||||
// survives the assert in as_bytes(), but gets caught during deserialization.
|
||||
let sk_toobig = SecretKey(GROUP_ORDER.clone());
|
||||
assert_ne!(sk_toobig, sk_123);
|
||||
let str_toobig = serde_json::to_string(&sk_toobig).unwrap();
|
||||
assert!(serde_json::from_str::<SecretKey>(&str_toobig).is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_secret_key_limbs() -> Result<(), anyhow::Error> {
|
||||
let sk_0 = SecretKey(BigUint::from(0u32));
|
||||
let limbs_0 = sk_0.to_limbs();
|
||||
assert_eq!(limbs_0, [GoldilocksField::from_canonical_u32(0); 10]);
|
||||
let rsk_0 = SecretKey::from_limbs(limbs_0).unwrap();
|
||||
assert_eq!(sk_0, rsk_0);
|
||||
|
||||
let sk_n: SecretKey = SecretKey(BigUint::from_slice((0..10).collect_vec().as_slice()));
|
||||
let limbs_n = sk_n.to_limbs();
|
||||
assert_eq!(
|
||||
limbs_n.as_slice(),
|
||||
(0..10)
|
||||
.map(GoldilocksField::from_canonical_u32)
|
||||
.collect_vec()
|
||||
.as_slice()
|
||||
);
|
||||
let rsk_n = SecretKey::from_limbs(limbs_n).unwrap();
|
||||
assert_eq!(sk_n, rsk_n);
|
||||
|
||||
assert!(SecretKey::from_limbs(
|
||||
(0..9)
|
||||
.chain([9u64 << 32])
|
||||
.map(GoldilocksField::from_canonical_u64)
|
||||
.collect_vec()
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
.is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue