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

[feat] Add signatures for mine method #23

Merged
merged 4 commits into from
Feb 14, 2023
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
9 changes: 6 additions & 3 deletions alice_node_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
"networks": {
"network_vec": [{
"url": "https://rpc-mumbai.maticvigil.com/",
"ledger_manager": "1AC9Fb66D542FEe49728e0da6af230dbECD6d547",
"ledger_manager": "465AAF9F6B8edb16D62344d4C100Bc69bC0e4AC7",
"id": 80001
},
{
"url": "https://data-seed-prebsc-2-s3.binance.org:8545",
"ledger_manager": "1AC9Fb66D542FEe49728e0da6af230dbECD6d547",
"ledger_manager": "465AAF9F6B8edb16D62344d4C100Bc69bC0e4AC7",
"id": 97
}],
"pair_vec": [[80001, 97], [97, 80001]],
"signer_public_key": "020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1",
"authority_manager_contract_name" : "FERRUM_QUANTUM_PORTAL_AUTHORITY_MGR",
"authority_manager_contract_version" : "000.010",
"authority_manager_contract_address" : "6036F77264bbbe1Fd601C773F21a9486313a70ec",
"authority_manager_contract_address" : "9367A0b0e80475EfADe4d4EdAd5bF64c5043C9D7",
"miner_manager_contract_name" : "FERRUM_QUANTUM_PORTAL_MINER_MGR",
"miner_manager_contract_version" : "000.010",
"miner_manager_contract_address" : "98a5282993A5d8404A29327FADfB6CD9F3Fe8ABd",
"role" : "QP_FINALIZER"
}
}
9 changes: 6 additions & 3 deletions bob_node_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
"networks": {
"network_vec": [{
"url": "https://rpc-mumbai.maticvigil.com/",
"ledger_manager": "1AC9Fb66D542FEe49728e0da6af230dbECD6d547",
"ledger_manager": "465AAF9F6B8edb16D62344d4C100Bc69bC0e4AC7",
"id": 80001
},
{
"url": "https://data-seed-prebsc-2-s3.binance.org:8545",
"ledger_manager": "1AC9Fb66D542FEe49728e0da6af230dbECD6d547",
"ledger_manager": "465AAF9F6B8edb16D62344d4C100Bc69bC0e4AC7",
"id": 97
}],
"pair_vec": [[80001, 97], [97, 80001]],
"signer_public_key": "0390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27",
"authority_manager_contract_name" : "FERRUM_QUANTUM_PORTAL_AUTHORITY_MGR",
"authority_manager_contract_version" : "000.010",
"authority_manager_contract_address" : "6036F77264bbbe1Fd601C773F21a9486313a70ec",
"authority_manager_contract_address" : "9367A0b0e80475EfADe4d4EdAd5bF64c5043C9D7",
"miner_manager_contract_name" : "FERRUM_QUANTUM_PORTAL_MINER_MGR",
"miner_manager_contract_version" : "000.010",
"miner_manager_contract_address" : "98a5282993A5d8404A29327FADfB6CD9F3Fe8ABd",
"role" : "QP_MINER"
}
}
13 changes: 8 additions & 5 deletions default_dev_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
"networks": {
"network_vec": [{
"url": "https://rpc-mumbai.maticvigil.com/",
"ledger_manager": "A8B001Ff4191F5e0D6b5DD15b8D466d8546d214b",
"ledger_manager": "1AC9Fb66D542FEe49728e0da6af230dbECD6d547",
"id": 80001
},
{
"url": "https://data-seed-prebsc-1-s1.binance.org:8545",
"ledger_manager": "A8B001Ff4191F5e0D6b5DD15b8D466d8546d214b",
"url": "https://data-seed-prebsc-2-s3.binance.org:8545",
"ledger_manager": "1AC9Fb66D542FEe49728e0da6af230dbECD6d547",
"id": 97
}],
"pair_vec": [[80001, 97], [97, 80001]],
"signer_public_key": "0390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27",
"signer_public_key": "020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1",
"authority_manager_contract_name" : "FERRUM_QUANTUM_PORTAL_AUTHORITY_MGR",
"authority_manager_contract_version" : "000.010",
"authority_manager_contract_address" : "7cD4f4B67A2cB13f46E70b37F79da1942572029E",
"authority_manager_contract_address" : "56a191D2B56202beBB1e1294e9f02D72F0d133ad",
"miner_manager_contract_name" : "FERRUM_QUANTUM_PORTAL_MINER_MGR",
"miner_manager_contract_version" : "000.010",
"miner_manager_contract_address" : "9458910F2b1f8B8c409200AC0A9C30B74DB66821",
"role" : "QP_MINER"
}
}
58 changes: 58 additions & 0 deletions ferrum-local-testnet.json

Large diffs are not rendered by default.

16 changes: 13 additions & 3 deletions node/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ pub struct NetworkConfig {
pub authority_manager_contract_version: Vec<u8>,
#[serde(with = "serde_bytes")]
pub authority_manager_contract_address: Vec<u8>,
#[serde(with = "serde_bytes")]
pub miner_manager_contract_name: Vec<u8>,
#[serde(with = "serde_bytes")]
pub miner_manager_contract_version: Vec<u8>,
#[serde(with = "serde_bytes")]
pub miner_manager_contract_address: Vec<u8>,
/// The role of this node
#[serde(with = "serde_bytes")]
pub role: Vec<u8>,
Expand All @@ -57,9 +63,13 @@ pub fn convert(network_config: NetworkConfig) -> QpConfig {
pair_vec: network_config.pair_vec,
signer_public_key: network_config.signer_public_key,
eip_712_config: EIP712Config {
contract_name: network_config.authority_manager_contract_name,
contract_version: network_config.authority_manager_contract_version,
verifying_address: network_config.authority_manager_contract_address,
finalizer_contract_name: network_config.authority_manager_contract_name,
finalizer_contract_version: network_config.authority_manager_contract_version,
finalizer_verifying_address: network_config.authority_manager_contract_address,

miner_contract_name: network_config.miner_manager_contract_name,
miner_contract_version: network_config.miner_manager_contract_version,
miner_verifying_address: network_config.miner_manager_contract_address,
},
role: role_as_bytes.into(),
}
Expand Down
1 change: 1 addition & 0 deletions pallets/quantum-portal/src/contract_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl ContractClientSignature {
}

pub fn signer(&self, hash: &H256) -> Result<ecdsa::Signature, TransactionCreationError> {
log::info!("Signer address is : {:?}", self.from);
// TODO : We should handle this properly, if the signing is not possible maybe propogate the error upstream
let signed: Result<ecdsa::Signature, TransactionCreationError> =
crypto::ecdsa_sign_prehashed(OFFCHAIN_SIGNER_KEY_TYPE, &self._signer, &hash.0)
Expand Down
10 changes: 7 additions & 3 deletions pallets/quantum-portal/src/qp_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ pub struct QpNetworkItem {
Default,
)]
pub struct EIP712Config {
pub contract_name: Vec<u8>,
pub contract_version: Vec<u8>,
pub verifying_address: Vec<u8>,
pub finalizer_contract_name: Vec<u8>,
pub finalizer_contract_version: Vec<u8>,
pub finalizer_verifying_address: Vec<u8>,

pub miner_contract_name: Vec<u8>,
pub miner_contract_version: Vec<u8>,
pub miner_verifying_address: Vec<u8>,
}

#[allow(non_camel_case_types)]
Expand Down
134 changes: 112 additions & 22 deletions pallets/quantum-portal/src/quantum_portal_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
Config,
};
use ethabi_nostd::{decoder::decode, ParamKind, Token};
use frame_support::traits::Randomness;
use sp_core::{H256, U256};
use sp_std::marker::PhantomData;
use sp_std::prelude::*;
Expand Down Expand Up @@ -280,12 +281,6 @@ impl<T: Config> QuantumPortalClient<T> {
let method_signature =
b"finalizeSingleSigner(uint256,uint256,bytes32,address[],bytes32,uint64,bytes)";

// generate randomness for salt
// let (random_hash, _) = T::PalletRandomness::random_seed();

// let random_hash = ChainUtils::keccack(b"test1");
// log::info!("random_hash {:?}", random_hash);

let salt = Token::FixedBytes(block_details.block_hash.as_ref().to_vec());
let finalizer_hash = Token::FixedBytes(block_details.block_hash.as_ref().to_vec());

Expand Down Expand Up @@ -349,10 +344,10 @@ impl<T: Config> QuantumPortalClient<T> {
) -> Result<Vec<u8>, TransactionCreationError> {
// Generate the domain seperator hash, the hash is generated from the given arguments
let domain_seperator_hash = EIP712Utils::generate_eip_712_domain_seperator_hash(
&self.eip_712_config.contract_name, // ContractName
&self.eip_712_config.contract_version, // ContractVersion
self.contract.chain_id, // ChainId
&self.eip_712_config.verifying_address, // VerifyingAddress
&self.eip_712_config.finalizer_contract_name, // ContractName
&self.eip_712_config.finalizer_contract_version, // ContractVersion
self.contract.chain_id, // ChainId
&self.eip_712_config.finalizer_verifying_address, // VerifyingAddress
);
log::info!("domain_seperator_hash {:?}", domain_seperator_hash);

Expand Down Expand Up @@ -403,7 +398,7 @@ impl<T: Config> QuantumPortalClient<T> {
log::info!("EIP712 Hash {:?}", eip_712_hash);

// Sign the eip message, we only consider a single signer here since we only expect a single key in the keystore
// TODO : Add the ability for multiple signers

let multi_sig_bytes = self.signer.signer(&eip_712_hash)?;

// Compute multisig format
Expand All @@ -430,20 +425,21 @@ impl<T: Config> QuantumPortalClient<T> {
remote_chain_id: u64,
block_nonce: u64,
txs: &Vec<QpTransaction>,
source_block: QpLocalBlock,
) -> ChainRequestResult<H256> {
let method_signature = b"mineRemoteBlock(uint64,uint64,(uint64,address,address,address,address,uint256,bytes,uint256)[],bytes32,uint64,bytes)";

let salt = Token::FixedBytes(vec![
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, 1,
]);
let expiry = Token::Uint(U256::from(2147483647));
let multi_sig = Token::Bytes(vec![
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, 1, 1,
]);
// set a random salt
let (random_hash, _) = T::PalletRandomness::random_seed();
let salt = Token::FixedBytes(Vec::from(random_hash.as_ref()));

let tx_vec = txs
// set timestamp 1hr from now
let current_timestamp = source_block.timestamp;
let expiry_buffer = core::time::Duration::from_secs(3600u64);
let expiry_time = current_timestamp.saturating_add(expiry_buffer.as_secs());
let expiry = Token::Uint(U256::from(expiry_time));

let tx_vec: Vec<Token> = txs
.iter()
.map(|t| {
Token::Tuple(vec![
Expand All @@ -459,6 +455,20 @@ impl<T: Config> QuantumPortalClient<T> {
})
.collect();

let multi_sig = self.generate_miner_signature(
remote_chain_id,
block_nonce,
tx_vec.clone(),
salt.clone(),
expiry.clone(),
)?;

log::info!(
"Encoded Miner Signature generated : {:?}",
sp_std::str::from_utf8(ChainUtils::bytes_to_hex(multi_sig.as_slice()).as_slice())
.unwrap()
);

let res = self.contract.send(
method_signature,
&[
Expand All @@ -467,7 +477,7 @@ impl<T: Config> QuantumPortalClient<T> {
Token::Array(tx_vec),
salt,
expiry,
multi_sig,
Token::Bytes(multi_sig),
],
None, // Some(U256::from(1000000 as u32)), // None,
None, // Some(U256::from(60000000000 as u64)), // None,
Expand All @@ -479,6 +489,85 @@ impl<T: Config> QuantumPortalClient<T> {
Ok(res)
}

/// Returns the Signature to sign mine transactions
/// The function will
/// 1. Generate the domain seperator values, encoded and hashed
/// 2. Generate the message hash from the (chainId, nonce, txs) and encoded it to the signature
/// 3. Generate the eip_712 type hash for the MinerSignature function
pub fn generate_miner_signature(
&self,
remote_chain_id: u64,
block_nonce: u64,
txs: Vec<Token>,
salt: Token,
expiry: Token,
) -> Result<Vec<u8>, TransactionCreationError> {
// Generate the domain seperator hash, the hash is generated from the given arguments
let domain_seperator_hash = EIP712Utils::generate_eip_712_domain_seperator_hash(
&self.eip_712_config.miner_contract_name, // ContractName
&self.eip_712_config.miner_contract_version, // ContractVersion
self.contract.chain_id, // ChainId
&self.eip_712_config.miner_verifying_address, // VerifyingAddress
);
log::info!("domain_seperator_hash {:?}", domain_seperator_hash);

// Generate the finalize method sigature to encode the finalize call
let miner_method_signature = b"MinerSignature(bytes32 msgHash,uint64 expiry,bytes32 salt)";
let miner_method_signature_hash = ChainUtils::keccack(miner_method_signature);
log::info!(
"miner_method_signature_hash {:?}",
miner_method_signature_hash
);

log::info!("remote_chain_id {:?}", remote_chain_id);
log::info!("block_nonce {:?}", block_nonce);
log::info!("txs {:?}", txs);
log::info!("salt {:?}", salt);
log::info!("expiry {:?}", expiry);

// encode the finalize call to the expected format
let encoded_message_hash = EIP712Utils::get_encoded_hash(vec![
Token::Uint(U256::from(remote_chain_id)), // remote chain id
Token::Uint(U256::from(block_nonce)), // block nonce
Token::Array(txs), // transactions
]);
log::info!("encoded_message_hash {:?}", encoded_message_hash);

// Generate the encoded eip message
let eip_args_hash = EIP712Utils::get_encoded_hash(vec![
Token::FixedBytes(Vec::from(miner_method_signature_hash.as_bytes())), // method hash
Token::FixedBytes(Vec::from(encoded_message_hash.as_bytes())), // msgHash
expiry, // expiry
salt, // salt
]);
log::info!("eip_args_hash {:?}", eip_args_hash);

let eip_712_hash =
EIP712Utils::generate_eip_712_hash(&domain_seperator_hash[..], &eip_args_hash[..]);
log::info!("EIP712 Hash {:?}", eip_712_hash);

// Sign the eip message, we only consider a single signer here since we only expect a single key in the keystore
let multi_sig_bytes = self.signer.signer(&eip_712_hash)?;

// Compute multisig format
// This computation makes it match the implementation we have in qp smart contracts repo
// refer https://github.com/ferrumnet/quantum-portal-smart-contracts/blob/326341cdfcb55052437393228f1d58e014c90f7b/test/common/Eip712Utils.ts#L93
let mut multisig_compressed: Vec<u8> = multi_sig_bytes.0[0..64].to_vec();
multisig_compressed.extend([28u8]);
multisig_compressed.extend([0u8; 31]);

log::info!(
"Extended signature of size {}: {}",
multisig_compressed.len(),
sp_std::str::from_utf8(
ChainUtils::bytes_to_hex(multisig_compressed.as_slice()).as_slice()
)
.unwrap()
);

Ok(multisig_compressed)
}

pub fn finalize(&self, chain_id: u64) -> ChainRequestResult<Option<H256>> {
log::info!("finalize({})", chain_id);
let block = self.last_remote_mined_block(chain_id)?;
Expand Down Expand Up @@ -550,6 +639,7 @@ impl<T: Config> QuantumPortalClient<T> {
remote_chain,
source_block.0.nonce,
&txs,
source_block.0,
)?))
}

Expand Down
18 changes: 18 additions & 0 deletions scripts/start-local-testnet.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

# remove any existing data from chain
rm -rf ./chain

# generate chain spec
./target/release/ferrum-network build-spec --disable-default-bootnode > ferrum-local-testnet.json

# insert the signing keys for alice
./target/release/ferrum-network key insert --key-type ofsg --scheme ecdsa --base-path ./chain/alice --chain ferrum-local-testnet.json --suri //Alice

# insert the signing keys for bob
./target/release/ferrum-network key insert --key-type ofsg --scheme ecdsa --base-path ./chain/bob --chain ferrum-local-testnet.json --suri //Bob

# start Alice node in background
./target/release/ferrum-network --chain ferrum-local-testnet.json --alice --base-path ./chain/alice --ws-port 9944 --config-file-path ./alice_node_config.json &

# start Bob node
./target/release/ferrum-network --chain ferrum-local-testnet.json --bob --base-path ./chain/bob --ws-port 9945 --config-file-path ./bob_node_config.json