Skip to content

Commit

Permalink
refactor(minor-ampd): separate generic public key for multisig signin…
Browse files Browse the repository at this point in the history
…g and cosmos public key for tx signing (#730)
  • Loading branch information
fish-sammy authored Dec 23, 2024
1 parent f9243a4 commit fbbb8d5
Show file tree
Hide file tree
Showing 16 changed files with 294 additions and 114 deletions.
2 changes: 0 additions & 2 deletions Cargo.lock

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

3 changes: 1 addition & 2 deletions ampd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ cosmwasm-std = { workspace = true, features = ["stargate"] }
der = { version = "0.7.9", features = ["derive"] }
deref-derive = "0.1.0"
dirs = "5.0.1"
ecdsa = { version = "0.16.6" }
ed25519 = { version = "2.2.3", default-features = false }
ed25519-dalek = { workspace = true }
enum-display-derive = "0.1.1"
error-stack = { workspace = true }
ethers-contract = { workspace = true }
Expand Down
30 changes: 15 additions & 15 deletions ampd/src/broadcaster/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use typed_builder::TypedBuilder;

use crate::tofnd;
use crate::tofnd::grpc::Multisig;
use crate::types::{PublicKey, TMAddress};
use crate::types::{CosmosPublicKey, TMAddress};

pub mod confirm_tx;
mod cosmos;
Expand Down Expand Up @@ -119,7 +119,7 @@ where
address_prefix: String,
#[builder(default, setter(skip))]
acc_sequence: Option<u64>,
pub_key: (String, PublicKey),
pub_key: (String, CosmosPublicKey),
config: Config,
}

Expand Down Expand Up @@ -153,7 +153,7 @@ where
})
}

fn derive_address(&mut self) -> Result<TMAddress, Error> {
fn derive_address(&self) -> Result<TMAddress, Error> {
Ok(self
.pub_key
.1
Expand Down Expand Up @@ -202,7 +202,7 @@ where
auth_query_client: Q,
address: TMAddress,
acc_sequence: Option<u64>,
pub_key: (String, PublicKey),
pub_key: (String, CosmosPublicKey),
config: Config,
}

Expand Down Expand Up @@ -239,7 +239,7 @@ where
self.signer.sign(
self.pub_key.0.as_str(),
sign_digest.into(),
&self.pub_key.1,
(&self.pub_key.1).into(),
tofnd::Algorithm::Ecdsa,
)
})
Expand Down Expand Up @@ -381,7 +381,6 @@ fn remap_account_not_found_error(
#[cfg(test)]
mod tests {
use cosmrs::bank::MsgSend;
use cosmrs::crypto::PublicKey;
use cosmrs::proto::cosmos::auth::v1beta1::{BaseAccount, QueryAccountResponse};
use cosmrs::proto::cosmos::bank::v1beta1::QueryBalanceResponse;
use cosmrs::proto::cosmos::base::abci::v1beta1::{GasInfo, TxResponse};
Expand All @@ -390,8 +389,6 @@ mod tests {
use cosmrs::proto::Any;
use cosmrs::tx::Msg;
use cosmrs::{AccountId, Coin, Denom};
use ecdsa::SigningKey;
use k256::Secp256k1;
use rand::rngs::OsRng;
use tokio::test;
use tonic::Status;
Expand All @@ -403,7 +400,7 @@ mod tests {
BasicBroadcaster, Broadcaster, Config, Error, UnvalidatedBasicBroadcaster,
};
use crate::tofnd::grpc::MockMultisig;
use crate::types::TMAddress;
use crate::types::{CosmosPublicKey, PublicKey, TMAddress};
use crate::PREFIX;

#[test]
Expand Down Expand Up @@ -631,8 +628,11 @@ mod tests {
MockBalanceQueryClient,
> {
let key_id = "key_uid".to_string();
let priv_key = SigningKey::random(&mut OsRng);
let pub_key: PublicKey = priv_key.verifying_key().into();
let priv_key = k256::ecdsa::SigningKey::random(&mut OsRng);
let pub_key = CosmosPublicKey::try_from(
PublicKey::new_secp256k1(priv_key.verifying_key().to_sec1_bytes()).unwrap(),
)
.unwrap();
let known_denom: Denom = Config::default().gas_price.denom.clone().into();

UnvalidatedBasicBroadcaster::builder()
Expand Down Expand Up @@ -724,7 +724,7 @@ mod tests {
}

// returns an account for the address corresponding to the given public key if that address is queried
fn init_mock_account_client(pub_key: PublicKey) -> MockAccountQueryClient {
fn init_mock_account_client(pub_key: CosmosPublicKey) -> MockAccountQueryClient {
let address: TMAddress = pub_key.account_id(PREFIX).unwrap().into();
let account = BaseAccount {
address: address.to_string(),
Expand All @@ -750,15 +750,15 @@ mod tests {
}

// signs a digest if the public key matches the given private key
fn init_mock_signer(key_id: String, priv_key: SigningKey<Secp256k1>) -> MockMultisig {
let pub_key: PublicKey = priv_key.verifying_key().into();
fn init_mock_signer(key_id: String, priv_key: k256::ecdsa::SigningKey) -> MockMultisig {
let pub_key = PublicKey::new_secp256k1(priv_key.verifying_key().to_sec1_bytes()).unwrap();

let mut signer = MockMultisig::default();
signer
.expect_sign()
.returning(move |actual_key_uid, data, actual_pub_key, _| {
assert_eq!(actual_key_uid, &key_id);
assert_eq!(actual_pub_key, &pub_key);
assert_eq!(actual_pub_key, pub_key);

let (signature, _) = priv_key
.sign_prehash_recoverable(<Vec<u8>>::from(data).as_slice())
Expand Down
10 changes: 5 additions & 5 deletions ampd/src/broadcaster/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use report::ResultCompatExt;
use thiserror::Error;
use typed_builder::TypedBuilder;

use crate::types::PublicKey;
use crate::types::CosmosPublicKey;

const DUMMY_CHAIN_ID: &str = "dummy_chain_id";
const DUMMY_ACC_NUMBER: u64 = 0;
Expand All @@ -29,7 +29,7 @@ where
M: IntoIterator<Item = Any>,
{
msgs: M,
pub_key: PublicKey,
pub_key: CosmosPublicKey,
acc_sequence: u64,
#[builder(default = zero_fee())]
fee: Fee,
Expand Down Expand Up @@ -110,13 +110,13 @@ mod tests {
use tokio::test;

use super::{Error, Tx, DUMMY_CHAIN_ID};
use crate::types::PublicKey;
use crate::types::CosmosPublicKey;

#[test]
async fn sign_with_should_produce_the_correct_tx() {
let priv_key = ecdsa::SigningKey::random(&mut OsRng);
let priv_key_bytes = priv_key.to_bytes();
let pub_key: PublicKey = priv_key.verifying_key().into();
let pub_key: CosmosPublicKey = priv_key.verifying_key().into();
let acc_number = 100;
let acc_sequence = 1000;
let chain_id: Id = DUMMY_CHAIN_ID.parse().unwrap();
Expand Down Expand Up @@ -160,7 +160,7 @@ mod tests {

#[test]
async fn with_dummy_sig_should_produce_the_correct_tx() {
let pub_key: PublicKey = ecdsa::SigningKey::random(&mut OsRng).verifying_key().into();
let pub_key: CosmosPublicKey = ecdsa::SigningKey::random(&mut OsRng).verifying_key().into();
let acc_sequence = 1000;
let msgs = vec![dummy_msg(), dummy_msg(), dummy_msg()];

Expand Down
14 changes: 8 additions & 6 deletions ampd/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::broadcaster::confirm_tx::TxConfirmer;
use crate::broadcaster::Broadcaster;
use crate::config::{Config as AmpdConfig, Config};
use crate::tofnd::grpc::{Multisig, MultisigClient};
use crate::types::{PublicKey, TMAddress};
use crate::types::{CosmosPublicKey, TMAddress};
use crate::{broadcaster, tofnd, Error, PREFIX};

pub mod bond_verifier;
Expand Down Expand Up @@ -80,20 +80,22 @@ impl Default for RewardsConfig {
}
}

async fn verifier_pub_key(config: tofnd::Config) -> Result<PublicKey, Error> {
MultisigClient::new(config.party_uid, config.url.clone())
async fn verifier_pub_key(config: tofnd::Config) -> Result<CosmosPublicKey, Error> {
let pub_key = MultisigClient::new(config.party_uid, config.url.clone())
.await
.change_context(Error::Connection)
.attach_printable(config.url.clone())?
.keygen(&config.key_uid, tofnd::Algorithm::Ecdsa)
.await
.change_context(Error::Tofnd)
.change_context(Error::Tofnd)?;

CosmosPublicKey::try_from(pub_key).change_context(Error::Tofnd)
}

async fn broadcast_tx(
config: AmpdConfig,
tx: Any,
pub_key: PublicKey,
pub_key: CosmosPublicKey,
) -> Result<TxResponse, Error> {
let (confirmation_sender, mut confirmation_receiver) = tokio::sync::mpsc::channel(1);
let (hash_to_confirm_sender, hash_to_confirm_receiver) = tokio::sync::mpsc::channel(1);
Expand Down Expand Up @@ -127,7 +129,7 @@ async fn broadcast_tx(

async fn instantiate_broadcaster(
config: Config,
pub_key: PublicKey,
pub_key: CosmosPublicKey,
) -> Result<(impl Broadcaster, TxConfirmer<ServiceClient<Channel>>), Error> {
let AmpdConfig {
tm_grpc,
Expand Down
2 changes: 1 addition & 1 deletion ampd/src/commands/register_public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub async fn run(config: Config, args: Args) -> Result<Option<String>, Error> {
.sign(
&multisig_address.to_string(),
address_hash.into(),
&multisig_key,
multisig_key,
args.key_type.into(),
)
.await
Expand Down
18 changes: 14 additions & 4 deletions ampd/src/grpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ mod tests {
#[test]
async fn key_should_work() {
let key_id = "key_id";
let key: PublicKey = SigningKey::random(&mut OsRng).verifying_key().into();
let key = PublicKey::new_secp256k1(
SigningKey::random(&mut OsRng)
.verifying_key()
.to_sec1_bytes(),
)
.unwrap();
let algorithm = Algorithm::Ed25519;

let mut multisig_client = MockMultisig::new();
Expand Down Expand Up @@ -123,8 +128,13 @@ mod tests {
#[test]
async fn sign_should_work() {
let key_id = "key_id";
let algorithm = Algorithm::Ed25519;
let key: PublicKey = SigningKey::random(&mut OsRng).verifying_key().into();
let algorithm = Algorithm::Ecdsa;
let key = PublicKey::new_secp256k1(
SigningKey::random(&mut OsRng)
.verifying_key()
.to_sec1_bytes(),
)
.unwrap();
let msg = b"message";
let mut hasher = Sha256::new();
hasher.update(msg);
Expand All @@ -143,7 +153,7 @@ mod tests {
.with(
predicate::eq(key_id),
predicate::eq(tofnd::MessageDigest::from(sign_digest)),
predicate::function(move |actual: &PublicKey| actual == &key),
predicate::function(move |actual| *actual == key),
predicate::eq(tofnd::Algorithm::from(algorithm)),
)
.return_once(|_, _, _, _| Ok(vec![1; 64]));
Expand Down
19 changes: 14 additions & 5 deletions ampd/src/grpc/server/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ where
let key = self.key(&req.key_id, algorithm).await?;
let signature = self
.multisig_client
.sign(&req.key_id, sign_digest.into(), &key, algorithm.into())
.sign(&req.key_id, sign_digest.into(), key, algorithm.into())
.await
.map_err(|err| Status::internal(err.to_string()))?;

Expand All @@ -85,7 +85,6 @@ where

#[cfg(test)]
mod tests {
use ecdsa::SigningKey;
use k256::sha2::{Digest, Sha256};
use mockall::predicate;
use rand::rngs::OsRng;
Expand All @@ -104,7 +103,12 @@ mod tests {
async fn sign_should_return_correct_signature() {
let key_id = "key_id";
let algorithm = proto::Algorithm::Ecdsa;
let key: PublicKey = SigningKey::random(&mut OsRng).verifying_key().into();
let key = PublicKey::new_secp256k1(
k256::ecdsa::SigningKey::random(&mut OsRng)
.verifying_key()
.to_sec1_bytes(),
)
.unwrap();
let msg = b"message";
let mut hasher = Sha256::new();
hasher.update(msg);
Expand All @@ -123,7 +127,7 @@ mod tests {
.with(
predicate::eq(key_id),
predicate::eq(tofnd::MessageDigest::from(sign_digest)),
predicate::function(move |actual: &PublicKey| actual == &key),
predicate::function(move |actual| *actual == key),
predicate::eq(tofnd::Algorithm::from(algorithm)),
)
.return_once(|_, _, _, _| Ok(vec![1; 64]));
Expand Down Expand Up @@ -162,7 +166,12 @@ mod tests {
async fn key_should_return_correct_key() {
let key_id = "key_id";
let algorithm = proto::Algorithm::Ecdsa;
let key: PublicKey = SigningKey::random(&mut OsRng).verifying_key().into();
let key = PublicKey::new_secp256k1(
k256::ecdsa::SigningKey::random(&mut OsRng)
.verifying_key()
.to_sec1_bytes(),
)
.unwrap();

let mut multisig_client = MockMultisig::default();
multisig_client
Expand Down
2 changes: 0 additions & 2 deletions ampd/src/handlers/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@ pub enum Error {
Sign,
#[error("failed to get transaction receipts")]
TxReceipts,
#[error("unsupported key type {0}")]
KeyType(String),
}
Loading

0 comments on commit fbbb8d5

Please sign in to comment.