Skip to content

Commit

Permalink
Beacon light client migrator (#282)
Browse files Browse the repository at this point in the history
* replace import_next_sync_committee to sync_committee_period_update

* Root `next_sync_committee` in `attested_header`, ref: ethereum/consensus-specs#2932

* use body hash verify `latest_execution_payload_state_root`

* sync_committee_period_update after it's finalized

* revert

* test

* verify update does not skip a sync committee period

* test beacon light client updates

* skip import too old state

* test beacon light client match spec

* test beacon light client match spec

* test beacon api

* test beacon light client match prater

* test beacon light client match mainnet

* comment

* comment

* change interface

* update BeaconLCMandatoryReward

* deploy new beacon light client

* using lodestar ssz

* change interface

* beacon lc e2e test

* finish beacon lc e2e test

* update deps

* rm log

* rm log

* beacon light client migrator

* compile blc migrator

* add block_number in light client

* flatten

* deploy bnlc migrator

* bnlc migrate script

* update flatten

* test migrator

* migrate bnlc testnet

* root next_sync_committee in attested_header

* migrate bnlc on testnet

* match spec test

* migrate on mainnet

* migrate on mainnet
  • Loading branch information
hujw77 committed Nov 29, 2022
1 parent b06a437 commit 56ad6af
Show file tree
Hide file tree
Showing 27 changed files with 290 additions and 47 deletions.
4 changes: 2 additions & 2 deletions contracts/bridge/bin/addr/prod/darwinia.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"ethlive": {
"FeeMarket": "0xD1182CddB414FfC00eF2Ce18299A1E12e1a552BE",
"FeeMarketProxy": "0xcA927Df15afb7629b79dA4713a871190315c7409",
"BeaconLightClient": "0x9C266C48F07121181d8424768f0deD0170cC63A6",
"ExecutionLayer": "0xe50F1Ddf0C8778773f07Eb2759d045Ece19F6Cc1",
"BeaconLightClient": "0xD2A37C4523542F2dFD7Cb792D2aeAd5c61C1bAAE",
"ExecutionLayer": "0xeC3c9B4d3674B3D03fdf20b082A3C2c669075990",
"BeaconLCMandatoryReward": "0xFB371c8B99ba0b239E66E0a66bB6296b00dCD09f",
"EthereumStorageVerifier": "0x1e0D6Ba9D7Ddd3f9bc121c51FA051E7826f12b9f",
"OutboundLane": "0xcA3749C8C3aF04278D596a3fBe461481B6aa1b01",
Expand Down
7 changes: 4 additions & 3 deletions contracts/bridge/bin/addr/test/pangoro.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
"goerli": {
"FeeMarket": "0x437eD31bCDE0B9FFe3454bb185a0d37988e2A0cd",
"FeeMarketProxy": "0x25ee4212CfA2DC29E6a5e4A857b9656E439259c9",
"BeaconLightClient": "0x64CEE61102be7Aef77B72Db8678f2107739d450e",
"ExecutionLayer": "0x7cf9A51AbeB2DfD4F4145e089488064fcf7840Aa",
"BeaconLightClient": "0x459aFc6f394BCd2e353d99Fd88Cb6293b8Ecc34d",
"ExecutionLayer": "0xe35A2C47aDDAEe469a0ef6722afd0aF528FfCf34",
"BeaconLCMandatoryReward": "0xFd2083e78591AfA0e280a8b59262a75CaCE34691",
"EthereumStorageVerifier": "0x0631D83Dfd95559f13Ca4426fb052f6DD6a25e8f",
"OutboundLane": "0x2f6aE7fDbB7c0c613F7923Ddce3E5b71aFE71f78",
"InboundLane": "0x8F02B779EaD342Bb431A2f6cCc7866EB1928AE88",
"LaneMessageCommitter": "0x286979170bB820801EB6148a00d2D15De63E780F"
"LaneMessageCommitter": "0x286979170bB820801EB6148a00d2D15De63E780F",
"BeaconLightClientMigrator": "0x847e77b590F956A909129C4945db30539d5Db9c5"
}
}
5 changes: 5 additions & 0 deletions contracts/bridge/bin/decode-func.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

set -e

cast --calldata-decode "import_next_sync_committee(((uint64,uint64,bytes32,bytes32,bytes32),(bytes[512],bytes),(uint64,uint64,bytes32,bytes32,bytes32),bytes32[],(bytes32[2],bytes),bytes4,uint64),((bytes[512],bytes),bytes32[]))" $1
5 changes: 3 additions & 2 deletions contracts/bridge/bin/migrate-prod.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ set -eo pipefail

export MODE=prod

. $(dirname $0)/migrate/prod/fee/darwinia.sh
. $(dirname $0)/migrate/prod/fee/ethlive.sh
# . $(dirname $0)/migrate/prod/fee/darwinia.sh
# . $(dirname $0)/migrate/prod/fee/ethlive.sh
. $(dirname $0)/migrate/prod/truth/darwinia2.sh
3 changes: 1 addition & 2 deletions contracts/bridge/bin/migrate-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ set -eo pipefail

export MODE=test

. $(dirname $0)/migrate/test/fee/pangoro-1.sh
. $(dirname $0)/migrate/test/fee/goerli.sh
. $(dirname $0)/migrate/test/truth/pangoro.m.sh
44 changes: 44 additions & 0 deletions contracts/bridge/bin/migrate/prod/truth/darwinia.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash

set -e

unset TARGET_CHAIN
unset NETWORK_NAME
unset ETH_RPC_URL
export NETWORK_NAME=darwinia
export TARGET_CHAIN=ethlive
export ETH_RPC_URL=https://rpc.darwinia.network

echo "ETH_FROM: ${ETH_FROM}"

. $(dirname $0)/base.sh

load_saddr() {
jq -r ".[\"$TARGET_CHAIN\"].\"$1\"" "$PWD/bin/addr/$MODE/$NETWORK_NAME.json"
}

load_taddr() {
jq -r ".[\"$NETWORK_NAME\"].\"$1\"" "$PWD/bin/addr/$MODE/$TARGET_CHAIN.json"
}

# beacon light client config
BLS_PRECOMPILE=0x0000000000000000000000000000000000000800
SLOT=5225184
PROPOSER_INDEX=205286
PARENT_ROOT=0x278b67c45b0684beac03e61036011eb5c58460db0cd37d297507c5dc55bc57a9
STATE_ROOT=0x5a6c1264b2a98c8fb3012ad095f3dc745f4a55b71cf4b4101defd99c32373ac8
BODY_ROOT=0x08d9d0ff508a3ca59baf53b79af98f26fa531dec17b52086f59582feae0b9e76
CURRENT_SYNC_COMMITTEE_HASH=0xe81fbd2b71e6c8f7cd599fb7964a412bcdec3ebdd9843dc92b840c7663be89e8
GENESIS_VALIDATORS_ROOT=0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95

BeaconLightClient=$(deploy BeaconLightClient \
$BLS_PRECOMPILE \
$SLOT \
$PROPOSER_INDEX \
$PARENT_ROOT \
$STATE_ROOT \
$BODY_ROOT \
$CURRENT_SYNC_COMMITTEE_HASH \
$GENESIS_VALIDATORS_ROOT)

ExecutionLayer=$(deploy ExecutionLayer $BeaconLightClient)
32 changes: 32 additions & 0 deletions contracts/bridge/bin/migrate/prod/truth/darwinia2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash

set -ex

unset TARGET_CHAIN
unset NETWORK_NAME
unset ETH_RPC_URL
export NETWORK_NAME=darwinia
export TARGET_CHAIN=ethlive
export ETH_RPC_URL=https://rpc.darwinia.network

echo "ETH_FROM: ${ETH_FROM}"

. $(dirname $0)/base.sh

load_saddr() {
jq -r ".[\"$TARGET_CHAIN\"].\"$1\"" "$PWD/bin/addr/$MODE/$NETWORK_NAME.json"
}

load_taddr() {
jq -r ".[\"$NETWORK_NAME\"].\"$1\"" "$PWD/bin/addr/$MODE/$TARGET_CHAIN.json"
}

HelixDaoMultisig=0xBd1a110ec476b4775c43905000288881367B1a88
EthereumStorageVerifier=$(load_saddr "EthereumStorageVerifier")
ExecutionLayer=$(load_saddr "ExecutionLayer")

data=$(seth calldata "changeLightClient(address)" $ExecutionLayer)
seth call -F $HelixDaoMultisig $EthereumStorageVerifier $data
seth send -F $ETH_FROM $HelixDaoMultisig "submitTransaction(address,uint,bytes)" $EthereumStorageVerifier 0 $data
count=$(seth call $HelixDaoMultisig "transactionCount()(uint)")
seth call $HelixDaoMultisig "transactions(uint)(address,uint,bytes,bool)" $(( $count - 1 ))
48 changes: 48 additions & 0 deletions contracts/bridge/bin/migrate/test/truth/pangoro.m.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash

set -e

unset TARGET_CHAIN
unset NETWORK_NAME
unset ETH_RPC_URL
export NETWORK_NAME=pangoro
export TARGET_CHAIN=goerli
# export ETH_RPC_URL=https://pangoro-rpc.darwinia.network
export ETH_RPC_URL=http://35.247.165.91:9933

. $(dirname $0)/base.sh

load_saddr() {
jq -r ".[\"$TARGET_CHAIN\"].\"$1\"" "$PWD/bin/addr/$MODE/$NETWORK_NAME.json"
}

load_taddr() {
jq -r ".[\"$NETWORK_NAME\"].\"$1\"" "$PWD/bin/addr/$MODE/$TARGET_CHAIN.json"
}

# beacon light client config
BLS_PRECOMPILE=0x0000000000000000000000000000000000000800
GENESIS_VALIDATORS_ROOT=0x043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb

HelixDaoMultisig=0x43d6711EB86C852Ec1E04af55C52a0dd51b2C743
OLD_BEACON_LC=$(load_saddr "BeaconLightClient")
EthereumStorageVerifier=$(load_saddr "EthereumStorageVerifier")

BeaconLightClientMigrator=$(dapp create src/migrate/BeaconLightClientMigrator.sol:BeaconLightClientMigrator \
$HelixDaoMultisig \
$OLD_BEACON_LC \
$EthereumStorageVerifier \
$BLS_PRECOMPILE \
$GENESIS_VALIDATORS_ROOT)

save_contract "BeaconLightClientMigrator" "$BeaconLightClientMigrator"

data=$(seth calldata "changeSetter(address)" $BeaconLightClientMigrator)
seth send $HelixDaoMultisig "submitTransaction(address,uint,bytes)" $EthereumStorageVerifier 0 $data
seth send $BeaconLightClientMigrator "migrate()"

BeaconLightClient=$(seth call $BeaconLightClientMigrator "new_beacon_lc()(address)")
save_contract "BeaconLightClient" "$BeaconLightClient"

ExecutionLayer=$(seth call $BeaconLightClientMigrator "new_execution_layer()(address)")
save_contract "ExecutionLayer" "$ExecutionLayer"
4 changes: 2 additions & 2 deletions contracts/bridge/e2e/beacon_light_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ describe("bridge e2e test: beacon light client", () => {

const tx = await subClient.executionLayer.import_latest_execution_payload_state_root(body)
await expect(tx)
.to.emit(subClient.executionLayer, "LatestExecutionPayloadStateRootImported")
.withArgs(p.state_root)
.to.emit(subClient.executionLayer, "LatestExecutionPayloadImported")
.withArgs(p.block_number, p.state_root)
})
})

5 changes: 5 additions & 0 deletions contracts/bridge/flat/BSCLightClient.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pragma abicoder v2;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}

////// src/utils/rlp/RLPEncode.sol
Expand Down Expand Up @@ -1254,6 +1255,10 @@ contract BSCLightClient is BinanceSmartChain, ILightClient {
return finalized_checkpoint.state_root;
}

function block_number() public view override returns (uint256) {
return finalized_checkpoint.number;
}

function finalized_authorities_contains(address value) external view returns (bool) {
return _finalized_authorities.contains(value);
}
Expand Down
1 change: 1 addition & 0 deletions contracts/bridge/flat/BSCStorageVerifier.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pragma abicoder v2;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}

////// src/interfaces/IVerifier.sol
Expand Down
2 changes: 1 addition & 1 deletion contracts/bridge/flat/BeaconLightClient.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ contract BeaconLightClient is BeaconLightClientUpdate, Bitfield {
require(verify_next_sync_committee(
sc_update.next_sync_committee,
sc_update.next_sync_committee_branch,
header_update.finalized_header.state_root),
header_update.attested_header.state_root),
"!next_sync_committee"
);

Expand Down
1 change: 1 addition & 0 deletions contracts/bridge/flat/DarwiniaMessageVerifier.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pragma abicoder v2;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}

////// src/interfaces/IVerifier.sol
Expand Down
1 change: 1 addition & 0 deletions contracts/bridge/flat/EthereumStorageVerifier.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pragma abicoder v2;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}

////// src/interfaces/IVerifier.sol
Expand Down
14 changes: 11 additions & 3 deletions contracts/bridge/flat/ExecutionLayer.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pragma abicoder v2;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}

////// src/utils/Math.sol
Expand Down Expand Up @@ -563,10 +564,11 @@ interface IConsensusLayer {

contract ExecutionLayer is BeaconChain, ILightClient {
bytes32 private latest_execution_payload_state_root;
uint256 private latest_execution_payload_block_number;

address public immutable CONSENSUS_LAYER;

event LatestExecutionPayloadStateRootImported(bytes32 state_root);
event LatestExecutionPayloadImported(uint256 block_number, bytes32 state_root);

constructor(address consensus_layer) {
CONSENSUS_LAYER = consensus_layer;
Expand All @@ -576,13 +578,19 @@ contract ExecutionLayer is BeaconChain, ILightClient {
return latest_execution_payload_state_root;
}

function block_number() public view override returns (uint256) {
return latest_execution_payload_block_number;
}

// follow beacon api: /eth/v2/beacon/blocks/{block_id}
function import_latest_execution_payload_state_root(BeaconBlockBody calldata body) external {
bytes32 state_root = body.execution_payload.state_root;
require(latest_execution_payload_state_root != state_root, "same");
uint256 new_block_number = body.execution_payload.block_number;
require(new_block_number > latest_execution_payload_block_number, "!new");
require(hash_tree_root(body) == IConsensusLayer(CONSENSUS_LAYER).body_root(), "!body");
latest_execution_payload_state_root = state_root;
emit LatestExecutionPayloadStateRootImported(state_root);
latest_execution_payload_block_number = new_block_number;
emit LatestExecutionPayloadImported(new_block_number, state_root);
}
}

3 changes: 2 additions & 1 deletion contracts/bridge/flat/POSALightClient.f.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pragma abicoder v2;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}

////// src/spec/POSACommitmentScheme.sol
Expand Down Expand Up @@ -515,7 +516,7 @@ contract POSALightClient is POSACommitmentScheme, EcdsaAuthority, ILightClient {
__ECDSA_init__(_relayers, _threshold, _nonce);
}

function block_number() public view returns (uint256) {
function block_number() public view override returns (uint256) {
return latest_block_number;
}

Expand Down
1 change: 1 addition & 0 deletions contracts/bridge/src/interfaces/ILightClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ pragma solidity 0.7.6;

interface ILightClient {
function merkle_root() external view returns (bytes32);
function block_number() external view returns (uint256);
}
92 changes: 92 additions & 0 deletions contracts/bridge/src/migrate/BeaconLightClientMigrator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// This file is part of Darwinia.
// Copyright (C) 2018-2022 Darwinia Network
// SPDX-License-Identifier: GPL-3.0
//
// Darwinia is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Darwinia is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Darwinia. If not, see <https://www.gnu.org/licenses/>.

pragma solidity 0.7.6;
pragma abicoder v2;

import "../truth/eth/BeaconLightClient.sol";
import "../truth/eth/ExecutionLayer.sol";


interface IEthereumStorageVerifier {
function changeLightClient(address lightclient) external;
function changeSetter(address setter) external;
}

contract BeaconLightClientMigrator {
BeaconLightClient public new_beacon_lc;
ExecutionLayer public new_execution_layer;

address public immutable HELIX_DAO;
address public immutable OLD_BEACON_LC;
address public immutable ETHEREUM_STORAGE_VERIFIER;
address public immutable BLS_PRECOMPILE;
bytes32 public immutable GENESIS_VALIDATORS_ROOT;

constructor(
address helix_dao,
address old_lc,
address verifier,
address bls,
bytes32 genesis_validators_root
) {
HELIX_DAO = helix_dao;
OLD_BEACON_LC = old_lc;
ETHEREUM_STORAGE_VERIFIER = verifier;
BLS_PRECOMPILE = bls;
GENESIS_VALIDATORS_ROOT = genesis_validators_root;
}

function migrate() public {
// fetch latest finalized header
(
uint64 slot,
uint64 proposer_index,
bytes32 parent_root,
bytes32 state_root,
bytes32 body_root
) = BeaconLightClient(OLD_BEACON_LC).finalized_header();
// current sync committee period
uint64 period = slot / 32 / 256;
// fetch current sync_committee hash
bytes32 current_sync_committee_hash = BeaconLightClient(OLD_BEACON_LC).sync_committee_roots(period);
require(current_sync_committee_hash != bytes32(0), "missing");

// new BeaconLightClient
new_beacon_lc = new BeaconLightClient(
BLS_PRECOMPILE,
slot,
proposer_index,
parent_root,
state_root,
body_root,
current_sync_committee_hash,
GENESIS_VALIDATORS_ROOT
);
// new ExecutionLayer
new_execution_layer = new ExecutionLayer(address(new_beacon_lc));
// change light client
IEthereumStorageVerifier(ETHEREUM_STORAGE_VERIFIER).changeLightClient(address(new_execution_layer));

returnSetter();
}

function returnSetter() public {
// return auth
IEthereumStorageVerifier(ETHEREUM_STORAGE_VERIFIER).changeSetter(HELIX_DAO);
}
}

0 comments on commit 56ad6af

Please sign in to comment.