Skip to content

feat: define Signed<M, A> message #321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/contracts/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub enum Error {
Std(#[from] StdError),
#[error("{0}")]
RaVerification(#[from] RaVerificationError),
#[error("Signature verification error: {0}")]
SignatureVerification(String),
#[error("Not Secp256K1")]
K256(K256Error),
#[error("invalid session nonce or attempt to reset pub_key")]
Expand Down
1 change: 1 addition & 0 deletions crates/contracts/core/src/handler/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod attested;
pub mod sequenced;
pub mod session_create;
pub mod session_set_pub_key;
pub mod signed;

use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};

Expand Down
25 changes: 25 additions & 0 deletions crates/contracts/core/src/handler/execute/signed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};

use crate::{
error::Error,
handler::Handler,
msg::execute::signed::{Auth, MsgVerifier, Signed},
};

impl<M, A, P, S> Handler for Signed<M, A>
where
M: Handler + MsgVerifier<PubKey = P, Sig = S>,
A: Auth<P, S>,
{
fn handle(
self,
mut deps: DepsMut<'_>,
env: &Env,
info: &MessageInfo,
) -> Result<Response, Error> {
let (msg, auth) = self.into_tuple();
let pub_key = auth.pub_key();
msg.verify(pub_key, auth.sig())?;
Handler::handle(msg, deps.branch(), env, info)
}
}
1 change: 1 addition & 0 deletions crates/contracts/core/src/msg/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod attested;
pub mod sequenced;
pub mod session_create;
pub mod session_set_pub_key;
pub mod signed;

use cosmwasm_schema::cw_serde;
use cosmwasm_std::StdError;
Expand Down
125 changes: 125 additions & 0 deletions crates/contracts/core/src/msg/execute/signed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use std::fmt::Debug;

use cosmwasm_schema::cw_serde;
use cosmwasm_std::StdError;

use super::attested::Noop;
use crate::{error::Error, msg::HasDomainType};

pub type AnySigned<M, P, S> = Signed<M, AnyAuth<P, S>>;

#[derive(Clone, Debug, PartialEq)]
pub struct Signed<M, A> {
msg: M,
auth: A,
}

impl<M, A> Signed<M, A> {
pub fn new(msg: M, auth: A) -> Self {
Self { msg, auth }
}

pub fn into_tuple(self) -> (M, A) {
let Self { msg, auth } = self;
(msg, auth)
}

pub fn msg(&self) -> &M {
&self.msg
}

pub fn auth(&self) -> &A {
&self.auth
}
}

#[cw_serde]
pub struct RawSigned<RM, RA> {
pub msg: RM,
pub auth: RA,
}

impl<RM, RA> RawSigned<RM, RA> {
pub fn new(msg: RM, auth: RA) -> Self {
Self { msg, auth }
}
}

impl<RM, RA> HasDomainType for RawSigned<RM, RA>
where
RM: HasDomainType,
RA: HasDomainType,
{
type DomainType = Signed<RM::DomainType, RA::DomainType>;
}

impl<RM, RA> TryFrom<RawSigned<RM, RA>> for Signed<RM::DomainType, RA::DomainType>
where
RM: HasDomainType,
RA: HasDomainType,
{
type Error = StdError;

fn try_from(value: RawSigned<RM, RA>) -> Result<Self, Self::Error> {
Ok(Self {
msg: value.msg.try_into()?,
auth: value.auth.try_into()?,
})
}
}

impl<RM, RA> From<Signed<RM::DomainType, RA::DomainType>> for RawSigned<RM, RA>
where
RM: HasDomainType,
RA: HasDomainType,
{
fn from(value: Signed<RM::DomainType, RA::DomainType>) -> Self {
Self {
msg: value.msg.into(),
auth: value.auth.into(),
}
}
}

pub trait MsgVerifier {
type PubKey;
type Sig;

fn verify(&self, pub_key: &Self::PubKey, sig: &Self::Sig) -> Result<(), Error>;
}

#[derive(Clone, Debug, PartialEq)]
pub struct AnyAuth<P, S> {
pub pub_key: P,
pub sig: S,
}

impl<P, S> AnyAuth<P, S> {
pub fn new(pub_key: P, sig: S) -> Self {
Self { pub_key, sig }
}
}

pub trait Auth<P, S> {
fn pub_key(&self) -> &P;
fn sig(&self) -> &S;
}

impl<P, S> Auth<P, S> for AnyAuth<P, S> {
fn pub_key(&self) -> &P {
&self.pub_key
}

fn sig(&self) -> &S {
&self.sig
}
}

impl<M: MsgVerifier> MsgVerifier for Noop<M> {
type PubKey = M::PubKey;
type Sig = M::Sig;

fn verify(&self, pub_key: &Self::PubKey, sig: &Self::Sig) -> Result<(), Error> {
self.0.verify(pub_key, sig)
}
}
4 changes: 4 additions & 0 deletions crates/contracts/core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,8 @@ impl Session {
pub fn nonce(&self) -> Nonce {
self.nonce.to_array().expect("correct by construction")
}

pub fn pub_key(self) -> Option<HexBinary> {
self.pub_key
}
}
2 changes: 1 addition & 1 deletion crates/contracts/dcap-verifier/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
to_json_binary(&())
} else {
Err(StdError::generic_err(
Error::Dcap(verification_output).to_string(),
Error::Dcap(Box::new(verification_output)).to_string(),
))
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/contracts/tee-ra/src/intel_sgx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ pub enum Error {
#[error("Specified MRENCLAVE does not match the report")]
MrEnclaveMismatch,
#[error("DCAP specific error: {0:?}")]
Dcap(dcap::VerificationOutput<dcap::DcapVerifierOutput>),
Dcap(Box<dcap::VerificationOutput<dcap::DcapVerifierOutput>>),
}
4 changes: 2 additions & 2 deletions examples/transfers/contracts/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,10 @@ mod query {
}

pub fn get_requests(deps: Deps) -> StdResult<Vec<Request>> {
Ok(REQUESTS.load(deps.storage)?)
REQUESTS.load(deps.storage)
}

pub fn get_state(deps: Deps) -> StdResult<HexBinary> {
Ok(STATE.load(deps.storage)?)
STATE.load(deps.storage)
}
}
Loading