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

add verifier middleware #678

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
82 changes: 82 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ members = [
"packages/*",
"test-contracts/*",
"ci/*",
"contracts/external/*"
"contracts/external/*",
"contracts/external/cw-verifier-middleware/derive"
]
exclude = ["ci/configs/"]

Expand Down Expand Up @@ -49,19 +50,28 @@ cw4 = "0.16"
cw4-group = "0.16"
cw721 = "0.16"
cw721-base = "0.16"
serde_json = "1.0"
proc-macro2 = "1.0"
quote = "1.0"
rand = "0.8"
serde = { version = "1.0", default-features = false, features = ["derive"]}
syn = { version = "1.0", features = ["derive"] }
thiserror = { version = "1.0.30" }
wynd-utils = "0.4.1"
secp256k1 = "0.26.0"
sha2 = "0.10.6"
bip32 = "0.4.0"
hex = "0.4.3"
ripemd = "0.1.3"
bech32 = "0.9.1"
bincode = "1.3"

# One commit ahead of version 0.3.0. Allows initialization with an
# optional owner.
cw-ownable = { git = "https://github.com/steak-enjoyers/cw-plus-plus", rev = "50d4d9333305894457e5028072a0465f4635b15b" }

cw-admin-factory = { path = "./contracts/external/cw-admin-factory" }
cw-verifier-middleware = { path = "./contracts/external/cw-verifier-middleware"}
cw-denom = { path = "./packages/cw-denom", version = "*" }
cw-hooks = { path = "./packages/cw-hooks", version = "*" }
cw-wormhole = { path = "./packages/cw-wormhole", version = "*" }
Expand Down Expand Up @@ -93,6 +103,7 @@ dao-voting-cw4 = { path = "./contracts/voting/dao-voting-cw4", version = "*" }
dao-voting-cw721-staked = { path = "./contracts/voting/dao-voting-cw721-staked", version = "*" }
dao-voting-native-staked = { path = "./contracts/voting/dao-voting-native-staked", version = "*" }


# v1 dependencies. used for state migrations.
cw-core-v1 = { package = "cw-core", version = "0.1.0", git = "https://github.com/DA0-DA0/dao-contracts.git", tag = "v1.0.0" }
cw-proposal-single-v1 = { package = "cw-proposal-single", version = "0.1.0", git = "https://github.com/DA0-DA0/dao-contracts.git", tag = "v1.0.0" }
Expand Down
23 changes: 23 additions & 0 deletions contracts/external/cw-verifier-middleware/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "cw-verifier-middleware"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cosmwasm-std = { workspace = true}
thiserror = { workspace = true }
sha2 = { workspace = true }
cosmwasm-schema = { workspace = true }
cw-storage-plus = { workspace = true }
cw-utils = {workspace = true}
hex = { workspace = true }
bip32 = { workspace = true }
ripemd = { workspace = true }
bech32 = { workspace = true }
serde_json = { workspace = true}
secp256k1 = { workspace = true }

[dev-dependencies]
secp256k1 = { workspace = true, features = ["rand-std", "bitcoin-hashes-std"] }
3 changes: 3 additions & 0 deletions contracts/external/cw-verifier-middleware/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
TODO

![](https://user-images.githubusercontent.com/30676292/214428970-aabed2eb-7271-4a91-a641-23d004f04512.png)
19 changes: 19 additions & 0 deletions contracts/external/cw-verifier-middleware/derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "derive"
version = "0.1.0"
edition = "2021"

[dependencies]
dao-macros = { workspace = true }
cosmwasm-std = { workspace = true}
serde = { workspace = true, features = ["derive"]}
serde_derive = { workspace = true }
serde_json = { workspace = true }
proc-macro2 = { workspace = true }
quote = { workspace = true }
syn = { workspace = true }

[lib]
name = "derive"
path = "lib.rs"
proc-macro = true
21 changes: 21 additions & 0 deletions contracts/external/cw-verifier-middleware/derive/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};
use proc_macro::TokenStream;
use quote::quote;
use serde::de::DeserializeOwned;
use std::error::Error;

#[proc_macro_attribute]
pub fn cw_verifier_execute(metadata: TokenStream, input: TokenStream) -> TokenStream {
merge_variants(
metadata,
input,
quote! {
enum Right {
VerifyAndExecuteSignedMessage {
msg: ::cw_verifier_middleware::WrappedMessage
},
}
}
.into(),
)
}
44 changes: 44 additions & 0 deletions contracts/external/cw-verifier-middleware/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use bech32::Error as Bech32Error;

use cosmwasm_std::OverflowError;
use cosmwasm_std::{StdError, VerificationError};
use hex::FromHexError;
use secp256k1::Error as Secp256k1Error;
use serde_json::Error as SerdeError;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),

#[error("{0}")]
FromHexError(#[from] FromHexError),

#[error("{0}")]
VerificationError(#[from] VerificationError),

#[error("{0}")]
Bech32Error(#[from] Bech32Error),

#[error("{0}")]
Secp256k1Error(#[from] Secp256k1Error),

#[error("{0}")]
OverflowError(#[from] OverflowError),

#[error("{0}")]
SerdeError(#[from] SerdeError),

#[error("Invalid nonce")]
InvalidNonce,

#[error("Message expiration has passed")]
MessageExpired,

#[error("Message signature is invalid")]
SignatureInvalid,

#[error("Invalid uncompressed public key hex string length; expected 130 bytes, got {length}")]
InvalidPublicKeyLength { length: usize },
}
10 changes: 10 additions & 0 deletions contracts/external/cw-verifier-middleware/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]

pub mod error;
pub mod msg;
pub mod state;
pub mod utils;
pub mod verify;

#[cfg(test)]
mod testing;
22 changes: 22 additions & 0 deletions contracts/external/cw-verifier-middleware/src/msg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Binary, HexBinary, Uint128};
use cw_utils::Expiration;

#[cw_serde]
pub struct WrappedMessage {
pub payload: Payload,
// Assumes signature is 'payload' hashed, signed, and base64 encoded
pub signature: Binary,
pub public_key: HexBinary, // hex encoded
}

#[cw_serde]
pub struct Payload {
pub nonce: Uint128,
pub contract_address: String,
pub chain_id: String,
pub msg: Binary,
pub expiration: Option<Expiration>,
pub bech32_prefix: String,
pub contract_version: String,
}
11 changes: 11 additions & 0 deletions contracts/external/cw-verifier-middleware/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_std::{Addr, Uint128};
use cw_storage_plus::{Item, Map};

/// Nonce for each public key, contract addr, contract version thruple
pub const NONCES: Map<(&str, &Addr, &str), Uint128> = Map::new("pk_to_nonce");

/// Contract address for which this middleware is used.
/// We require the contract address as part of the
/// payload to prevent replay attacks across contracts (a nonce may be used multiple times if there is no other
/// way to determine that it has already be used).
pub const CONTRACT_ADDRESS: Item<String> = Item::new("contract_address");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// TODO: test where a wrapped message passed to the verifier contains
// a payload with a large (in size) msg that was pre-signed
#[test]
fn test_verify_big_payload() {
}

2 changes: 2 additions & 0 deletions contracts/external/cw-verifier-middleware/src/testing/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod adversarial_tests;
mod tests;
Loading