Skip to content

Commit 66b3305

Browse files
committed
Merge branch 'main' into anodar/3569-6-chain-aware-presigs
2 parents 7d693b8 + 949895f commit 66b3305

5 files changed

Lines changed: 721 additions & 667 deletions

File tree

crates/contract/src/api.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
33
pub mod authorization;
44
pub mod common;
5+
pub mod keys;
6+
pub mod sign;
57
#[cfg(not(target_arch = "wasm32"))]
68
#[cfg(test)]
79
pub mod test_utils;

crates/contract/src/api/keys.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Public-key views: the domain public key, per-account derived keys, and the
2+
//! latest key version.
3+
4+
use crate::crypto_shared::{
5+
derive_key_secp256k1, kdf::derive_public_key_edwards_point_ed25519, types::PublicKeyExtended,
6+
};
7+
use crate::errors::Error;
8+
use crate::errors::PublicKeyError;
9+
use near_mpc_contract_interface::types::kdf::derive_tweak;
10+
use near_mpc_contract_interface::types::{self as dtos};
11+
12+
use dtos::{Curve, DomainId};
13+
use near_sdk::{AccountId, env, near};
14+
15+
use crate::{MpcContract, MpcContractExt};
16+
17+
#[near]
18+
impl MpcContract {
19+
/// This is the root public key combined from all the public keys of the participants.
20+
/// The domain parameter specifies which domain we're querying the public key for;
21+
/// the default is the first domain.
22+
#[handle_result]
23+
pub fn public_key(&self, domain_id: Option<DomainId>) -> Result<dtos::PublicKey, Error> {
24+
let domain_id = domain_id.unwrap_or_else(DomainId::legacy_ecdsa_id);
25+
self.public_key_extended(domain_id).map(Into::into)
26+
}
27+
28+
/// This is the derived public key of the caller given path and predecessor
29+
/// if predecessor is not provided, it will be the caller of the contract.
30+
///
31+
/// The domain parameter specifies which domain we're deriving the public key for;
32+
/// the default is the first domain.
33+
#[handle_result]
34+
pub fn derived_public_key(
35+
&self,
36+
path: String,
37+
predecessor: Option<AccountId>,
38+
domain_id: Option<DomainId>,
39+
) -> Result<dtos::PublicKey, Error> {
40+
let predecessor: AccountId = predecessor.unwrap_or_else(env::predecessor_account_id);
41+
let tweak = derive_tweak(&predecessor, &path);
42+
43+
let domain = domain_id.unwrap_or_else(DomainId::legacy_ecdsa_id);
44+
let public_key = self.public_key_extended(domain)?;
45+
46+
let derived_public_key: dtos::PublicKey = match public_key {
47+
PublicKeyExtended::Secp256k1 { near_public_key } => {
48+
let secp_pk = dtos::Secp256k1PublicKey::try_from(&near_public_key)
49+
.expect("Secp256k1 variant always has a secp256k1 key");
50+
let affine = *k256::PublicKey::try_from(&secp_pk)
51+
.expect("stored key is always valid")
52+
.as_affine();
53+
let derived_public_key =
54+
derive_key_secp256k1(&affine, &tweak).map_err(PublicKeyError::from)?;
55+
derived_public_key.into()
56+
}
57+
PublicKeyExtended::Ed25519 { edwards_point, .. } => {
58+
let derived_public_key_edwards_point =
59+
derive_public_key_edwards_point_ed25519(&edwards_point, &tweak);
60+
dtos::Ed25519PublicKey::from(derived_public_key_edwards_point.compress()).into()
61+
}
62+
PublicKeyExtended::Bls12381 { public_key } => public_key,
63+
};
64+
65+
Ok(derived_public_key)
66+
}
67+
68+
/// Key versions refer new versions of the root key that we may choose to generate on cohort
69+
/// changes. Older key versions will always work but newer key versions were never held by
70+
/// older signers. Newer key versions may also add new security features, like only existing
71+
/// within a secure enclave. The signature_scheme parameter specifies which protocol
72+
/// we're querying the latest version for. The default is Secp256k1. The default is **NOT**
73+
/// to query across all protocols.
74+
pub fn latest_key_version(&self, signature_scheme: Option<Curve>) -> u32 {
75+
self.protocol_state
76+
.most_recent_domain_for_curve(signature_scheme.unwrap_or_default())
77+
.unwrap()
78+
.0 as u32
79+
}
80+
}
81+
82+
impl MpcContract {
83+
pub(crate) fn public_key_extended(
84+
&self,
85+
domain_id: DomainId,
86+
) -> Result<PublicKeyExtended, Error> {
87+
self.protocol_state.public_key(domain_id)
88+
}
89+
}

0 commit comments

Comments
 (0)