Skip to content

Commit

Permalink
Merge pull request #3 from securesecrets/optional-permit-alternative
Browse files Browse the repository at this point in the history
Optional permit alternative
  • Loading branch information
FloppyDisck authored Jan 29, 2022
2 parents c0e6dcc + dbcfa04 commit 256d7dc
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 19 deletions.
79 changes: 69 additions & 10 deletions src/permit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::transaction::{PermitSignature, PubKeyValue, SignedTx, TxMsg};
use bech32::FromBase32;
use cosmwasm_std::{to_binary, Binary, CanonicalAddr, StdError, StdResult};
use cosmwasm_std::{to_binary, Binary, CanonicalAddr, StdError, StdResult, Uint128};
use schemars::JsonSchema;
use secp256k1::Secp256k1;
use secret_toolkit::crypto::sha_256;
Expand All @@ -15,8 +15,11 @@ use serde::{Deserialize, Serialize};
#[serde(rename_all = "snake_case")]
pub struct Permit<T: Clone + Serialize> {
pub params: T,
pub chain_id: Option<String>,
pub signature: PermitSignature,
pub account_number: Option<Uint128>,
pub chain_id: Option<String>,
pub sequence: Option<Uint128>,
pub memo: Option<String>,
}

pub fn bech32_to_canonical(addr: &str) -> CanonicalAddr {
Expand All @@ -25,16 +28,20 @@ pub fn bech32_to_canonical(addr: &str) -> CanonicalAddr {
}

impl<T: Clone + Serialize> Permit<T> {
pub fn create_signed_tx(&self) -> SignedTx<T> {
SignedTx::from_msg(TxMsg::from_permit(self), self.chain_id.clone())
pub fn create_signed_tx(&self, msg_type: Option<String>) -> SignedTx<T> {
SignedTx::from_permit(&self, msg_type)
}

/// Returns the permit signer
pub fn validate(&self) -> StdResult<PubKeyValue> {
let pubkey = &self.signature.pub_key.value;
pub fn validate(&self, msg_type: Option<String>) -> StdResult<PubKeyValue> {
Permit::validate_signed_tx(&self.signature, &self.create_signed_tx(msg_type))
}

pub fn validate_signed_tx(signature: &PermitSignature, signed_tx: &SignedTx<T>) -> StdResult<PubKeyValue> {
let pubkey = &signature.pub_key.value;

// Validate signature
let signed_bytes = to_binary(&self.create_signed_tx())?;
let signed_bytes = to_binary(signed_tx)?;
let signed_bytes_hash = sha_256(signed_bytes.as_slice());
let secp256k1_msg = secp256k1::Message::from_slice(&signed_bytes_hash).map_err(|err| {
StdError::generic_err(format!(
Expand All @@ -46,7 +53,7 @@ impl<T: Clone + Serialize> Permit<T> {
let secp256k1_verifier = Secp256k1::verification_only();

let secp256k1_signature =
secp256k1::Signature::from_compact(&self.signature.signature.0)
secp256k1::Signature::from_compact(&signature.signature.0)
.map_err(|err| StdError::generic_err(format!("Malformed signature: {:?}", err)))?;
let secp256k1_pubkey = secp256k1::PublicKey::from_slice(pubkey.0.as_slice())
.map_err(|err| StdError::generic_err(format!("Malformed pubkey: {:?}", err)))?;
Expand Down Expand Up @@ -115,13 +122,65 @@ mod signature_tests {
some_number: Uint128(10),
},
chain_id: Some("pulsar-1".to_string()),
sequence: None,
signature: PermitSignature {
pub_key: PubKey::new(Binary::from_base64(PUBKEY).unwrap()),
signature: Binary::from_base64(SIGNED_TX).unwrap(),
},
account_number: None,
memo: None
};

let addr = permit.validate().unwrap();
let addr = permit.validate(None).unwrap();
assert_eq!(addr.as_canonical(), bech32_to_canonical(ADDRESS));
}
}

const FILLERPERMITNAME: &str = "wasm/MsgExecuteContract";

type MemoPermit = Permit<FillerPermit>;

#[remain::sorted]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
struct FillerPermit {
pub coins: Vec<String>,
pub contract: String,
pub execute_msg: EmptyMsg,
pub sender: String,
}

#[remain::sorted]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(rename_all = "snake_case")]
struct EmptyMsg {}

#[test]
fn memo_signature() {
let mut permit = MemoPermit {
params: FillerPermit {
coins: vec![],
sender: "".to_string(),
contract: "".to_string(),
execute_msg: EmptyMsg {}
},
chain_id: Some("bombay-12".to_string()),
sequence: Some(Uint128(0)),
signature: PermitSignature {
pub_key: PubKey::new(Binary::from_base64(
"A50CTeVnMYyZGh7K4x4NtdfG1H1oicog6lEoPMi65IK2").unwrap()),
signature: Binary::from_base64(
"75RcVHa/SW1WyjcFMkhZ63+D4ccxffchLvJPyURmtaskA8CPj+y6JSrpuRhxMC+1hdjSJC3c0IeJVbDIRapxPg==").unwrap(),
},
account_number: Some(Uint128(203289)),
memo: Some("b64Encoded".to_string())
};

let addr = permit.validate(Some(FILLERPERMITNAME.to_string())).unwrap();
assert_eq!(addr.as_canonical(), bech32_to_canonical("terra1m79yd3jh97vz4tqu0m8g49gfl7qmknhh23kac5"));
assert_ne!(addr.as_canonical(), bech32_to_canonical("secret102nasmxnxvwp5agc4lp3flc6s23335xm8g7gn9"));

permit.memo = Some("OtherMemo".to_string());

assert!(permit.validate(Some(FILLERPERMITNAME.to_string())).is_err())
}
}
18 changes: 9 additions & 9 deletions src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ pub struct TxMsg<T> {
}

impl<T: Clone + Serialize> TxMsg<T> {
pub fn from_permit(permit: &Permit<T>) -> Self {
pub fn new(params: T, msg_type: Option<String>) -> Self {
Self {
r#type: "signature_proof".to_string(),
value: permit.params.clone(),
r#type: msg_type.unwrap_or("signature_proof".to_string()),
value: params.clone(),
}
}
}
Expand All @@ -80,14 +80,14 @@ pub struct SignedTx<T> {
}

impl<T: Clone + Serialize> SignedTx<T> {
pub fn from_msg(item: TxMsg<T>, chain_id: Option<String>) -> Self {
pub fn from_permit(permit: &Permit<T>, msg_type: Option<String>) -> Self {
Self {
account_number: Uint128::zero(),
chain_id: chain_id.unwrap_or("secret-4".to_string()),
account_number: permit.account_number.unwrap_or(Uint128::zero()),
chain_id: permit.chain_id.clone().unwrap_or("secret-4".to_string()),
fee: Default::default(),
memo: String::new(),
msgs: vec![item],
sequence: Uint128::zero(),
memo: permit.memo.clone().unwrap_or(String::new()),
msgs: vec![TxMsg::new(permit.params.clone(), msg_type)],
sequence: permit.sequence.unwrap_or(Uint128::zero()),
}
}
}
Expand Down

0 comments on commit 256d7dc

Please sign in to comment.