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

Initialize beacon light client from checkpoint #828

Merged
merged 12 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[submodule "core/packages/contracts/lib/forge-std"]
path = core/packages/contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
branch = v1.4.0
branch = master
yrong marked this conversation as resolved.
Show resolved Hide resolved
[submodule "core/packages/contracts/lib/ds-test"]
path = core/packages/contracts/lib/ds-test
url = https://github.com/dapphub/ds-test
Expand Down
1 change: 0 additions & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"devDependencies": {
"husky": "^8.0.1",
"turbo": "^1.6.3",
"pnpm-deduplicate": "^0.4.1",
yrong marked this conversation as resolved.
Show resolved Hide resolved
"@remix-project/remixd": "^0.6.1"
}
}
4 changes: 2 additions & 2 deletions core/packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"typescript": "^4.8.4"
},
"dependencies": {
"@polkadot/api": "9.11.1",
"@polkadot/types": "9.11.1",
"@polkadot/api": "10.7.1",
"@polkadot/types": "10.7.1",
"@snowbridge/contracts": "workspace:*",
"ethers": "^5.7.2"
}
Expand Down
2 changes: 1 addition & 1 deletion core/packages/contracts/lib/ds-test
4 changes: 2 additions & 2 deletions core/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"@ethersproject/abi": "^5.0.0",
"@ethersproject/hdnode": "^5.7.0",
"@iarna/toml": "^2.2.5",
"@polkadot/api": "9.11.1",
"@polkadot/types": "9.11.1",
"@polkadot/api": "10.7.1",
"@polkadot/types": "10.7.1",
"@typechain/ethers-v5": "^10.1.1",
"@types/keccak": "^3.0.1",
"@types/lodash": "^4.14.186",
Expand Down
2 changes: 1 addition & 1 deletion core/packages/contracts/scripts/configure-beefy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import fs from "fs"
import path from "path"

let endpoint = process.env.RELAYCHAIN_ENDPOINT || "ws://127.0.0.1:9944"
const beefyStartBlock = process.env.BEEFY_START_BLOCK ? parseInt(process.env.BEEFY_START_BLOCK) : 15
const beefyStartBlock = process.env.BEEFY_START_BLOCK ? parseInt(process.env.BEEFY_START_BLOCK) : 12
const BeefyStateFile =
process.env.BEEFY_STATE_FILE || path.join(process.env.output_dir!, "beefy-state.json")

Expand Down
2 changes: 1 addition & 1 deletion core/packages/contracts/scripts/generateContractInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const NetworkId = process.env.ETH_NETWORK_ID || 15;
const DeployInfoFile = `./broadcast/DeployScript.sol/${NetworkId}/run-latest.json`;
const BuildInfoDir = "./out";
const DestFile =
process.argv.length >= 3 ? process.argv[2] : "/tmp/snowbridge/contracts.json";
process.argv.length >= 3 ? process.argv[2] : (process.env["output_dir"] + "/contracts.json");

const run = async () => {
let contracts = {};
Expand Down
41 changes: 14 additions & 27 deletions core/packages/contracts/test/BeefyClient.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,7 @@ import "./mocks/BeefyClientMock.sol";
import "../src/ScaleCodec.sol";
import "../src/utils/Bitfield.sol";

interface CheatCodes {
function prank(address) external;

function roll(uint256) external;

function warp(uint256) external;

function expectRevert(bytes4 message) external;

function difficulty(uint256) external;
}

contract BeefyClientTest is Test {
CheatCodes cheats = CheatCodes(HEVM_ADDRESS);
BeefyClientMock beefyClient;
uint8 randaoCommitDelay;
uint8 randaoCommitExpiration;
Expand Down Expand Up @@ -99,10 +86,10 @@ contract BeefyClientTest is Test {
beefyClient.submitInitial(commitHash, bitfield);

// mine random delay blocks
cheats.roll(block.number + randaoCommitDelay);
vm.roll(block.number + randaoCommitDelay);

// set difficulty as PrevRandao
cheats.difficulty(difficulty);
vm.prevrandao(bytes32(uint256(difficulty)));

beefyClient.commitPrevRandao(commitHash);

Expand All @@ -117,12 +104,12 @@ contract BeefyClientTest is Test {
testSubmit();

beefyClient.submitInitial(commitHash, bitfield);
cheats.roll(block.number + randaoCommitDelay);
cheats.difficulty(difficulty);
vm.roll(block.number + randaoCommitDelay);
vm.prevrandao(bytes32(uint256(difficulty)));
beefyClient.commitPrevRandao(commitHash);
BeefyClient.Commitment memory commitment = BeefyClient.Commitment(blockNumber, setId, payload);
//submit again will be reverted with StaleCommitment
cheats.expectRevert(BeefyClient.StaleCommitment.selector);
vm.expectRevert(BeefyClient.StaleCommitment.selector);
beefyClient.submitFinal(commitment, bitfield, finalValidatorProofs);
}

Expand All @@ -131,16 +118,16 @@ contract BeefyClientTest is Test {

beefyClient.submitInitial(commitHash, bitfield);

cheats.roll(block.number + randaoCommitDelay);
vm.roll(block.number + randaoCommitDelay);

cheats.difficulty(difficulty);
vm.prevrandao(bytes32(uint256(difficulty)));

beefyClient.commitPrevRandao(commitHash);

BeefyClient.Commitment memory commitment = BeefyClient.Commitment(blockNumber, setId, payload);
// invalid bitfield here
bitfield[0] = 0;
cheats.expectRevert(BeefyClient.InvalidBitfield.selector);
vm.expectRevert(BeefyClient.InvalidBitfield.selector);
beefyClient.submitFinal(commitment, bitfield, finalValidatorProofs);
}

Expand All @@ -149,20 +136,20 @@ contract BeefyClientTest is Test {
beefyClient.submitInitial(commitHash, bitfield);
BeefyClient.Commitment memory commitment = BeefyClient.Commitment(blockNumber, setId, payload);
// reverted without commit PrevRandao
cheats.expectRevert(BeefyClient.PrevRandaoNotCaptured.selector);
vm.expectRevert(BeefyClient.PrevRandaoNotCaptured.selector);
beefyClient.submitFinal(commitment, bitfield, finalValidatorProofs);
}

function testSubmitFailForPrevRandaoTooEarlyOrTooLate() public {
initialize(setId);
beefyClient.submitInitial(commitHash, bitfield);
// reverted for commit PrevRandao too early
cheats.expectRevert(BeefyClient.WaitPeriodNotOver.selector);
vm.expectRevert(BeefyClient.WaitPeriodNotOver.selector);
beefyClient.commitPrevRandao(commitHash);

// reverted for commit PrevRandao too late
cheats.roll(block.number + randaoCommitDelay + randaoCommitExpiration + 1);
cheats.expectRevert(BeefyClient.TicketExpired.selector);
vm.roll(block.number + randaoCommitDelay + randaoCommitExpiration + 1);
vm.expectRevert(BeefyClient.TicketExpired.selector);
beefyClient.commitPrevRandao(commitHash);
}

Expand All @@ -172,9 +159,9 @@ contract BeefyClientTest is Test {

beefyClient.submitInitialWithHandover(commitHash, bitfield);

cheats.roll(block.number + randaoCommitDelay);
vm.roll(block.number + randaoCommitDelay);

cheats.difficulty(difficulty);
vm.prevrandao(bytes32(uint256(difficulty)));

beefyClient.commitPrevRandao(commitHash);

Expand Down
3 changes: 1 addition & 2 deletions core/packages/test/config/launch-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ default_args = [
## Bridge Hub
[[parachains]]
id = 1013
add_to_genesis = true
chain_spec_path = "{{output_dir}}/spec.json"
chain = "bridge-hub-rococo-local"
cumulus_based = true

# run alice as parachain collator
Expand Down
12 changes: 6 additions & 6 deletions core/packages/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
},
"devDependencies": {
"@chainsafe/lodestar": "1.5.1",
"@polkadot/api": "9.11.1",
"@polkadot/api-cli": "0.51.12-0",
"@polkadot/types": "9.11.1",
"@polkadot/util": "10.2.3",
"@polkadot/util-crypto": "10.2.3",
"@polkadot/api": "10.7.1",
"@polkadot/api-cli": "0.54.4",
"@polkadot/types": "10.7.1",
"@polkadot/util": "12.2.1",
"@polkadot/util-crypto": "12.2.1",
"@types/keccak": "^3.0.1",
"@types/node": "^18.13.0",
"@types/yargs": "^17.0.2",
"@zombienet/cli": "^1.3.29",
"@zombienet/cli": "^1.3.52",
"bignumber.js": "^9.0.0",
"bn.js": "^5.2.0",
"c-kzg": "^1.0.7",
Expand Down
116 changes: 116 additions & 0 deletions core/packages/test/scripts/configure-beacon.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env bash
set -eu

source scripts/set-env.sh

config_beacon_checkpoint()
{
check_point_call=$($relay_bin generate-beacon-checkpoint --spec $active_spec --url $beacon_endpoint_http)
send_governance_transact $relay_url $sudo_seed $bridge_hub_para_id "$check_point_call" 180000000000 900000
}

config_beacon_relayer()
{
# Configure beacon relay
jq \
--arg beacon_endpoint_http $beacon_endpoint_http \
--arg active_spec $active_spec \
'
.source.beacon.endpoint = $beacon_endpoint_http
| .source.beacon.activeSpec = $active_spec
' \
config/beacon-relay.json > $output_dir/beacon-relay.json
}

wait_beacon_chain_ready()
{
initial_beacon_block=""
while [ -z "$initial_beacon_block" ] || [ "$initial_beacon_block" == "0x0000000000000000000000000000000000000000000000000000000000000000" ]
do
echo "Waiting for beacon chain to finalize to get initial block..."
initial_beacon_block=$(curl -s "$beacon_endpoint_http/eth/v1/beacon/states/head/finality_checkpoints" \
| jq -r '.data.finalized.root' || true)
sleep 3
done
}

send_governance_transact() {
local relay_url=$1
local relay_chain_seed=$2
local para_id=$3
local hex_encoded_data=$4
local require_weight_at_most_ref_time=$5
local require_weight_at_most_proof_size=$6
echo " calling send_governance_transact:"
echo " relay_url: ${relay_url}"
echo " relay_chain_seed: ${relay_chain_seed}"
echo " para_id: ${para_id}"
echo " hex_encoded_data: ${hex_encoded_data}"
echo " require_weight_at_most_ref_time: ${require_weight_at_most_ref_time}"
echo " require_weight_at_most_proof_size: ${require_weight_at_most_proof_size}"
echo " params:"

local dest=$(jq --null-input \
--arg para_id "$para_id" \
'{ "v3": { "parents": 0, "interior": { "x1": { "parachain": $para_id } } } }')

local message=$(jq --null-input \
--arg hex_encoded_data "$hex_encoded_data" \
--arg require_weight_at_most_ref_time "$require_weight_at_most_ref_time" \
--arg require_weight_at_most_proof_size "$require_weight_at_most_proof_size" \
'
{
"v3": [
{
"unpaidexecution": {
"weight_limit": "unlimited"
}
},
{
"transact": {
"origin_kind": "superuser",
"require_weight_at_most": {
"ref_time": $require_weight_at_most_ref_time,
"proof_size": $require_weight_at_most_proof_size,
},
"call": {
"encoded": $hex_encoded_data
}
}
}
]
}
')

echo ""
echo " dest:"
echo "${dest}"
echo ""
echo " message:"
echo "${message}"
echo ""
echo "--------------------------------------------------"

npx polkadot-js-api \
--ws "${relay_url?}" \
--seed "${relay_chain_seed?}" \
--sudo \
tx.xcmPallet.send \
"${dest}" \
"${message}"
}

function configure_beacon()
{
wait_beacon_chain_ready
config_beacon_relayer
config_beacon_checkpoint
}

if [ -z "${from_start_services:-}" ]; then
echo "config beacon checkpoint only!"
wait_beacon_chain_ready
config_beacon_relayer
config_beacon_checkpoint
wait
fi
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -eu

source scripts/set-env.sh

configure_contracts()
configure_beefy()
{
pushd "$contract_dir"

Expand Down Expand Up @@ -36,6 +36,6 @@ configure_contracts()

if [ -z "${from_start_services:-}" ]; then
echo "config contracts only!"
configure_contracts
configure_beefy
wait
fi
49 changes: 0 additions & 49 deletions core/packages/test/scripts/deploy-polkadot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,12 @@ set -eu

source scripts/set-env.sh

generate_chain_spec() {
echo "Generating chain specification"
"$output_bin_dir/polkadot-parachain" build-spec --chain "$bridge_hub_runtime" --disable-default-bootnode > "$output_dir/spec.json"

initial_beacon_block=""
while [ -z "$initial_beacon_block" ] || [ "$initial_beacon_block" == "0x0000000000000000000000000000000000000000000000000000000000000000" ]
do
echo "Waiting for beacon chain to finalize to get initial block..."
initial_beacon_block=$(curl -s "$beacon_endpoint_http/eth/v1/beacon/states/head/finality_checkpoints" \
| jq -r '.data.finalized.root' || true)
sleep 3
done

echo "Found initial finalized block: $initial_beacon_block"
bootstrap_header=""
slot=0
while [ -z "$bootstrap_header" ] || [ "$bootstrap_header" == "" ] || [ "$bootstrap_header" == "null" ]
do
echo "Waiting for beacon to get initial bootstrap..."
bootstrap_data=$(curl -s "$beacon_endpoint_http/eth/v1/beacon/light_client/bootstrap/$initial_beacon_block")
# sometimes will get http 503 error from the above bootstrap endpoint in goerli network
# so add true here to ignore the error and just retry
bootstrap_header=$(jq -r '.data.header' <<< "$bootstrap_data" || true)
slot=$(jq -r '.data.header.beacon.slot' <<< "$bootstrap_data" || true)
sleep 3
done

curl -s "$beacon_endpoint_http/eth/v1/beacon/light_client/bootstrap/$initial_beacon_block" > "$output_dir/initialBeaconSync_tmp.json"

genesisData=$(curl -s "$beacon_endpoint_http/eth/v1/beacon/genesis")
validatorsRoot=$(jq -r '.data.genesis_validators_root' <<< "$genesisData")
genesisTime=$(jq -r '.data.genesis_time' <<< "$genesisData")

importTime="$((genesisTime + (seconds_per_slot * slot)))"

jq \
--arg validatorsRoot "$validatorsRoot" \
--arg importTime "$importTime" \
' .validators_root = $validatorsRoot
| .import_time = $importTime
' \
"$output_dir/initialBeaconSync_tmp.json" \
> "$output_dir/initialBeaconSync_tmp2.json"

cat "$output_dir/initialBeaconSync_tmp2.json" | node scripts/helpers/transformInitialBeaconSync.js | sponge "$output_dir/initialBeaconSync.json"

cat "$output_dir/spec.json" | node scripts/helpers/mutateSpec.js "$output_dir/contracts.json" "$output_dir/initialBeaconSync.json" | sponge "$output_dir/spec.json"
}

wait_start() {
scripts/wait-for-it.sh -t 120 127.0.0.1:11144
}

zombienet_launch() {
generate_chain_spec
npx zombienet spawn config/launch-config.toml --provider=native 2>&1 &
wait_start
}
Expand Down
Loading