pub mod order; pub mod sign; pub mod verify; #[cfg(test)] mod tests { use crate::order::{Order, OrderSignature}; use crate::{sign, verify}; use cosmrs::AccountId; use nym_validator_client::signing::direct_wallet::DirectSecp256k1HdWallet; use std::str::FromStr; fn get_order(prefix: &str) -> anyhow::Result<(OrderSignature, String)> { let mnemonic = "crush minute paddle tobacco message debate cabin peace bar jacket execute twenty winner view sure mask popular couch penalty fragile demise fresh pizza stove"; let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic.parse()?); let accounts = wallet.try_derive_accounts()?; let message = "This is the order message from Bity"; let signature = sign::sign_order(&wallet, &accounts[0], message.to_string())?; Ok((signature, message.to_string())) } #[test] fn integration_happy_path() -> anyhow::Result<()> { let (signature, message) = get_order("n")?; let account_id = AccountId::from_str("n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf").unwrap(); assert_eq!(account_id.to_string(), signature.account_id.to_string()); println!("Order signature:"); println!("{}", ::serde_json::to_string_pretty(&signature)?); Ok(verify::verify_order(Order { account_id, signature, message, })?) } #[test] fn integration_fails_on_non_mainnet_address() -> anyhow::Result<()> { let (signature, message) = get_order("nymt")?; println!("Order signature:"); println!("{}", ::serde_json::to_string_pretty(&signature)?); let res = verify::verify_order(Order { account_id: signature.clone().account_id, signature, message, }); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } #[test] fn integration_fails_on_non_mainnet_address_variant2() -> anyhow::Result<()> { let (signature, message) = get_order("atom")?; println!("Order signature:"); println!("{}", ::serde_json::to_string_pretty(&signature)?); let res = verify::verify_order(Order { account_id: signature.clone().account_id, signature, message, }); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } #[test] fn integration_change_account_id() -> anyhow::Result<()> { let (signature, message) = get_order("n")?; let OrderSignature { signature_as_hex, public_key, account_id: _, } = signature; // use a different account id to the one that signed the order let account_id = AccountId::from_str("n1h5hgn94nsq4kh99rjj794hr5h5q6yfm2lr52es").unwrap(); let res = verify::verify_order(Order { account_id: account_id.clone(), signature: OrderSignature { account_id, signature_as_hex, public_key, }, message, }); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } #[test] fn integration_change_signature() -> anyhow::Result<()> { let (signature, message) = get_order("n")?; let OrderSignature { signature_as_hex: _, public_key, account_id, } = signature; let res = verify::verify_order(Order { account_id: account_id.clone(), signature: OrderSignature { account_id, signature_as_hex: "this is not the signature you were looking for".to_string(), public_key, }, message, }); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } #[test] fn integration_with_json_happy_path() -> anyhow::Result<()> { let json_order = r#"{ "account_id": "n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf", "message": "This is the order message from Bity", "signature": { "public_key": { "@type": "/cosmos.crypto.secp256k1.PubKey", "key": "A/zqdyeyPhCEXB9pyVLdNb5er+eds5ayboCdEEHK3Uom" }, "account_id": "n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf", "signature_as_hex": "31C522B9B5C522A93CE14BE38E2D380CA166F69E952DF6F5D45B3B9CCDAAFE9115FBDF8539092986391C46885242E6E4CF806EEC1BB869A28D0E6D347C52121A" } }"#; let order: Order = serde_json::from_str(json_order)?; Ok(verify::verify_order(order)?) } #[test] fn integration_with_json_bad_signature() -> anyhow::Result<()> { let json_order = r#"{ "account_id": "n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf", "message": "A different message to the one signed", "signature": { "public_key": { "@type": "/cosmos.crypto.secp256k1.PubKey", "key": "A/zqdyeyPhCEXB9pyVLdNb5er+eds5ayboCdEEHK3Uom" }, "account_id": "n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf", "signature_as_hex": "31C522B9B5C522A93CE14BE38E2D380CA166F69E952DF6F5D45B3B9CCDAAFE9115FBDF8539092986391C46885242E6E4CF806EEC1BB869A28D0E6D347C52121A" } }"#; let order: Order = serde_json::from_str(json_order)?; let res = verify::verify_order(order); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } #[test] fn integration_with_json_bad_account_id() -> anyhow::Result<()> { let json_order = r#"{ "account_id": "n1h5hgn94nsq4kh99rjj794hr5h5q6yfm2lr52es", "message": "This is the order message from Bity", "signature": { "public_key": { "@type": "/cosmos.crypto.secp256k1.PubKey", "key": "A/zqdyeyPhCEXB9pyVLdNb5er+eds5ayboCdEEHK3Uom" }, "account_id": "n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf", "signature_as_hex": "31C522B9B5C522A93CE14BE38E2D380CA166F69E952DF6F5D45B3B9CCDAAFE9115FBDF8539092986391C46885242E6E4CF806EEC1BB869A28D0E6D347C52121A" } }"#; let order: Order = serde_json::from_str(json_order)?; let res = verify::verify_order(order); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } #[test] fn integration_with_json_bad_account_id_variation_2() -> anyhow::Result<()> { let json_order = r#"{ "account_id": "n1jw6mp7d5xqc7w6xm79lha27glmd0vdt3l9artf", "message": "This is the order message from Bity", "signature": { "public_key": { "@type": "/cosmos.crypto.secp256k1.PubKey", "key": "A/zqdyeyPhCEXB9pyVLdNb5er+eds5ayboCdEEHK3Uom" }, "account_id": "n1h5hgn94nsq4kh99rjj794hr5h5q6yfm2lr52es", "signature_as_hex": "31C522B9B5C522A93CE14BE38E2D380CA166F69E952DF6F5D45B3B9CCDAAFE9115FBDF8539092986391C46885242E6E4CF806EEC1BB869A28D0E6D347C52121A" } }"#; let order: Order = serde_json::from_str(json_order)?; let res = verify::verify_order(order); println!("Expecting error, got: {:?}", res); assert!(res.is_err()); Ok(()) } }