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 extension sig support #946

Merged
merged 7 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion primitives/orderbook/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ rand = { version = "0.8.5", optional = true }
serde = { workspace = true, default-features = false }
serde_with = { version = "3.6.1", features = ["json", "macros"], default-features = false }
log = { workspace = true, default-features = false }
serde_json = { workspace = true }
anyhow = { version = "1.0.69", default-features = false }
rust_decimal = { git = "https://github.com/Polkadex-Substrate/rust-decimal.git", branch = "master", features = [
"scale-codec",
], default-features = false }

hex = { workspace = true }

[dev-dependencies]
serde_json = "1.0.94"
Expand Down
2 changes: 2 additions & 0 deletions primitives/orderbook/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub const MAX_PRICE: Balance = 10000000 * UNIT_BALANCE;

pub const FEE_POT_PALLET_ID: PalletId = PalletId(*b"ocexfees");

pub const EXT_WRAP_PREFIX: &str = "<Bytes>";
pub const EXT_WRAP_POSTFIX: &str = "</Bytes>";
#[cfg(test)]
mod test {
use crate::constants::{MAX_PRICE, MAX_QTY, POLKADEX_MAINNET_SS58};
Expand Down
4 changes: 4 additions & 0 deletions primitives/orderbook/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,7 @@ impl<AccountId> LiquidityMiningCrowdSourcePallet<AccountId> for () {

fn stop_accepting_lmp_withdrawals(_epoch: u16) {}
}

pub trait VerifyExtensionSignature<AccountId> {
fn verify_extension_signature(&self, payload: &str, account_id: &AccountId) -> bool;
}
68 changes: 65 additions & 3 deletions primitives/orderbook/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use std::{
ops::{Mul, Rem},
str::FromStr,
};

pub type OrderId = H256;

/// Defined account information required for the "Orderbook" client.
Expand Down Expand Up @@ -88,6 +89,14 @@ pub struct Trade {
pub time: i64,
}

impl VerifyExtensionSignature<AccountId> for MultiSignature {
fn verify_extension_signature(&self, payload: &str, account: &AccountId) -> bool {
let wrapped_payload = crate::constants::EXT_WRAP_PREFIX.to_string()
+ payload + crate::constants::EXT_WRAP_POSTFIX;
return self.verify(wrapped_payload.as_bytes(), account);
}
}

impl Trade {
/// Depends on the trade side - calculates and provides price and asset information required for
/// further balances transfers.
Expand Down Expand Up @@ -303,8 +312,10 @@ impl<AccountId: Codec + Clone + TypeInfo> WithdrawalRequest<AccountId> {
Decimal::from_str(&self.payload.amount)
}
}

use crate::ingress::{EgressMessages, IngressMessages};
use crate::ocex::TradingPairConfig;
use crate::traits::VerifyExtensionSignature;
#[cfg(not(feature = "std"))]
use core::{
ops::{Mul, Rem},
Expand All @@ -313,6 +324,7 @@ use core::{
use frame_support::{Deserialize, Serialize};
use parity_scale_codec::alloc::string::ToString;
use scale_info::prelude::string::String;
use sp_runtime::MultiSignature;
use sp_std::collections::btree_map::BTreeMap;

/// Withdraw payload requested by user.
Expand Down Expand Up @@ -644,10 +656,20 @@ impl Order {
pub fn verify_signature(&self) -> bool {
let payload: OrderPayload = self.clone().into();
let result = self.signature.verify(&payload.encode()[..], &self.user);
if !result {
log::error!(target:"orderbook","Order signature check failed");
if result {
return true;
}
result
log::error!(target:"orderbook","Order signature check failed");
let payload_str = serde_json::to_string(&payload);
if let Ok(payload_str) = payload_str {
let result =
self.signature.verify_extension_signature(&payload_str, &self.main_account);
if result {
return true;
}
}
log::error!(target:"orderbook","orderbook extension signature check failed");
false
}

/// Returns the key used for storing in orderbook
Expand Down Expand Up @@ -905,6 +927,7 @@ impl From<Order> for OrderPayload {
}
}
}

#[cfg(feature = "std")]
impl TryFrom<OrderDetails> for Order {
type Error = &'static str;
Expand Down Expand Up @@ -972,6 +995,26 @@ pub struct WithdrawalDetails {
pub signature: Signature,
}

impl WithdrawalDetails {
/// Verifies the signature.
pub fn verify_signature(&self) -> bool {
let result = self.signature.verify(self.payload.encode().as_ref(), &self.proxy);
if result {
return true;
}
log::error!(target:"orderbook","Withdrawal signature check failed");
let payload_str = serde_json::to_string(&self.payload);
if let Ok(payload_str) = payload_str {
let result = self.signature.verify_extension_signature(&payload_str, &self.main);
if result {
return true;
}
}
log::error!(target:"orderbook","Withdrawal extension signature check failed");
false
}
}

/// Overarching type used by validators when submitting
/// their signature for a summary to aggregator
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
Expand All @@ -987,10 +1030,13 @@ pub struct ApprovedSnapshot {
#[cfg(test)]
mod tests {
use crate::ingress::{EgressMessages, IngressMessages};
use crate::traits::VerifyExtensionSignature;
use crate::types::UserActions;
use polkadex_primitives::{AccountId, AssetId};
use rust_decimal::Decimal;
use sp_runtime::MultiSignature;
use std::collections::BTreeMap;
use std::str::FromStr;

#[test]
pub fn test_serialize_deserialize_user_actions() {
Expand All @@ -1006,4 +1052,20 @@ mod tests {

serde_json::to_vec(&action).unwrap();
}

#[test]
pub fn verify_signature_from_extension() {
// the string signed by polkadot-js api extension using signRaw
let payload = "hello world!";
let account =
AccountId::from_str("5FYr5g1maSsAAw6w98xdAytZ6MEQ8sNPgp3PNLgy9o79kMug").unwrap();
// raw signature from polkadot-js api signRaw
let raw_signature = "36751864552cb500ef323ad1b4bd559ade88cff9b922bfdd0b1c18ace7429f57eacc2421dc3ea38a9c434593461fcae0ffa751280e25fedb48e406e42e0f6b82";
//convert raw signature to sr25519 signature
let sig = hex::decode(raw_signature).unwrap();
let sig = sp_core::sr25519::Signature::from_slice(&sig[..]).unwrap();
let sig = MultiSignature::from(sig);
let result = sig.verify_extension_signature(&payload, &account);
assert_eq!(result, true);
}
}
Loading