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 support for trusted getter/calls that have been signed with an extension-dapp signer #1610

Merged
merged 2 commits into from
Oct 4, 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
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,7 @@ dependencies = [
name = "ita-stf"
version = "0.9.0"
dependencies = [
"base58",
"frame-support",
"frame-system",
"ita-sgx-runtime",
Expand Down
2 changes: 2 additions & 0 deletions app-libs/stf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substr

[dev-dependencies]
sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" }
base58 = { version = "0.2.0" }


[features]
default = ["std"]
Expand Down
44 changes: 43 additions & 1 deletion app-libs/stf/src/getter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use ita_sgx_runtime::{AddressMapping, HashedAddressMapping};
#[cfg(feature = "evm")]
use crate::evm_helpers::{get_evm_account, get_evm_account_codes, get_evm_account_storages};

use crate::helpers::wrap_bytes;
use itp_stf_primitives::traits::PoolTransactionValidation;
#[cfg(feature = "evm")]
use sp_core::{H160, H256};
Expand Down Expand Up @@ -143,8 +144,15 @@ impl TrustedGetterSigned {
}

pub fn verify_signature(&self) -> bool {
let encoded = self.getter.encode();

if self.signature.verify(encoded.as_slice(), self.getter.sender_account()) {
return true
};

// check if the signature is from an extension-dapp signer.
self.signature
.verify(self.getter.encode().as_slice(), self.getter.sender_account())
.verify(wrap_bytes(&encoded).as_slice(), self.getter.sender_account())
}
}

Expand Down Expand Up @@ -235,3 +243,37 @@ impl ExecuteGetter for PublicGetter {
Vec::new()
}
}

mod tests {
use super::*;

#[test]
fn extension_dapp_signature_works() {
// This is a getter, which has been signed in the browser with the `signRaw` interface,
// which wraps the data in `<Bytes>...</Bytes>`
//
// see: https://github.com/polkadot-js/extension/pull/743
let dapp_extension_signed_getter: Vec<u8> = vec![
1, 0, 6, 72, 250, 19, 15, 144, 30, 85, 114, 224, 117, 219, 65, 218, 30, 241, 136, 74,
157, 10, 202, 233, 233, 100, 255, 63, 64, 102, 81, 215, 65, 60, 1, 192, 224, 67, 233,
49, 104, 156, 159, 245, 26, 136, 60, 88, 123, 174, 171, 67, 215, 124, 223, 112, 16,
133, 35, 138, 241, 36, 68, 27, 41, 63, 14, 103, 132, 201, 130, 216, 43, 81, 123, 71,
149, 215, 191, 100, 58, 182, 123, 229, 188, 245, 130, 66, 202, 126, 51, 137, 140, 56,
44, 176, 239, 51, 131,
];
let getter = Getter::decode(&mut dapp_extension_signed_getter.as_slice()).unwrap();

if let Getter::trusted(trusted) = getter {
let g = &trusted.getter;
let signature = &trusted.signature;

// check the signature check itself works
assert!(signature.verify(wrap_bytes(&g.encode()).as_slice(), g.sender_account()));

// check that the trusted getter's method works
assert!(trusted.verify_signature())
} else {
panic!("invalid getter")
}
}
}
19 changes: 19 additions & 0 deletions app-libs/stf/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,22 @@ pub fn shard_creation_info() -> ShardCreationInfo {
target_b: maybe_target_b_info,
}
}

const PREFIX: &[u8] = b"<Bytes>";
const POSTFIX: &[u8] = b"</Bytes>";

/// This function reproduces the wrapping that occurs when the
/// `signRaw` interface is used with a signer that is injected
/// from a dapp-extension.
///
/// See: https://github.com/polkadot-js/extension/pull/743
pub fn wrap_bytes(data: &[u8]) -> Vec<u8> {
let total_len = PREFIX.len() + data.len() + POSTFIX.len();
let mut bytes_wrapped = Vec::with_capacity(total_len);

bytes_wrapped.extend_from_slice(PREFIX);
bytes_wrapped.extend_from_slice(data);
bytes_wrapped.extend_from_slice(POSTFIX);

bytes_wrapped
}
50 changes: 48 additions & 2 deletions app-libs/stf/src/trusted_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::vec::Vec;
#[cfg(feature = "evm")]
use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address};
use crate::{
helpers::{enclave_signer_account, ensure_enclave_signer_account, shard_vault},
helpers::{enclave_signer_account, ensure_enclave_signer_account, shard_vault, wrap_bytes},
Getter,
};
use codec::{Compact, Decode, Encode};
Expand Down Expand Up @@ -199,7 +199,14 @@ impl TrustedCallVerification for TrustedCallSigned {
payload.append(&mut self.nonce.encode());
payload.append(&mut mrenclave.encode());
payload.append(&mut shard.encode());
self.signature.verify(payload.as_slice(), self.call.sender_account())

if self.signature.verify(payload.as_slice(), self.call.sender_account()) {
return true
};

// check if the signature is from an extension-dapp signer.
self.signature
.verify(wrap_bytes(&payload).as_slice(), self.call.sender_account())
}
}

Expand Down Expand Up @@ -635,6 +642,21 @@ mod tests {
use itp_stf_primitives::types::KeyPair;
use sp_keyring::AccountKeyring;

use base58::FromBase58;

pub(crate) fn shard_from_base58(src: &str) -> ShardIdentifier {
ShardIdentifier::decode(
&mut src.from_base58().expect("shard has to be base58 encoded").as_slice(),
)
.unwrap()
}

pub(crate) fn mrenclave_from_base58(src: &str) -> [u8; 32] {
let mut mrenclave = [0u8; 32];
mrenclave.copy_from_slice(&src.from_base58().expect("mrenclave has to be base58 encoded"));
mrenclave
}

#[test]
fn verify_signature_works() {
let nonce = 21;
Expand All @@ -656,4 +678,28 @@ mod tests {

assert!(signed_call.verify_signature(&mrenclave, &shard));
}

#[test]
fn extension_dapp_verify_signature_works() {
// This is a getter, which has been signed in the browser with the `signRaw` interface,
// which wraps the data in `<Bytes>...</Bytes>`
//
// see: https://github.com/polkadot-js/extension/pull/743
let dapp_extension_signed_call: Vec<u8> = vec![
3, 6, 72, 250, 19, 15, 144, 30, 85, 114, 224, 117, 219, 65, 218, 30, 241, 136, 74, 157,
10, 202, 233, 233, 100, 255, 63, 64, 102, 81, 215, 65, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 110, 99, 111, 103, 110, 105, 116, 101, 101, 84, 101,
115, 116, 110, 101, 116, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 51, 1,
0, 0, 0, 1, 54, 194, 196, 95, 0, 150, 174, 244, 180, 4, 197, 64, 98, 123, 229, 37, 222,
44, 232, 93, 170, 211, 231, 95, 157, 7, 88, 164, 204, 179, 171, 14, 68, 138, 43, 37,
155, 15, 245, 130, 224, 239, 138, 44, 83, 46, 63, 200, 86, 5, 182, 47, 195, 144, 170,
1, 108, 60, 4, 72, 201, 22, 212, 143,
];
let call = TrustedCallSigned::decode(&mut dapp_extension_signed_call.as_slice()).unwrap();

let mrenclave = mrenclave_from_base58("8weGnjvG3nh6UzoYjqaTjpWjX1ouNPioA1K5134DJc5j");
let shard = shard_from_base58("5wePd1LYa5M49ghwgZXs55cepKbJKhj5xfzQGfPeMS7c");
assert!(call.verify_signature(&mrenclave, &shard))
}
}
Loading