Skip to content
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

Feat: SelfSign trait #14

Merged
merged 15 commits into from
Aug 2, 2024
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ cosmwasm-schema = { version = "1.5.5", optional = true }
cosmwasm-std = { version = "1.5.5", optional = true }
cw-storage-plus = "1.2.0"
hex = "0.4.3"
lazy_static = "1.5.0"
sha3 = "0.10"
semver = { version = "1.0", features = ["serde"] }
serde = { version = "1.0", optional = true }
Expand Down
4 changes: 1 addition & 3 deletions src/crypto.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use sha3::{Digest, Keccak256};
use vrf_rs::Secp256k1Sha256;

use crate::{error::Result, types::Hash};

pub fn verify_proof(public_key: &[u8], proof: &[u8], hash: Hash) -> Result<()> {
let verifier = Secp256k1Sha256::default();
let verifed = verifier.verify(public_key, proof, &hash);
let verifed = crate::types::VRF.verify(public_key, proof, &hash);

// If we don't get an error it's always ok
verifed?;
Expand Down
37 changes: 20 additions & 17 deletions src/msgs/assert_json.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
#[cfg(cosmwasm)]
use serde_json::to_string;
use serde_json::to_value;
//! assert that the msg M serializes to the expected json J
//! if cosmwasm feature is enabled, also assert that we can deserialize the json back to the msg

// assert that the msg M serializes to the expected json J
// if cosmwasm feature is enabled, also assert that we can deserialize the json back to the msg
pub fn assert_json_ok<M, J>(msg: &M, json: &J)
#[track_caller]
#[cfg(not(feature = "cosmwasm"))]
pub fn assert_json_ok<M>(msg: M, expected_json: serde_json::Value)
where
M: serde::Serialize,
J: serde::Serialize,
M: serde::Serialize + std::fmt::Debug + PartialEq,
{
let msg_json = to_value(msg).unwrap();
let expected_json = to_value(json).unwrap();
let msg_json = serde_json::to_value(&msg).unwrap();
assert_eq!(msg_json, expected_json);
}

#[track_caller]
#[cfg(feature = "cosmwasm")]
pub fn assert_json_ok<M>(msg: M, expected_json: serde_json::Value)
where
M: serde::Serialize + std::fmt::Debug + PartialEq + serde::de::DeserializeOwned,
{
let msg_json = serde_json::to_value(&msg).unwrap();
assert_eq!(msg_json, expected_json);

#[cfg(cosmwasm)]
{
let msg_str = to_string(msg).unwrap();
let serialized = to_string(msg_str).unwrap();
let deserialized: QueryMsg = serde_json::from_str(&serialized).unwrap();
assert_eq!(msg, deserialized);
}
let msg_str = serde_json::to_string(&msg).unwrap();
let deserialized: M = serde_json::from_str(&msg_str).unwrap();
assert_eq!(msg, deserialized);
}
47 changes: 46 additions & 1 deletion src/msgs/data_requests/execute/commit_result.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

#[cfg_attr(feature = "cosmwasm", cw_serde)]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize))]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize, Debug, PartialEq))]
#[cfg_attr(not(feature = "cosmwasm"), serde(rename_all = "snake_case"))]
pub struct Execute {
pub dr_id: String,
Expand All @@ -10,6 +10,51 @@ pub struct Execute {
pub proof: String,
}

impl SignSelf for Execute {
type Extra = u64;

fn proof(&self) -> Result<Vec<u8>> {
Ok(hex::decode(&self.proof)?)
}

fn msg_hash(&self, chain_id: &str, contract_addr: &str, dr_height: Self::Extra) -> Result<Hash> {
Ok(hash([
"commit_data_result".as_bytes(),
self.dr_id.as_bytes(),
&dr_height.to_be_bytes(),
self.commitment.as_bytes(),
chain_id.as_bytes(),
contract_addr.as_bytes(),
]))
}
}

impl Execute {
pub fn new(
dr_id: String,
commitment: String,
public_key: String,
signing_key: &[u8],
gluax marked this conversation as resolved.
Show resolved Hide resolved
chain_id: &str,
contract_addr: &str,
dr_height: u64,
mariocao marked this conversation as resolved.
Show resolved Hide resolved
) -> Result<Self> {
let mut ex = Self {
dr_id,
commitment,
public_key,
proof: Default::default(),
};
ex.proof = ex.sign(signing_key, chain_id, contract_addr, dr_height)?.to_hex();

Ok(ex)
}

pub fn verify(&self, public_key: &[u8], chain_id: &str, contract_addr: &str, dr_height: u64) -> Result<()> {
self.verify_inner(public_key, chain_id, contract_addr, dr_height)
}
}

impl From<Execute> for crate::msgs::ExecuteMsg {
fn from(value: Execute) -> Self {
super::ExecuteMsg::CommitDataResult(value).into()
Expand Down
2 changes: 1 addition & 1 deletion src/msgs/data_requests/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod post_request;
pub mod reveal_result;

#[cfg_attr(feature = "cosmwasm", cw_serde)]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize))]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize, Debug, PartialEq))]
#[cfg_attr(not(feature = "cosmwasm"), serde(rename_all = "snake_case"))]
pub enum ExecuteMsg {
CommitDataResult(commit_result::Execute),
Expand Down
2 changes: 1 addition & 1 deletion src/msgs/data_requests/execute/post_request.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

#[cfg_attr(feature = "cosmwasm", cw_serde)]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize))]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize, Debug, PartialEq))]
#[cfg_attr(not(feature = "cosmwasm"), serde(rename_all = "snake_case"))]
pub struct Execute {
pub posted_dr: PostDataRequestArgs,
Expand Down
67 changes: 66 additions & 1 deletion src/msgs/data_requests/execute/reveal_result.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

#[cfg_attr(feature = "cosmwasm", cw_serde)]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize))]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize, Debug, PartialEq))]
#[cfg_attr(not(feature = "cosmwasm"), serde(rename_all = "snake_case"))]
pub struct Execute {
pub dr_id: String,
Expand All @@ -12,6 +12,71 @@ pub struct Execute {
pub stdout: Vec<String>,
}

impl SignSelf for Execute {
type Extra = (u64, Hash);

fn proof(&self) -> Result<Vec<u8>> {
Ok(hex::decode(&self.proof)?)
}

fn msg_hash(
&self,
chain_id: &str,
contract_addr: &str,
(dr_height, reveal_body_hash): Self::Extra,
) -> Result<Hash> {
Ok(hash([
"reveal_data_result".as_bytes(),
self.dr_id.as_bytes(),
&dr_height.to_be_bytes(),
&reveal_body_hash,
chain_id.as_bytes(),
contract_addr.as_bytes(),
]))
}
}

impl Execute {
#[allow(clippy::too_many_arguments)]
pub fn new(
dr_id: String,
reveal_body: RevealBody,
public_key: String,
stderr: Vec<String>,
stdout: Vec<String>,
Comment on lines +83 to +84
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if there should be any consideration not including these 2 fields in the signature. Any thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concern is about replaying the reveal transaction... but let's think about this.

Maybe they could be included as a sort of hash but inside of the reveal body.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to merge the PR without this, we should create an issue. :)

signing_key: &[u8],
chain_id: &str,
contract_addr: &str,
dr_height: u64,
reveal_body_hash: Hash,
) -> Result<Self> {
let mut ex = Self {
dr_id,
reveal_body,
public_key,
stderr,
stdout,
proof: Default::default(),
};
ex.proof = ex
.sign(signing_key, chain_id, contract_addr, (dr_height, reveal_body_hash))?
.to_hex();

Ok(ex)
}

pub fn verify(
&self,
public_key: &[u8],
chain_id: &str,
contract_addr: &str,
dr_height: u64,
reveal_body_hash: Hash,
) -> Result<()> {
self.verify_inner(public_key, chain_id, contract_addr, (dr_height, reveal_body_hash))
}
}

impl From<Execute> for crate::msgs::ExecuteMsg {
fn from(value: Execute) -> Self {
super::ExecuteMsg::RevealDataResult(value).into()
Expand Down
42 changes: 21 additions & 21 deletions src/msgs/data_requests/execute_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn json_commit_result() {
proof: "proof".to_string(),
}
.into();
assert_json_ok(&msg, &expected_json);
assert_json_ok(msg, expected_json);
}

#[test]
Expand All @@ -44,12 +44,12 @@ fn json_post_request() {
let consensus_filter: Bytes = "consensus_filter".as_bytes().into();

#[cfg(not(feature = "cosmwasm"))]
let gas_price = "100".to_string();
let gas_price = 100;
#[cfg(feature = "cosmwasm")]
let gas_price: U128 = 100u128.into();

#[cfg(not(feature = "cosmwasm"))]
let gas_limit = "100".to_string();
let gas_limit = 100;
#[cfg(feature = "cosmwasm")]
let gas_limit: U128 = 100u128.into();

Expand All @@ -69,16 +69,16 @@ fn json_post_request() {
let payback_address: Bytes = "payback_address".as_bytes().into();

let args = PostDataRequestArgs {
version: Version::new(1, 0, 0),
dr_binary_id: "dr_binary_id".to_string(),
dr_inputs: dr_inputs.clone(),
tally_binary_id: "tally_binary_id".to_string(),
tally_inputs: tally_inputs.clone(),
version: Version::new(1, 0, 0),
dr_binary_id: "dr_binary_id".to_string(),
dr_inputs: dr_inputs.clone(),
tally_binary_id: "tally_binary_id".to_string(),
tally_inputs: tally_inputs.clone(),
replication_factor: 1,
consensus_filter: consensus_filter.clone(),
gas_price: gas_price.clone(),
gas_limit: gas_limit.clone(),
memo: memo.clone(),
consensus_filter: consensus_filter.clone(),
gas_price,
gas_limit,
memo: memo.clone(),
};
let expected_json = json!({
"post_data_request": {
Expand All @@ -90,8 +90,8 @@ fn json_post_request() {
"tally_inputs": tally_inputs,
"replication_factor": 1,
"consensus_filter": consensus_filter,
"gas_price": gas_price,
"gas_limit": gas_limit,
"gas_price": gas_price.to_string(),
"gas_limit": gas_limit.to_string(),
"memo": memo
},
"seda_payload": seda_payload,
Expand All @@ -104,13 +104,13 @@ fn json_post_request() {
payback_address,
}
.into();
assert_json_ok(&msg, &expected_json);
assert_json_ok(msg, expected_json);
}

#[test]
fn json_reveal_result() {
#[cfg(not(feature = "cosmwasm"))]
let gas_used = "100".to_string();
let gas_used = 100;
#[cfg(feature = "cosmwasm")]
let gas_used: U128 = 100u128.into();

Expand All @@ -120,18 +120,18 @@ fn json_reveal_result() {
let reveal: Bytes = "reveal".as_bytes().into();

let reveal_body = RevealBody {
salt: "salt".to_string(),
salt: "salt".to_string(),
exit_code: 0,
gas_used: gas_used.clone(),
reveal: reveal.clone(),
gas_used,
reveal: reveal.clone(),
};
let expected_json = json!({
"reveal_data_result": {
"dr_id": "dr_id",
"reveal_body": {
"salt": "salt",
"exit_code": 0,
"gas_used": gas_used,
"gas_used": gas_used.to_string(),
"reveal": reveal,
},
"public_key": "public_key",
Expand All @@ -149,5 +149,5 @@ fn json_reveal_result() {
stdout: vec!["some-output".to_string()],
}
.into();
assert_json_ok(&msg, &expected_json);
assert_json_ok(msg, expected_json);
}
2 changes: 1 addition & 1 deletion src/msgs/data_requests/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::*;

#[cfg_attr(feature = "cosmwasm", cw_serde)]
#[cfg_attr(feature = "cosmwasm", derive(QueryResponses))]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize))]
#[cfg_attr(not(feature = "cosmwasm"), derive(Serialize, Debug, PartialEq))]
#[cfg_attr(not(feature = "cosmwasm"), serde(rename_all = "snake_case"))]
pub enum QueryMsg {
#[cfg_attr(feature = "cosmwasm", returns(Option<DataRequest>))]
Expand Down
Loading