Posture: How can wallets safely participate in the wave of ETH Staking?

With the successful completion of the merger of ETH2.0, the enthusiasm for staking is constantly hitting new highs. According to the current data on the chain, the total amount of stakings on the Ethereum chain has reached an astonishing more than 14 million ETH, and nearly 440,000 verification nodes are running stably, and 1000-2000 ETH are staked every day , while ensuring the security of Ethereum, these nodes are also earning huge profits.

With the addition of the validator’s proposal fee, it is expected that the profit of Nianhua will reach about 6%-10%. Looking at the well-known staking platforms currently on the market, there are almost a handful of which can safely and stably achieve this profit.

After staking 32ETH, the user will get a verifier on the chain. The verifier first enters the staking queuing system and activates in about 24 hours - 14 days. This process depends on the current number of staking queues. After activation, each verifier Period (6.4 minutes) will receive staking income.

In order to realize the above staking process, it is necessary to generate a "withdrawal certificate" for the user. The withdrawal certificate is the certificate for the user to withdraw the staked principal and income in the future, and it is also one of the most important parameters for creating a validator on the chain.

There are two main ways to generate ETH2.0 withdrawal vouchers:

After searching, the current Ledger hardware wallets on the market have implemented the EIP2334:BLS12-381 algorithm, which may be limited by development complexity or other reasons. Most hardware wallets have not yet supported this algorithm. But don’t worry, the good news is that there is still ETH1_WITHDRAWAL_PREFIX, basically all wallets that can generate ETH addresses can perfectly support it.

Next, let’s take a look at how to use these two methods so that each wallet can seamlessly integrate the ETH2.0 staking system.

How to use EIP2334:BLS12-381 method to generate withdrawal certificate?

This specification mainly defines the purpose of keys in the key tree, and is a standard for assigning keys generated by EIP-2333open in new window to specific purposes. It defines a Path string, which is the index to be used when generating the key tree of EIP-2333. This specification is not only designed as the standard of ETH2.0, but also widely adopted by other communities.

In order to ensure the safety of the funds staked by users, each verifier has two key pairs, one for fund withdrawal and transfer (withdrawal key), and the other for the verifier's signature (signing key ), the operations that the verifier can perform are divided into two sets of different keys to initiate.

(1) Withdrawal key: The withdrawal key is used to withdraw the user's staked principal and income, and it needs to be used after the official withdrawal function of ETH2.0 is launched. The key is related to the security of the user's funds, so it needs to be stored in a hardware wallet or a cold wallet.

(2) Signature key: The signature key refers to the key used by a verifier when signing messages and proposing blocks. Because the verifier must sign at least one message every epoch, the signing key needs to be stored on a third-party networked server.

(1) Basic principles

EIP2334 paths are defined by integers, and the hierarchical relationship is represented by the separator /. There are 4 levels in the path (plus master node) and at least 4 levels must be used (total of 5 including master node).

M / Purpose / Coin_Type /  Account / User


1.M represents the main node (or root) of the tree, the separator / divides the tree into multiple depths, and the symbols used in paths are specified in EIP-2333.

2.Purpose is set to 12381, which is the name of the new curve (BLS12-381).

3. Coin_Type is set to 3600 because it is the square of the coin_type (3600==60^2) of ETH1.0.

4.Account It provides users with the ability to set different keys, which can achieve different account levels for a single user.

5. User provides a set of related keys, if a single account has many related uses, it should be kept separate for security reasons.

Students who have developed HD Wallet may know this better. Modifying the last level 0 will generate a different key pair. After obtaining the withdrawal key pair, we can extract the public key as the user's ETH2.0 withdrawal certificate :

Path to withdrawal key: m/12381/3600/i/0

Path to signing key: m/12381/3600/i/0/0

(2) How to achieve it?

The specific algorithm will not be expanded here due to space reasons. To realize the complete algorithm, you need to be familiar with EIP-2333open in new window. The official Python implementation of this algorithm has been provided. , which can be converted according to the development language of the wallet itself:

https://github.com/ethereum/staking-deposit-cliopen in new window

How to use ETH1_WITHDRAWAL_PREFIX to generate a withdrawal voucher?

In order to allow the ETH1.0 wallet address to transition smoothly to the ETH2.0 staking system, the official provides a new way to convert the ETH1.0 address into an ETH2.0 withdrawal certificate. That is the method of ETH1_WITHDRAWAL_PREFIXopen in new window mentioned above.

This method supports all APP wallets, hardware wallets, WEB wallets, etc. that can generate ETH1.0 addresses. You only need to slightly change the user's ETH1.0 address to get an ETH2.0 withdrawal certificate.

The converted withdrawal vouchers are all lowercase letters. After the ETH2.0 withdrawal function is launched, the user will use the signature of the ETH1.0 address to withdraw the ETH2.0 staked amount. Please make sure that the conversion is correct.

The specific conversion method is as follows:

ETH2 withdrawal certificate = 0x01 + 11 00 + ETH1.0 address without 0x

Conversion example:
ETH1.0 deposit address: 0x5dD3BD08cBc8498C8640Abc26D19480219bB0606
ETH2.0 withdrawal certificate: 0x0100000000000000000000005dd3bd08cbc8498c8640abc26d19480219bb0606

This method is much simpler than the above method. Any wallet that supports ETH1.0 address generation can be easily accessed. Next, let’s take a look at how to use the generated ETH2.0 withdrawal certificate.

How to make the wallet support ETH2.0 staking?

After generating the ETH2.0 withdrawal certificate through the above two methods, the preparation work on the user's side is only completed. Running the ETH2 node also needs to generate a signature key pair of the verifier node. This signature key pair must be signed and associated with the user's withdrawal certificate in order to run the verifier client software on the server to help the user obtain staking income.

(1) Verification node signature key pair generation service

This service has only one function, which is to let the user pass in the withdrawal certificate, generate the verification node signature key pair of this certificate on the server side, and return some parameters after the signature to the user side, and the user calls the ETH2.0 official staking contract through the wallet can be passed in.

Since the official has provided the source code of related tools for key pair generation, you can directly modify the official ETH-Staking-Deposit-CLIopen in new window tool to reduce development cost.

Why is such a backend service needed? Can't users use this tool to generate the verifier key and then upload it to the wallet? Of course, but as the node operator, the wallet must make the user’s staking process simple enough on the one hand, and ensure the security of the verification node key on the other hand. If the verification node key is run by two clients at the same time, the ETH chain will immediately punish or even confiscate the node for security reasons. If the verification node key is in the hands of the user, it is difficult to determine who caused the slashing.

After the final transformation is completed, the user's withdrawal certificate will be passed in, and two files will be generated, among which keystore-*.json is the verification node signature key to be run on the server, which needs to be kept safely by the node operator. And deposit_*.json is to pass in the parameters of the official staking deposit contract, which needs to be returned to the front end. These parameters are required to call the staking contract, and its content structure is roughly as follows:

{
    // validator public key
    "pubkey": "86ee4eecf1c83725020cf8667c555b286b54445691da44aa7a671b6d18abf118452e60876216f9adec5e64ff09c3e231",
    // withdrawal certificate
    "withdrawal_credentials": "0100000000000000000000005dd3bd08cbc8498c8640abc26d19480219bb0606",
    // validator signature
    "signature":"a61e5ed96b5b22ec9da92cf3f09c24cf9230ec1db99918e9dedfc9440de473f64b7520b5fb40558d0bc9f009dd20731917c3dbf6b3cfd98b48377a190d9e2959df3d2fa2dcec9c09e8be420accc9daa25301d4a2ce1636a5413ac066e7a4628f",
    // Merkle root
    "deposit_data_root": "ebb84a75e241501cc64c4e42dd3cdb7a2f72e6af60ab828b2fb246905eb629e5",
    //ETH network
    "network_name":"Goerli"
}

(2) Call ETH2.0 official deposit contract staking

So far, all the data required for staking is available. The above JSON object contains the parameters that need to be passed in by the official staking deposit contract. Now let’s call the contract to complete the staking process.

ETH2.0 official deposit contract: 0x00000000219ab540356cbb839cbe05303d7705faopen in new window

Let's take javascript as an example to call the official contract staking to create a verification node:



// import library
import { ethers } from "ethers";

// Connect to Metamask wallet
const provider = new ethers.providers.Web3Provider(window.ethereum)
await provider. send("eth_requestAccounts", []);
const signer = provider. getSigner();
let userAddress = await signer. getAddress();

// Initialize contract parameters
const kelepool = {
  address: "0x00000000219ab540356cbb839cbe05303d7705fa", // official contract
  abi: [{"anonymous":false....}] // official contract ABI, refer to contract link for details
};
const contract = new ethers.Contract(kelepool.address, kelepool.abi, signer);


// Assemble staking data (support one user to create multiple validator nodes at the same time)
let data = {
    // validator public key
    "pubkey": "86ee4eecf1c83725020cf8667c555b286b54445691da44aa7a671b6d18abf118452e60876216f9adec5e64ff09c3e231",
    // withdrawal certificate
    "withdrawal_credentials": "0100000000000000000000005dd3bd08cbc8498c8640abc26d19480219bb0606",
    // validator signature
    "signature":"a61e5ed96b5b22ec9da92cf3f09c24cf9230ec1db99918e9dedfc9440de473f64b7520b5fb40558d0bc9f009dd20731917c3dbf6b3cfd98b48377a190d9e2959df3d2fa2dcec9c09e8be420accc9daa25301d4a2ce1636a5413ac066e7a4628f",
    // Merkle root
    "deposit_data_root": "ebb84a75e241501cc64c4e42dd3cdb7a2f72e6af60ab828b2fb246905eb629e5",
    // ETH network (mainnet should be used for the main network)
    "network_name":"Goerli"
}

// generate staking contract parameters
let prefix = '0x'
let pubkey = ethers.utils.arrayify(prefix + data.pubkey)
let withdrawal_credentials = ethers.utils.arrayify(prefix + data.withdrawal_credentials)
let signature = ethers.utils.arrayify(prefix + data.signature)
let deposit_data_root = data. deposit_data_root

// Execute the contract staking method. If the number of verification nodes above is N, the staking amount must be an integer multiple of 32ETH*N
let amount = ethers. utils. parseUnits('32', 'ether')
const tx = await contract. deposit(pubkey, withdrawal_credentials, signature, deposit_data_root, {
    from: userAddress, // caller account
    value: amount, // staking amount
    gasLimit: 10000000 // Maximum gas limit
})
console.log(`Transaction hash: ${tx.hash}`);

(3) Run the verification node client

After the call contract staking is completed, there is already a verifier on the ETH2.0 chain with a balance of 32ETH, and it may take about 24 hours to 14 days to take effect, depending on the number of staking queues.

Now it is time to run a validator client, perform block signing and secure the ETH network, and at the same time earn the benefits of network rewards.

Choose a client to run the validator on:

-Nimbus

-Prysm

  • Lighthouse

  • Teku

Here, Lighthouse is used to run the verification node, and using Docker will make the whole process easier:

For detailed installation method, please refer to the official tutorial:

https://lighthouse-book.sigmaprime.io/mainnet-validator.htmlopen in new window

Start the beacon chain:

$ docker run \
    --network host \
    -v $HOME/.lighthouse:/root/.lighthouse sigp/lighthouse \
    lighthouse --network mainnet bn --staking --http-address 0.0.0.0

Start the validator:


$ docker run \
    --network host \
    -v $HOME/.lighthouse:/root/.lighthouse \
    sigp/lighthouse \
    lighthouse --network mainnet vc


$ docker run -it \
    -v $HOME/.lighthouse:/root/.lighthouse \
    -v $(pwd)/validator_keys:/root/validator_keys \
    sigp/lighthouse \
    lighthouse --network mainnet account validator import --directory /root/validator_keys

Note here that the validator key is stored in /root/validator_keys, and docker will automatically import your key.

(4) Query node status

Finally, you can query the status on the official validator node browser:

https://beaconcha.in/validator/validator node public keyopen in new window

In conclusion

The above is the entire staking process of ETH2.0. If there is no accident during the process, your validator node will be activated in about (24 hours - 14 days), depending on the current staking queue situation. After the verifier is activated, every 6.4 minutes will see income entering the balance.

At present, there are also some platforms that provide one-stop access services. The wallet side only needs to simply integrate to have all the above functions, such as [Coke Pool](https://docs.kelepool.com/zh/ developers/ethereum/api/Hardware.html), you can choose according to your own needs.