Skip to content

Commit

Permalink
Deposit_v3 tooling (#2032)
Browse files Browse the repository at this point in the history
* feat: Pass signature through to popVerify precompile

* refactor: bring pop creation outside of EthereumAddress constructor

* feat: update convert-key script to take chain_id as argument

* feat: Sign over bls public key as well as an evm address, allowing for a deposit transaction to be paid for by a different account to the one staking

* feat: New precompile bls_verify

* test: Add upgraded deposit contract test

* feat: cfg validation for contract_upgrade_block_heights config var

* fix: revert convert-key changes such that pop_verify is still expected method

* fix: revert changes to z2 deployer and validator

* chore: styling

* fix: fix deployer

* chore: satisfy clippy

* feat: z2 tooling changes for deposit_v3 auth signature

* block number for withdrawal unbonding period and signingAddress

* fix: bring deposit_v3 up to date

* fix: z2 commands to support deposit auth sig

* feat: Allow address to be passed into convert-key

* feat: set contract upgrade block heights via z2

* fix: revert reward addr in example

* feat: rebase deposit_v3

* chore: update proto networks upgrade heights

* fix: convert-key improved docs in deposit.md
  • Loading branch information
86667 authored Dec 18, 2024
1 parent 9a7b365 commit 1736ed5
Showing 9 changed files with 102 additions and 26 deletions.
35 changes: 27 additions & 8 deletions z2/docs/deposit.md
Original file line number Diff line number Diff line change
@@ -11,9 +11,10 @@ z2 deposit \
--private-key <PRIVATE_KEY_OF_WALLET_WITH_MIN_10_MIL_FUND> \
--amount <AMOUNT_IN_ZIL> \
--reward-address <REWARD_ADDRESS_OF_VALIDATOR> \
--pop-signature <BLS_POP_SIGNATURE>
--signing-address <SIGNING_ADDRESS_OF_VALIDATOR> \
--deposit-auth-signature <DEPOSIT_AUTH_SIGNATURE>

Usage: z2 deposit --chain <CHAIN_NAME> --public-key <BLS_PUBLIC_KEY> --peer-id <PEER_ID> --private-key <PRIVATE_KEY_OF_WALLET_WITH_MIN_10_MIL_FUND> --amount <AMOUNT_IN_ZIL> --reward-address <REWARD_ADDRESS_OF_VALIDATOR> --pop-signature <BLS_POP_SIGNATURE>
Usage: z2 deposit --chain <CHAIN_NAME> --public-key <BLS_PUBLIC_KEY> --peer-id <PEER_ID> --private-key <PRIVATE_KEY_OF_WALLET_WITH_MIN_10_MIL_FUND> --amount <AMOUNT_IN_ZIL> --reward-address <REWARD_ADDRESS_OF_VALIDATOR> --signing-address <SIGNING_ADDRESS_OF_VALIDATOR> --deposit-auth-signature <DEPOSIT_AUTH_SIGNATURE>
```
## Parameters
* `--chain <CHAIN_NAME>`: The name of the chain. Possible values are zq2-devnet, zq2-prototestnet, zq2-protomainnet, zq2-testnet, zq2-mainnet.
@@ -22,21 +23,38 @@ Usage: z2 deposit --chain <CHAIN_NAME> --public-key <BLS_PUBLIC_KEY> --peer-id <
* `--private-key <PRIVATE_KEY_OF_WALLET_WITH_MIN_10_MIL_FUND>`: The private key of the wallet that has a minimum stake amount of 10 million.
* `--amount <AMOUNT_IN_MILLION_ZIL>`: The amount in ZIL to deposit. The valid range is from 10 million to 255 million ZIL, allowing a deposit of up to 255 million ZIL.
* `--reward-address <REWARD_ADDRESS>`: Specifies the address to receive rewards. You can generate a new wallet address to receive the rewards.
* `--pop-signature <BLS_POP_SIGNATURE>`: The BLS proof-of-possession signature of the validator node.
* `--signing-address <SIGNING_ADDRESS>`: Specifies the address which signs cross-chain events.
* `--deposit-auth-signature <DEPOSIT_AUTH_SIGNATURE>`: BLS signature of the validator node signing over control address and chain Id.

**Note**: The `--private-key` parameter should be the private key of a wallet that has secured a minimum stake amount of 10 million ZILs.

### Generating Required Values
To generate the `public-key`, `pop-signature` and `peer-id`, use the following command inside the zq2 folder. Please pass `PRIVATE_KEY_OF_VALIDATOR` to the command input.
To generate the `public-key`, `deposit-auth-signature` and `peer-id`, use the following command inside the zq2 folder. Please pass `PRIVATE_KEY_OF_VALIDATOR` and `CHAIN_ID` to the command input.


```bash
echo '{"secret_key":"<PRIVATE_KEY_OF_VALIDATOR>"}' | cargo run --bin convert-key
echo '{"secret_key":"<PRIVATE_KEY_OF_VALIDATOR>", "chain_id": <CHAIN_ID>}' | cargo run --bin convert-key
```

By default this tool signs over the address derived from the given secret key to generate the `deposit-auth-signature`, you may want to override this for example if deploying via a Delegation contract. To override pass in `"control_address": "<CONTROL_ADDRESS>"`.


#### Sample run
```bash
$ echo '{"secret_key":"96252e38af375be21d9eb30a6b88abc3836acecaeb2240731fb42e0299e14419"}' | cargo run --bin convert-key
$ echo '{"secret_key":"96252e38af375be21d9eb30a6b88abc3836acecaeb2240731fb42e0299e14419", "chain_id": 33469}' | cargo run --bin convert-key
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.67s
Running `target/debug/convert-key`
{"bls_public_key":"825124961d51c99816848875fa505b75f2e62e69937fe9bfa5fa97711845abd667f05bdc3756f7dba6b7e9e0467a3804","control_address":"0x3946f9872247af2eb4fe44c81c463e801925b8d4","deposit_auth_signature":"a53efd8bad058e4e551b7e9681613a278b782acfe05fb98d536bc95029278704adbb85891cdc7fa384ab7d5008fdd42c0ea70404ab4ec07bcf5e738c92b2be88debdc33014852ead1d9976fcbf7760043615ba74f36181fc87db21f8f8997a44","peer_id":"12D3KooWGu8PBoj6vMPafnhA2P7sLumSV1NhQJZ2W2AGiBgc5ATW","tx_pubkey":{"Ecdsa":["3056301006072A8648CE3D020106052B8104000A03420004B7C457DC36C75EADA5675629F1CE0FA93534FB76ADFC49840CC050AE2995FC87764AEB8975D049D19FDA6BFF2B3FF51608034A3FC6708F476A0C9306BA5CBE14",true]}}
```

Or with delegation contract control address:

```bash
$ echo '{"secret_key":"96252e38af375be21d9eb30a6b88abc3836acecaeb2240731fb42e0299e14419", "chain_id": 33469, "control_address": "0x81fbbe8916a4e986735296e130a87a97226480c5"}' | cargo run --bin convert-key
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.67s
Running `target/debug/convert-key`
{"address":"0x3946f9872247af2eb4fe44c81c463e801925b8d4","bls_pop_signature":"90dbc73ac9f40b75acd8279a50447f5f4e61c377f4147d1dc4b6f139b84d5c48180aae67c76db3abc4c205e4c48df5160a88ae1b84ed4869c9660458d7feb5100ccc499dbd4f2131b5a90e34261ae6ea9246abf8c32b75b1f16e63a66eec2214","bls_public_key":"825124961d51c99816848875fa505b75f2e62e69937fe9bfa5fa97711845abd667f05bdc3756f7dba6b7e9e0467a3804","peer_id":"12D3KooWGu8PBoj6vMPafnhA2P7sLumSV1NhQJZ2W2AGiBgc5ATW","tx_pubkey":{"Ecdsa":["3056301006072A8648CE3D020106052B8104000A03420004B7C457DC36C75EADA5675629F1CE0FA93534FB76ADFC49840CC050AE2995FC87764AEB8975D049D19FDA6BFF2B3FF51608034A3FC6708F476A0C9306BA5CBE14",true]}}
{"bls_public_key":"825124961d51c99816848875fa505b75f2e62e69937fe9bfa5fa97711845abd667f05bdc3756f7dba6b7e9e0467a3804","control_address":"0x81fbbe8916a4e986735296e130a87a97226480c5","deposit_auth_signature":"b4770471f1b6b798b3a5cf19b6f574724777f2fbf7b7f520e75fc8461cafcfd84114316fe2aeaf35b52b9ca519310f8c0bf5cd941426e4a78cc7e10c6da80f245a9ddadc42de3f8a35db42d633b2b03847b33883f702eb13c332988d34d68d90","peer_id":"12D3KooWGu8PBoj6vMPafnhA2P7sLumSV1NhQJZ2W2AGiBgc5ATW","tx_pubkey":{"Ecdsa":["3056301006072A8648CE3D020106052B8104000A03420004B7C457DC36C75EADA5675629F1CE0FA93534FB76ADFC49840CC050AE2995FC87764AEB8975D049D19FDA6BFF2B3FF51608034A3FC6708F476A0C9306BA5CBE14",true]}}

```

### Run z2 deposit
@@ -49,7 +67,8 @@ $ echo '{"secret_key":"96252e38af375be21d9eb30a6b88abc3836acecaeb2240731fb42e029
--peer-id 12D3KooWGu8PBoj6vMPafnhA2P7sLumSV1NhQJZ2W2AGiBgc5ATW \
--private-key 96252e38af375be21d9eb30a6b88abc3836acecaeb2240731fb42e0299e14419 \
--reward-address 0xe29a3e99a6997B1571DA24d6517e7b3acaFB5d9e \
--signing-address 0x3946f9872247af2eb4fe44c81c463e801925b8d4 \
--amount 100 \
--public-key 825124961d51c99816848875fa505b75f2e62e69937fe9bfa5fa97711845abd667f05bdc3756f7dba6b7e9e0467a3804 \
--pop-signature 90dbc73ac9f40b75acd8279a50447f5f4e61c377f4147d1dc4b6f139b84d5c48180aae67c76db3abc4c205e4c48df5160a88ae1b84ed4869c9660458d7feb5100ccc499dbd4f2131b5a90e34261ae6ea9246abf8c32b75b1f16e63a66eec2214
--deposit-auth-signature b12ab1e18e2393f165c083f9685f708aa7a1578d2685e18f4f19d950ad27c10c8dd0cf4cb637b7b215687afe861906ec064a7d89acbba718e6590cfd3baebe06bc7779028207909fff9c9c3db34f0ce812969e37d252907f9496e50bd725bb5e
```
1 change: 1 addition & 0 deletions z2/resources/config.tera.toml
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ consensus.minimum_stake = "10_000_000_000_000_000_000_000_000"
consensus.eth_block_gas_limit = 84000000
consensus.gas_price = "4_761_904_800_000"
consensus.scilla_call_gas_exempt_addrs = {{ whitelisted_evm_contract_addresses }}
consensus.contract_upgrade_block_heights = {{ contract_upgrade_block_heights }}

{%- if role == "checkpoint" %}
# Checkpoint configuration
15 changes: 11 additions & 4 deletions z2/src/bin/z2.rs
Original file line number Diff line number Diff line change
@@ -444,9 +444,12 @@ struct DepositStruct {
/// Specify the staking reward address
#[clap(long, short)]
reward_address: String,
/// Specify the Validator Proof-of-Possession
/// Specify the signing address
#[clap(long, short)]
signing_address: String,
/// Specify the Validator deposit signature
#[clap(long)]
pop_signature: String,
deposit_auth_signature: String,
}

#[derive(Args, Debug)]
@@ -962,14 +965,18 @@ async fn main() -> Result<()> {
Ok(())
}
Commands::Deposit(ref args) => {
let node =
validators::Validator::new(&args.peer_id, &args.public_key, &args.pop_signature)?;
let node = validators::Validator::new(
&args.peer_id,
&args.public_key,
&args.deposit_auth_signature,
)?;
let stake = validators::StakeDeposit::new(
node,
args.amount,
args.chain_name.get_endpoint()?,
&args.private_key,
&args.reward_address,
&args.signing_address,
)?;
validators::deposit_stake(&stake).await
}
16 changes: 16 additions & 0 deletions z2/src/chain.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ use clap::ValueEnum;
use colored::Colorize;
use strum::EnumProperty;
use strum_macros::{Display, EnumString};
use zilliqa::cfg::ContractUpgradesBlockHeights;

#[derive(Clone, Debug, ValueEnum, Display, EnumString, EnumProperty)]
// TODO: decomment when became available
@@ -151,6 +152,21 @@ impl Chain {
}
}

pub fn get_contract_upgrades_block_heights(&self) -> ContractUpgradesBlockHeights {
match self {
Self::Zq2Devnet => ContractUpgradesBlockHeights {
deposit_v3: Some(3600),
},
Self::Zq2ProtoMainnet => ContractUpgradesBlockHeights {
deposit_v3: Some(5299200),
},
Self::Zq2ProtoTestnet => ContractUpgradesBlockHeights {
deposit_v3: Some(8406000),
},
_ => ContractUpgradesBlockHeights::default(),
}
}

pub fn get_endpoint(&self) -> Result<&'static str> {
let endpoint = self.get_str("endpoint");

6 changes: 6 additions & 0 deletions z2/src/chain/node.rs
Original file line number Diff line number Diff line change
@@ -520,6 +520,7 @@ impl ChainNode {
let eth_chain_id = self.eth_chain_id.to_string();
let bootstrap_public_ip = selected_bootstrap.machine.external_address;
let whitelisted_evm_contract_addresses = self.chain()?.get_whitelisted_evm_contracts();
let contract_upgrade_block_heights = self.chain()?.get_contract_upgrades_block_heights();
// 4201 is the publically exposed port - We don't expose everything there.
let public_api = if self.role == NodeRole::Api {
// Enable all APIs, except `admin_` for API nodes.
@@ -547,6 +548,11 @@ impl ChainNode {
"whitelisted_evm_contract_addresses",
&whitelisted_evm_contract_addresses,
);
ctx.insert(
"contract_upgrade_block_heights",
&serde_json::from_value::<toml::Value>(json!(contract_upgrade_block_heights))?
.to_string(),
);
// convert json to toml formatting
let toml_servers: toml::Value = serde_json::from_value(api_servers)?;
ctx.insert("api_servers", &toml_servers.to_string());
17 changes: 14 additions & 3 deletions z2/src/deployer.rs
Original file line number Diff line number Diff line change
@@ -236,11 +236,15 @@ pub async fn get_node_deposit_commands(genesis_private_key: &str, node: &ChainNo
println!("\t--peer-id {} \\", node_ethereum_address.peer_id);
println!("\t--public-key {} \\", node_ethereum_address.bls_public_key);
println!(
"\t--pop-signature {} \\",
serde_json::to_value(node_ethereum_address.secret_key.pop_prove()).unwrap()
"\t--deposit-auth-signature {} \\",
node_ethereum_address.secret_key.deposit_auth_signature(
node.chain_id(),
node_ethereum_address.secret_key.to_evm_address()
)
);
println!("\t--private-key {} \\", genesis_private_key);
println!("\t--reward-address {} \\", ZERO_ACCOUNT);
println!("\t--staking-address {} \\", ZERO_ACCOUNT);
println!("\t--amount {VALIDATOR_DEPOSIT_IN_MILLIONS}\n");

Ok(())
@@ -289,14 +293,21 @@ pub async fn run_deposit(config_file: &str, node_selection: bool) -> Result<()>
let validator = validators::Validator::new(
&node_ethereum_address.peer_id,
&node_ethereum_address.bls_public_key,
&serde_json::to_value(node_ethereum_address.secret_key.pop_prove())?.to_string(),
&node_ethereum_address
.secret_key
.deposit_auth_signature(
node.chain_id(),
node_ethereum_address.secret_key.to_evm_address(),
)
.to_string(),
)?;
let stake = validators::StakeDeposit::new(
validator,
VALIDATOR_DEPOSIT_IN_MILLIONS,
chain.chain()?.get_endpoint()?,
&genesis_private_key,
ZERO_ACCOUNT,
ZERO_ACCOUNT,
)?;

let result = validators::deposit_stake(&stake).await;
21 changes: 14 additions & 7 deletions z2/src/validators.rs
Original file line number Diff line number Diff line change
@@ -25,18 +25,21 @@ use crate::{chain::Chain, github, utils};
pub struct Validator {
peer_id: libp2p::PeerId,
public_key: zilliqa::crypto::NodePublicKey,
pop: blsful::ProofOfPossession<Bls12381G2Impl>,
pop: blsful::Signature<Bls12381G2Impl>,
}

impl Validator {
pub fn new(peer_id: &str, public_key: &str, pop_signature: &str) -> Result<Self> {
pub fn new(peer_id: &str, public_key: &str, deposit_auth_signature: &str) -> Result<Self> {
Ok(Self {
peer_id: PeerId::from_str(peer_id).unwrap(),
public_key: NodePublicKey::from_bytes(hex::decode(public_key).unwrap().as_slice())
.unwrap(),
pop: blsful::ProofOfPossession::<Bls12381G2Impl>::try_from(
hex::decode(pop_signature).unwrap().as_slice(),
)?,
pop: blsful::Signature::Basic(
<blsful::Bls12381G2Impl as blsful::Pairing>::Signature::try_from(
hex::decode(deposit_auth_signature).unwrap(),
)
.unwrap(),
),
})
}
}
@@ -48,6 +51,7 @@ pub struct StakeDeposit {
chain_endpoint: String,
private_key: String,
reward_address: H160,
signing_address: H160,
}

impl StakeDeposit {
@@ -57,13 +61,15 @@ impl StakeDeposit {
chain_endpoint: &str,
private_key: &str,
reward_address: &str,
signing_address: &str,
) -> Result<Self> {
Ok(Self {
validator,
amount,
chain_endpoint: chain_endpoint.to_owned(),
private_key: private_key.to_owned(),
reward_address: H160(hex_string_to_u8_20(reward_address).unwrap()),
signing_address: H160(hex_string_to_u8_20(signing_address).unwrap()),
})
}
}
@@ -191,12 +197,13 @@ pub async fn deposit_stake(stake: &StakeDeposit) -> Result<()> {
.to(H160(contract_addr::DEPOSIT_PROXY.into_array()))
.value(stake.amount as u128 * 1_000_000u128 * 10u128.pow(18))
.data(
contracts::deposit::DEPOSIT
contracts::deposit_v3::DEPOSIT
.encode_input(&[
Token::Bytes(stake.validator.public_key.as_bytes()),
Token::Bytes(stake.validator.peer_id.to_bytes()),
Token::Bytes(stake.validator.pop.0.to_compressed().to_vec()),
Token::Bytes(stake.validator.pop.as_raw_value().to_compressed().to_vec()),
Token::Address(stake.reward_address),
Token::Address(stake.signing_address),
])
.unwrap(),
);
13 changes: 11 additions & 2 deletions zilliqa/src/bin/convert-key.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::io;

use alloy::primitives::Address;
use anyhow::Result;
use crypto_bigint::generic_array::GenericArray;
use serde::Deserialize;
@@ -9,6 +10,8 @@ use zilliqa::crypto::{SecretKey, TransactionPublicKey};
#[derive(Deserialize)]
struct Input {
secret_key: String,
chain_id: u64,
control_address: Option<String>,
}

fn main() -> Result<()> {
@@ -25,12 +28,18 @@ fn main() -> Result<()> {

let tx_pubkey = TransactionPublicKey::Ecdsa(k256::ecdsa::VerifyingKey::from(&ecdsa_key), true);

// default to address derived from pub key
let address = match input.control_address {
None => tx_pubkey.into_addr(),
Some(addr) => addr.parse::<Address>().unwrap(),
};

let output = json!({
"bls_public_key": secret_key.node_public_key(),
"peer_id": secret_key.to_libp2p_keypair().public().to_peer_id(),
"tx_pubkey": tx_pubkey,
"address": tx_pubkey.into_addr(),
"bls_pop_signature": secret_key.pop_prove(),
"control_address": address,
"deposit_auth_signature": hex::encode(secret_key.deposit_auth_signature(input.chain_id, address).as_raw_value().to_compressed()),
});

println!("{output}");
4 changes: 2 additions & 2 deletions zilliqa/tests/it/staking.rs
Original file line number Diff line number Diff line change
@@ -445,7 +445,7 @@ async fn validators_can_join_and_become_proposer(mut network: Network) {
assert!(!stakers.contains(&new_validator_key.node_public_key()));

let staker_wallet = network.wallet_of_node(index).await;
let deposit_pop_signature = new_validator_key.pop_prove();
let deposit_auth_signature = new_validator_key.pop_prove();

let deposit_hash = deposit_stake(
&mut network,
@@ -454,7 +454,7 @@ async fn validators_can_join_and_become_proposer(mut network: Network) {
new_validator_key,
32 * 10u128.pow(18),
reward_address,
&deposit_pop_signature.0,
&deposit_auth_signature.0,
)
.await;

0 comments on commit 1736ed5

Please sign in to comment.