document how to run merge local testnet with Nethermind (#3110)

This commit is contained in:
tersec 2021-11-17 19:45:39 +00:00 committed by GitHub
parent c673525591
commit 39f6a6534e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 14 deletions

View File

@ -47,7 +47,7 @@ func compute_deltas(
logScope: logScope:
topics = "fork_choice" topics = "fork_choice"
proc init*(T: type ForkChoiceBackend, func init*(T: type ForkChoiceBackend,
justified_epoch: Epoch, justified_epoch: Epoch,
finalized_root: Eth2Digest, finalized_root: Eth2Digest,
finalized_epoch: Epoch): T = finalized_epoch: Epoch): T =
@ -91,7 +91,7 @@ func extend[T](s: var seq[T], minLen: int) =
if s.len < minLen: if s.len < minLen:
s.setLen(minLen) s.setLen(minLen)
proc compute_slots_since_epoch_start(slot: Slot): uint64 = func compute_slots_since_epoch_start(slot: Slot): uint64 =
slot - slot.epoch().compute_start_slot_at_epoch() slot - slot.epoch().compute_start_slot_at_epoch()
proc on_tick(self: var Checkpoints, dag: ChainDAGRef, time: Slot): FcResult[void] = proc on_tick(self: var Checkpoints, dag: ChainDAGRef, time: Slot): FcResult[void] =
@ -116,7 +116,7 @@ proc on_tick(self: var Checkpoints, dag: ChainDAGRef, time: Slot): FcResult[void
balances: epochRef.effective_balances) balances: epochRef.effective_balances)
ok() ok()
proc process_attestation_queue(self: var ForkChoice) {.gcsafe.} func process_attestation_queue(self: var ForkChoice) {.gcsafe.}
proc update_time(self: var ForkChoice, dag: ChainDAGRef, time: Slot): FcResult[void] = proc update_time(self: var ForkChoice, dag: ChainDAGRef, time: Slot): FcResult[void] =
if time > self.checkpoints.time: if time > self.checkpoints.time:
@ -152,7 +152,7 @@ func process_attestation*(
validator_index = validator_index, validator_index = validator_index,
new_vote = shortLog(vote) new_vote = shortLog(vote)
proc process_attestation_queue(self: var ForkChoice) = func process_attestation_queue(self: var ForkChoice) =
self.queuedAttestations.keepItIf: self.queuedAttestations.keepItIf:
if it.slot < self.checkpoints.time: if it.slot < self.checkpoints.time:
for validator_index in it.attesting_indices: for validator_index in it.attesting_indices:
@ -199,7 +199,7 @@ proc on_attestation*(
ok() ok()
# https://github.com/ethereum/consensus-specs/blob/v0.12.1/specs/phase0/fork-choice.md#should_update_justified_checkpoint # https://github.com/ethereum/consensus-specs/blob/v0.12.1/specs/phase0/fork-choice.md#should_update_justified_checkpoint
proc should_update_justified_checkpoint( func should_update_justified_checkpoint(
self: var Checkpoints, self: var Checkpoints,
dag: ChainDAGRef, dag: ChainDAGRef,
epochRef: EpochRef): FcResult[bool] = epochRef: EpochRef): FcResult[bool] =
@ -274,7 +274,7 @@ proc process_state(self: var Checkpoints,
balances: justifiedEpoch.effective_balances) balances: justifiedEpoch.effective_balances)
ok() ok()
proc process_block*(self: var ForkChoiceBackend, func process_block*(self: var ForkChoiceBackend,
block_root: Eth2Digest, block_root: Eth2Digest,
parent_root: Eth2Digest, parent_root: Eth2Digest,
justified_epoch: Epoch, justified_epoch: Epoch,
@ -329,7 +329,7 @@ proc process_block*(self: var ForkChoice,
ok() ok()
proc find_head*( func find_head*(
self: var ForkChoiceBackend, self: var ForkChoiceBackend,
justified_epoch: Epoch, justified_epoch: Epoch,
justified_root: Eth2Digest, justified_root: Eth2Digest,

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

83
docs/neth-m2-nimbus.md Normal file
View File

@ -0,0 +1,83 @@
# How to run Nethermind
https://github.com/NethermindEth/nethermind/pull/3597 documents this aspect.
## Install dotnet:
```
https://dotnet.microsoft.com/download
```
## Build Nethermind:
```
git clone https://github.com/NethermindEth/nethermind.git --recursive -b themerge_kintsugi
cd src/Nethermind
dotnet build Nethermind.sln -c Release
# if src/Nethermind/Nethermind.Runner/bin/Release/net5.0/plugins has no Nethermind.Merge.Plugin.dll plugin then you may need to run the build again
dotnet build Nethermind.sln -c Release
cd Nethermind.Runner
```
# Run Nethermind
run Nethermind
```
rm -rf bin/Release/net5.0/nethermind_db
dotnet run -c Release -- --config themerge_kintsugi_m2 --Merge.TerminalTotalDifficulty 100
```
# Verify that Nimbus runs through test vectors
- Run `./env.sh nim c -r tests/test_merge_vectors.nim`. It should show output akin to:
```
$ ./env.sh nim c -r tests/test_merge_vectors.nim
[Suite] Merge test vectors
DBG 2021-11-17 15:31:31.560+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=79
DBG 2021-11-17 15:31:31.576+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=493
DBG 2021-11-17 15:31:31.597+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=87
DBG 2021-11-17 15:31:31.619+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=1196
DBG 2021-11-17 15:31:31.634+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=494
DBG 2021-11-17 15:31:31.637+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=87
DBG 2021-11-17 15:31:31.640+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=1197
DBG 2021-11-17 15:31:31.644+00:00 Message sent to RPC server topics="JSONRPC-HTTP-CLIENT" tid=960621 file=httpclient.nim:191 address=127.0.0.1:9550 msg_len=494
[OK] getPayload, executePayload, and forkchoiceUpdated
```
# How to run Nimbus local testnet with Nethermind
- Run Nethermind.
- Check out `nimbus-eth2` branch `kintsugi`
- Run `./scripts/launch_local_testnet.sh --preset minimal --nodes 4 --disable-htop --stop-at-epoch 7 -- --verify-finalization --discv5:no`
This creates a 4-node local testnet with 128 validators.
The Nimbus console output will be similar to
```
nimbus-eth2$ N=0; while ./scripts/launch_local_testnet.sh --preset minimal --nodes 4 --disable-htop --stop-at-epoch 8 -- --verify-finalization --discv5:no; do N=$((N+1)); echo "That was run #${N}"; sleep 67; done
Building: build/nimbus_beacon_node
Building: build/nimbus_signing_process
Building: build/deposit_contract
Build completed successfully: build/nimbus_signing_process
Build completed successfully: build/deposit_contract
Build completed successfully: build/nimbus_beacon_node
NOT 2021-11-17 15:40:11.894+01:00 Generating deposits tid=966934 file=keystore_management.nim:562 totalNewValidators=128 validatorsDir=local_testnet_data/validators secretsDir=local_testnet_data/secrets
NOT 2021-11-17 15:40:51.434+01:00 Deposit data written tid=966934 file=deposit_contract.nim:222 filename=local_testnet_data/deposits.json
Wrote local_testnet_data/genesis.ssz
WRN 2021-11-17 15:40:51.443+01:00 Using insecure password to lock networking key key_path=local_testnet_data/network_key.json
INF 2021-11-17 15:40:52.184+01:00 New network key storage was created topics="networking" key_path=local_testnet_data/network_key.json network_public_key=08021221029b0d9c63dc15335b6f1f73dc359a0bda88a84cc7e0346f12e64084673a35a915
Wrote local_testnet_data/bootstrap_nodes.txt
Wrote local_testnet_data/config.yaml:
DEPOSIT_NETWORK_ID: 1
PRESET_BASE: minimal
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 128
MIN_GENESIS_TIME: 0
GENESIS_DELAY: 10
DEPOSIT_CONTRACT_ADDRESS: 0x0000000000000000000000000000000000000000
ETH1_FOLLOW_DISTANCE: 1
ALTAIR_FORK_EPOCH: 1
MERGE_FORK_EPOCH: 2
TERMINAL_TOTAL_DIFFICULTY: 0
That was run #1
```
Meanwhile, Nimbus is interacting with Nethermind in preparing, getting, and executing payloads:
![./kintsugi_nethermind_logs.png](./kintsugi_nethermind_logs.png)

View File

@ -13,7 +13,7 @@ set -Eeuo pipefail
# eth/catalyst: remove headHash from payloadAttributes # eth/catalyst: remove headHash from payloadAttributes
# Prepare payload # Prepare payload
resp_prepare_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdatedV1","params":[{"headBlockHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", "safeBlockHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", "finalizedBlockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}, {"timestamp":"0x5", "random":"0x0000000000000000000000000000000000000000000000000000000000000000", "feeRecipient":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"}],"id":67}' http://localhost:8545) resp_prepare_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdatedV1","params":[{"headBlockHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", "safeBlockHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", "finalizedBlockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}, {"timestamp":"0x5", "random":"0x0000000000000000000000000000000000000000000000000000000000000000", "feeRecipient":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"}],"id":67}' http://localhost:8550)
echo "engine_forkchoiceUpdatedV1 response: ${resp_prepare_payload}" echo "engine_forkchoiceUpdatedV1 response: ${resp_prepare_payload}"
# Inconsistency in test vectors vs Geth behavior # Inconsistency in test vectors vs Geth behavior
@ -22,14 +22,14 @@ empirical_resp_prepare_payload='{"jsonrpc":"2.0","id":67,"result":{"status":"SUC
[[ ${resp_prepare_payload} == "${expected_resp_prepare_payload}" ]] || [[ ${resp_prepare_payload} == "${empirical_resp_prepare_payload}" ]] || (echo "Unexpected response to engine_forkchoiceUpdatedV1"; false) [[ ${resp_prepare_payload} == "${expected_resp_prepare_payload}" ]] || [[ ${resp_prepare_payload} == "${empirical_resp_prepare_payload}" ]] || (echo "Unexpected response to engine_forkchoiceUpdatedV1"; false)
# Get payload # Get payload
resp_get_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_getPayloadV1","params":["0xa247243752eb10b4"],"id":67}' http://localhost:8545) resp_get_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_getPayloadV1","params":["0xa247243752eb10b4"],"id":67}' http://localhost:8550)
echo "engine_getPayloadV1 response: ${resp_get_payload}" echo "engine_getPayloadV1 response: ${resp_get_payload}"
expected_resp_get_payload='{"jsonrpc":"2.0","id":67,"result":{"parentHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a","coinbase":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x7","blockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858","transactions":[]}}' expected_resp_get_payload='{"jsonrpc":"2.0","id":67,"result":{"parentHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a","coinbase":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x7","blockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858","transactions":[]}}'
[[ ${resp_get_payload} == "${expected_resp_get_payload}" ]] || (echo "Unexpected response to engine_getPayloadV1"; false) [[ ${resp_get_payload} == "${expected_resp_get_payload}" ]] || (echo "Unexpected response to engine_getPayloadV1"; false)
# Execute payload # Execute payload
resp_execute_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_executePayloadV1","params":[{"parentHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a","coinbase":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x7","blockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858","transactions":[]}],"id":67}' http://localhost:8545) resp_execute_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_executePayloadV1","params":[{"parentHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a","coinbase":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x7","blockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858","transactions":[]}],"id":67}' http://localhost:8550)
echo "engine_executePayloadV1 response: ${resp_execute_payload}" echo "engine_executePayloadV1 response: ${resp_execute_payload}"
# SUCCESS vs VALID again, but in the other direction # SUCCESS vs VALID again, but in the other direction
@ -38,7 +38,7 @@ empirical_resp_execute_payload='{"jsonrpc":"2.0","id":67,"result":{"status":"VAL
[[ ${resp_execute_payload} == "${expected_resp_execute_payload}" ]] || [[ ${resp_execute_payload} == "${empirical_resp_execute_payload}" ]] || (echo "Unexpected response to engine_executePayloadV1"; false) [[ ${resp_execute_payload} == "${expected_resp_execute_payload}" ]] || [[ ${resp_execute_payload} == "${empirical_resp_execute_payload}" ]] || (echo "Unexpected response to engine_executePayloadV1"; false)
# Update the fork choice # Update the fork choice
resp_update_forkchoice=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdatedV1","params":[{"headBlockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "safeBlockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "finalizedBlockHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a"}, null],"id":67}' http://localhost:8545) resp_update_forkchoice=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdatedV1","params":[{"headBlockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "safeBlockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "finalizedBlockHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a"}, null],"id":67}' http://localhost:8550)
echo "engine_forkchoiceUpdatedV1 response: ${resp_update_forkchoice}" echo "engine_forkchoiceUpdatedV1 response: ${resp_update_forkchoice}"
expected_resp_update_forkchoice='{"jsonrpc":"2.0","id":67,"result":{"status":"SUCCESS","payloadId":null}}' expected_resp_update_forkchoice='{"jsonrpc":"2.0","id":67,"result":{"status":"SUCCESS","payloadId":null}}'

View File

@ -1,7 +1,7 @@
{.used.} {.used.}
# https://notes.ethereum.org/@9AeMAlpyQYaAAyuj47BzRw/rkwW3ceVY # https://notes.ethereum.org/@9AeMAlpyQYaAAyuj47BzRw/rkwW3ceVY
# Monitor traffic: socat -v TCP-LISTEN:9545,fork TCP-CONNECT:127.0.0.1:8545 # Monitor traffic: socat -v TCP-LISTEN:9550,fork TCP-CONNECT:127.0.0.1:8550
import import
unittest2, unittest2,
@ -12,13 +12,13 @@ import
suite "Merge test vectors": suite "Merge test vectors":
let web3Provider = (waitFor Web3DataProvider.new( let web3Provider = (waitFor Web3DataProvider.new(
default(Eth1Address), "ws://127.0.0.1:8546")).get default(Eth1Address), "http://127.0.0.1:8550")).get
test "getPayload, executePayload, and forkchoiceUpdated": test "getPayload, executePayload, and forkchoiceUpdated":
const feeRecipient = const feeRecipient =
Eth1Address.fromHex("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b") Eth1Address.fromHex("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")
let let
existingBlock = waitFor web3Provider.getBlockByNumber(1) existingBlock = waitFor web3Provider.getBlockByNumber(0)
payloadId = waitFor web3Provider.forkchoiceUpdated( payloadId = waitFor web3Provider.forkchoiceUpdated(
existingBlock.hash.asEth2Digest, existingBlock.hash.asEth2Digest,
existingBlock.hash.asEth2Digest, existingBlock.hash.asEth2Digest,