2024-03-19 21:19:38 +00:00
|
|
|
use core::time::Duration;
|
|
|
|
|
2024-02-19 15:55:46 +00:00
|
|
|
use cosmwasm_schema::cw_serde;
|
2024-03-19 21:19:38 +00:00
|
|
|
use cosmwasm_std::{HexBinary, StdError};
|
2024-02-19 15:55:46 +00:00
|
|
|
use cw_storage_plus::Item;
|
|
|
|
use k256::ecdsa::VerifyingKey;
|
|
|
|
|
|
|
|
pub type MrEnclave = [u8; 32];
|
|
|
|
pub type Nonce = [u8; 32];
|
|
|
|
pub type UserData = [u8; 64];
|
2024-03-19 21:19:38 +00:00
|
|
|
pub type Hash = [u8; 32];
|
|
|
|
pub type Height = u64;
|
|
|
|
pub type TrustThreshold = (u64, u64);
|
2024-02-19 15:55:46 +00:00
|
|
|
|
2024-03-19 21:19:38 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
2024-02-19 15:55:46 +00:00
|
|
|
pub struct Config {
|
2024-03-19 21:19:38 +00:00
|
|
|
mr_enclave: MrEnclave,
|
|
|
|
epoch_duration: Duration,
|
|
|
|
light_client_opts: LightClientOpts,
|
2024-02-19 15:55:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Config {
|
2024-03-19 21:19:38 +00:00
|
|
|
pub fn new(
|
|
|
|
mr_enclave: MrEnclave,
|
|
|
|
epoch_duration: Duration,
|
|
|
|
light_client_opts: LightClientOpts,
|
|
|
|
) -> Self {
|
2024-02-19 15:55:46 +00:00
|
|
|
Self {
|
2024-03-19 21:19:38 +00:00
|
|
|
mr_enclave,
|
|
|
|
epoch_duration,
|
|
|
|
light_client_opts,
|
2024-02-19 15:55:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 21:19:38 +00:00
|
|
|
pub fn light_client_opts(&self) -> &LightClientOpts {
|
|
|
|
&self.light_client_opts
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mr_enclave(&self) -> MrEnclave {
|
|
|
|
self.mr_enclave
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cw_serde]
|
|
|
|
pub struct RawConfig {
|
|
|
|
mr_enclave: HexBinary,
|
|
|
|
epoch_duration: Duration,
|
|
|
|
light_client_opts: RawLightClientOpts,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RawConfig {
|
|
|
|
pub fn mr_enclave(&self) -> &[u8] {
|
|
|
|
self.mr_enclave.as_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<RawConfig> for Config {
|
|
|
|
type Error = StdError;
|
|
|
|
|
|
|
|
fn try_from(value: RawConfig) -> Result<Self, Self::Error> {
|
|
|
|
Ok(Self {
|
|
|
|
mr_enclave: value.mr_enclave.to_array()?,
|
|
|
|
epoch_duration: value.epoch_duration,
|
|
|
|
light_client_opts: value
|
|
|
|
.light_client_opts
|
|
|
|
.try_into()
|
|
|
|
.map_err(|e| StdError::parse_err("light_client_opts", e))?,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Config> for RawConfig {
|
|
|
|
fn from(value: Config) -> Self {
|
|
|
|
Self {
|
|
|
|
mr_enclave: value.mr_enclave.into(),
|
|
|
|
epoch_duration: value.epoch_duration,
|
|
|
|
light_client_opts: value.light_client_opts.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub struct LightClientOpts {
|
|
|
|
chain_id: String,
|
|
|
|
trusted_height: Height,
|
|
|
|
trusted_hash: Hash,
|
|
|
|
trust_threshold: TrustThreshold,
|
|
|
|
trusting_period: u64,
|
|
|
|
max_clock_drift: u64,
|
|
|
|
max_block_lag: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LightClientOpts {
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
|
|
pub fn new(
|
|
|
|
chain_id: String,
|
|
|
|
trusted_height: Height,
|
|
|
|
trusted_hash: Hash,
|
|
|
|
trust_threshold: TrustThreshold,
|
|
|
|
trusting_period: u64,
|
|
|
|
max_clock_drift: u64,
|
|
|
|
max_block_lag: u64,
|
|
|
|
) -> Result<Self, StdError> {
|
|
|
|
let (numerator, denominator) = (trust_threshold.0, trust_threshold.1);
|
|
|
|
if numerator > denominator {
|
|
|
|
return Err(StdError::generic_err("trust_threshold_too_large"));
|
|
|
|
}
|
|
|
|
if denominator == 0 {
|
|
|
|
return Err(StdError::generic_err("undefined_trust_threshold"));
|
|
|
|
}
|
|
|
|
if 3 * numerator < denominator {
|
|
|
|
return Err(StdError::generic_err("trust_threshold_too_small"));
|
|
|
|
}
|
|
|
|
|
|
|
|
let _trusted_height: i64 = trusted_height
|
|
|
|
.try_into()
|
|
|
|
.map_err(|_| StdError::generic_err("trusted_height too large"))?;
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
chain_id,
|
|
|
|
trusted_height,
|
|
|
|
trusted_hash,
|
|
|
|
trust_threshold,
|
|
|
|
trusting_period,
|
|
|
|
max_clock_drift,
|
|
|
|
max_block_lag,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn chain_id(&self) -> &String {
|
|
|
|
&self.chain_id
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn trusted_height(&self) -> Height {
|
|
|
|
self.trusted_height
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn trusted_hash(&self) -> &Hash {
|
|
|
|
&self.trusted_hash
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn trust_threshold(&self) -> &TrustThreshold {
|
|
|
|
&self.trust_threshold
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn trusting_period(&self) -> u64 {
|
|
|
|
self.trusting_period
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn max_clock_drift(&self) -> u64 {
|
|
|
|
self.max_clock_drift
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn max_block_lag(&self) -> u64 {
|
|
|
|
self.max_block_lag
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cw_serde]
|
|
|
|
pub struct RawLightClientOpts {
|
|
|
|
chain_id: String,
|
|
|
|
trusted_height: u64,
|
|
|
|
trusted_hash: HexBinary,
|
|
|
|
trust_threshold: (u64, u64),
|
|
|
|
trusting_period: u64,
|
|
|
|
max_clock_drift: u64,
|
|
|
|
max_block_lag: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<RawLightClientOpts> for LightClientOpts {
|
|
|
|
type Error = StdError;
|
|
|
|
|
|
|
|
fn try_from(value: RawLightClientOpts) -> Result<Self, Self::Error> {
|
|
|
|
Self::new(
|
|
|
|
value.chain_id,
|
|
|
|
value.trusted_height,
|
|
|
|
value.trusted_hash.to_array()?,
|
|
|
|
(value.trust_threshold.0, value.trust_threshold.1),
|
|
|
|
value.trusting_period,
|
|
|
|
value.max_clock_drift,
|
|
|
|
value.max_block_lag,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<LightClientOpts> for RawLightClientOpts {
|
|
|
|
fn from(value: LightClientOpts) -> Self {
|
|
|
|
Self {
|
|
|
|
chain_id: value.chain_id,
|
|
|
|
trusted_height: value.trusted_height,
|
|
|
|
trusted_hash: Vec::<u8>::from(value.trusted_hash).into(),
|
|
|
|
trust_threshold: (value.trust_threshold.0, value.trust_threshold.1),
|
|
|
|
trusting_period: value.trusting_period,
|
|
|
|
max_clock_drift: value.max_clock_drift,
|
|
|
|
max_block_lag: value.max_block_lag,
|
|
|
|
}
|
2024-02-19 15:55:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cw_serde]
|
|
|
|
pub struct Session {
|
|
|
|
nonce: HexBinary,
|
|
|
|
pub_key: Option<HexBinary>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Session {
|
|
|
|
pub fn create(nonce: Nonce) -> Self {
|
|
|
|
Self {
|
|
|
|
nonce: nonce.into(),
|
|
|
|
pub_key: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_pub_key(mut self, nonce: Nonce, pub_key: VerifyingKey) -> Option<Self> {
|
|
|
|
if self.nonce == nonce && self.pub_key.is_none() {
|
|
|
|
self.pub_key = Some(pub_key.to_sec1_bytes().into_vec().into());
|
|
|
|
Some(self)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 21:19:38 +00:00
|
|
|
|
|
|
|
pub fn nonce(&self) -> Nonce {
|
|
|
|
self.nonce.to_array().expect("correct by construction")
|
|
|
|
}
|
2024-02-19 15:55:46 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 21:19:38 +00:00
|
|
|
pub const CONFIG: Item<'_, RawConfig> = Item::new("quartz_config");
|
2024-02-19 15:55:46 +00:00
|
|
|
pub const SESSION: Item<'_, Session> = Item::new("quartz_session");
|
2024-03-19 21:19:38 +00:00
|
|
|
pub const EPOCH_COUNTER: Item<'_, usize> = Item::new("epoch_counter");
|