Skip to content
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
8 changes: 8 additions & 0 deletions Cargo.lock

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

12 changes: 8 additions & 4 deletions crates/crypto-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ edition = "2021"
publish = false

[dependencies]
pallet-im-online = { git = "https://github.com/humanode-network/substrate", branch = "master" }
sp-consensus-babe = { git = "https://github.com/humanode-network/substrate", branch = "master" }
sp-finality-grandpa = { git = "https://github.com/humanode-network/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/humanode-network/substrate", branch = "master" }
pallet-im-online = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "master" }
sp-consensus-babe = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "master" }
sp-finality-grandpa = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "master" }
sp-runtime = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "master" }

[features]
default = ["std"]
std = ["pallet-im-online/std", "sp-consensus-babe/std", "sp-finality-grandpa/std", "sp-runtime/std"]
2 changes: 2 additions & 0 deletions crates/crypto-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Various crypto helper functions.

#![cfg_attr(not(feature = "std"), no_std)]

use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use sp_consensus_babe::AuthorityId as BabeId;
use sp_finality_grandpa::AuthorityId as GrandpaId;
Expand Down
21 changes: 14 additions & 7 deletions crates/eip712-account-claim/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,21 @@ fn make_account_claim_hash(account: &EthBytes) -> [u8; 32] {
keccak_256(&buf)
}

/// Verify EIP-712 typed signature based on provided domain_separator and entire message.
pub fn verify_account_claim(
/// Prepare the EIP-712 message hash.
pub fn make_message_hash(domain: Domain<'_>, account: &[u8]) -> [u8; 32] {
let payload_hash = make_account_claim_hash(account);
eip712_common::make_message_hash(domain, &payload_hash)
}

/// Verify EIP-712 typed signature based on provided domain and message params and recover
/// the signer address.
pub fn recover_signer(
signature: &EcdsaSignature,
domain: Domain<'_>,
account: &[u8],
) -> Option<EthereumAddress> {
let payload_hash = make_account_claim_hash(account);
eip712_common::verify_signature(signature, domain, &payload_hash)
let message = make_message_hash(domain, account);
eip712_common::recover_signer(signature, &message)
}

#[cfg(test)]
Expand Down Expand Up @@ -85,7 +92,7 @@ mod tests {
let signature = test_input(&pair);
let domain = prepare_sample_domain();

let ethereum_address = verify_account_claim(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
let ethereum_address = recover_signer(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
assert_eq!(ethereum_address, ethereum_address_from_seed(b"Alice"));
}

Expand All @@ -95,7 +102,7 @@ mod tests {
let signature = test_input(&pair);
let domain = prepare_sample_domain();

let ethereum_address = verify_account_claim(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
let ethereum_address = recover_signer(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
assert_ne!(ethereum_address, ethereum_address_from_seed(b"Bob"));
}

Expand All @@ -113,7 +120,7 @@ mod tests {
let signature = hex!("151d5f52e6c249db84b8705374c6f51dd08b50ddad5b1175ec20a7e00cbc48f55a23470ab0db16146b3b7d2a8565aaf2b700f548c9e9882a0034e654bd214e821b");

let ethereum_address =
verify_account_claim(&EcdsaSignature(signature), domain, &account_to_claim).unwrap();
recover_signer(&EcdsaSignature(signature), domain, &account_to_claim).unwrap();
assert_eq!(
ethereum_address.0,
hex!("e9726f3d0a7736034e2a4c63ea28b3ab95622cb9"),
Expand Down
16 changes: 10 additions & 6 deletions crates/eip712-common-test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ version = "0.1.0"
edition = "2021"

[dependencies]
eip712-common = { version = "0.1", path = "../eip712-common" }
primitives-ethereum = { version = "0.1", path = "../primitives-ethereum" }
eip712-common = { default-features = false, version = "0.1", path = "../eip712-common" }
primitives-ethereum = { default-features = false, version = "0.1", path = "../primitives-ethereum" }

eth-eip-712 = { package = "eip-712", version = "=0.1.0" }
eth-eip-712 = { package = "eip-712", version = "=0.1.0", optional = true }
hex-literal = "0.3"
secp256k1 = "0.22"
serde_json = "1"
sp-core = { git = "https://github.com/humanode-network/substrate", branch = "master" }
secp256k1 = { version = "0.22", optional = true }
serde_json = { version = "1", optional = true }
sp-core = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "master" }

[features]
default = ["std"]
std = ["eth-eip-712", "secp256k1", "serde_json", "eip712-common/std", "primitives-ethereum/std", "sp-core/std"]
8 changes: 5 additions & 3 deletions crates/eip712-common-test-utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Common test utils for EIP-712 typed data message construction and signature verification.

#![cfg_attr(not(feature = "std"), no_std)]

use eip712_common::*;
use primitives_ethereum::{EcdsaSignature, EthereumAddress};
pub use sp_core::{crypto::Pair, ecdsa, H256, U256};
Expand All @@ -10,8 +12,8 @@ pub fn ecdsa_pair(seed: &[u8]) -> ecdsa::Pair {
}

/// Sign a given message with the given ECDSA keypair.
pub fn ecdsa_sign(pair: &ecdsa::Pair, msg: [u8; 32]) -> EcdsaSignature {
EcdsaSignature(pair.sign_prehashed(&msg).0)
pub fn ecdsa_sign(pair: &ecdsa::Pair, msg: &[u8; 32]) -> EcdsaSignature {
EcdsaSignature(pair.sign_prehashed(msg).0)
}

/// Sign a given EIP-712 typed data JSON with the given ECDSA keypair.
Expand All @@ -20,7 +22,7 @@ pub fn ecdsa_sign_typed_data(pair: &ecdsa::Pair, type_data_json: &str) -> EcdsaS
let msg_bytes: [u8; 32] = eth_eip_712::hash_structured_data(typed_data)
.unwrap()
.into();
ecdsa_sign(pair, msg_bytes)
ecdsa_sign(pair, &msg_bytes)
}

/// Create an Ethereum address from the given seed.
Expand Down
21 changes: 13 additions & 8 deletions crates/eip712-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,28 @@ pub fn make_payload_hash<'a>(
keccak_256(&buf)
}

/// Prepare the EIP-712 message.
pub fn make_message_hash(domain: Domain<'_>, payload_hash: &[u8; 32]) -> [u8; 32] {
let domain_hash = make_domain_hash(domain);
make_eip712_message_hash(&domain_hash, payload_hash)
}

/// Extract the signer address from the signature and the message.
pub fn recover_signer(sig: &EcdsaSignature, msg: &[u8; 32]) -> Option<EthereumAddress> {
let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig.0, msg).ok()?;
Some(ecdsa_public_key_to_ethereum_address(&pubkey))
}

/// Verify EIP-712 typed signature based on provided domain and payload hash.
pub fn verify_signature(
signature: &EcdsaSignature,
domain: Domain<'_>,
payload_hash: &[u8; 32],
) -> Option<EthereumAddress> {
let domain_hash = make_domain_hash(domain);
let msg_hash = make_eip712_message_hash(&domain_hash, payload_hash);
let msg_hash = make_message_hash(domain, payload_hash);
recover_signer(signature, &msg_hash)
}

/// Extract the signer address from the signatue and the message.
fn recover_signer(sig: &EcdsaSignature, msg: &[u8; 32]) -> Option<EthereumAddress> {
let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig.0, msg).ok()?;
Some(ecdsa_public_key_to_ethereum_address(&pubkey))
}

/// Convert the ECDSA public key to Ethereum address.
fn ecdsa_public_key_to_ethereum_address(pubkey: &[u8; 64]) -> EthereumAddress {
let mut address = [0u8; 20];
Expand Down
27 changes: 17 additions & 10 deletions crates/eip712-token-claim/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,24 @@ fn hash_token_claim_data(substrate_address: &EthBytes) -> [u8; 32] {
keccak_256(substrate_address)
}

/// Verify EIP-712 typed signature based on provided domain_separator and entire message.
pub fn verify_token_claim(
signature: &EcdsaSignature,
domain: Domain<'_>,
substrate_address: &[u8],
) -> Option<EthereumAddress> {
/// Prepare the EIP-712 message hash.
pub fn make_message_hash(domain: Domain<'_>, substrate_address: &[u8]) -> [u8; 32] {
let payload_hash = make_payload_hash(
&TOKEN_CLAIM_TYPEHASH,
[&hash_token_claim_data(substrate_address)],
);
eip712_common::verify_signature(signature, domain, &payload_hash)
eip712_common::make_message_hash(domain, &payload_hash)
}

/// Verify EIP-712 typed signature based on provided domain and message params and recover
/// the signer address.
pub fn recover_signer(
signature: &EcdsaSignature,
domain: Domain<'_>,
substrate_address: &[u8],
) -> Option<EthereumAddress> {
let message = make_message_hash(domain, substrate_address);
eip712_common::recover_signer(signature, &message)
}

#[cfg(test)]
Expand Down Expand Up @@ -83,7 +90,7 @@ mod tests {
let signature = test_input(&pair);
let domain = prepare_sample_domain();

let ethereum_address = verify_token_claim(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
let ethereum_address = recover_signer(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
assert_eq!(ethereum_address, ethereum_address_from_seed(b"Alice"));
}

Expand All @@ -93,7 +100,7 @@ mod tests {
let signature = test_input(&pair);
let domain = prepare_sample_domain();

let ethereum_address = verify_token_claim(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
let ethereum_address = recover_signer(&signature, domain, &SAMPLE_ACCOUNT).unwrap();
assert_ne!(ethereum_address, ethereum_address_from_seed(b"Bob"));
}

Expand All @@ -114,7 +121,7 @@ mod tests {
let signature = hex!("3027e569de1d835350ffa4f07218d3be7298de65f12ffc767c6d80ab16ee704245e158f660817433f3748563cf83cf8a53a5ab569e7751bf158d9215f0e9b58b1b");

let ethereum_address =
verify_token_claim(&EcdsaSignature(signature), domain, &substrate_account).unwrap();
recover_signer(&EcdsaSignature(signature), domain, &substrate_account).unwrap();
assert_eq!(
ethereum_address.0,
hex!("6be02d1d3665660d22ff9624b7be0551ee1ac91b"),
Expand Down
24 changes: 20 additions & 4 deletions crates/humanode-peer/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ use std::{collections::BTreeMap, str::FromStr};
use crypto_utils::{authority_keys_from_seed, get_account_id_from_seed};
use hex_literal::hex;
use humanode_runtime::{
opaque::SessionKeys, robonode, AccountId, BabeConfig, Balance, BalancesConfig, BioauthConfig,
BootnodesConfig, ChainPropertiesConfig, EVMConfig, EthereumChainIdConfig, EthereumConfig,
EvmAccountsMappingConfig, GenesisConfig, GrandpaConfig, ImOnlineConfig, SessionConfig,
Signature, SudoConfig, SystemConfig, WASM_BINARY,
opaque::SessionKeys, robonode, token_claims::types::ClaimInfo, AccountId, BabeConfig, Balance,
BalancesConfig, BioauthConfig, BootnodesConfig, ChainPropertiesConfig, EVMConfig,
EthereumAddress, EthereumChainIdConfig, EthereumConfig, EvmAccountsMappingConfig,
GenesisConfig, GrandpaConfig, ImOnlineConfig, SessionConfig, Signature, SudoConfig,
SystemConfig, TokenClaimsConfig, WASM_BINARY,
};
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup};
Expand Down Expand Up @@ -236,6 +237,10 @@ fn testnet_genesis(
humanode_runtime::FeesPot::account_id(),
EXISTANTIAL_DEPOSIT + DEV_ACCOUNT_BALANCE,
),
(
humanode_runtime::TokenClaimsPot::account_id(),
EXISTANTIAL_DEPOSIT + DEV_ACCOUNT_BALANCE,
),
];
pot_accounts
.into_iter()
Expand Down Expand Up @@ -333,6 +338,17 @@ fn testnet_genesis(
transaction_payment: Default::default(),
fees_pot: Default::default(),
treasury_pot: Default::default(),
token_claims_pot: Default::default(),
token_claims: TokenClaimsConfig {
claims: vec![(
EthereumAddress(hex!("bf0b5a4099f0bf6c8bc4252ebec548bae95602ea")),
ClaimInfo {
balance: DEV_ACCOUNT_BALANCE,
vesting: vec![].try_into().unwrap(),
},
)],
total_claimable: Some(DEV_ACCOUNT_BALANCE),
},
}
}

Expand Down
Loading