mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-21 10:48:17 +00:00
interop updates
* add interop launcher scripts * stick validator_keygen into beacon_node * fix lmd ghost slot number on missing block * use mocked eth1data when producing blocks * use bls public key method for withdrawal credentials * fix deposit domain * prefer lowercase for a bunch of toHex * build simulation binary in data folder to avoid data types confusion
This commit is contained in:
parent
1ec4c5aef7
commit
7b73b40bab
6
Makefile
6
Makefile
@ -11,7 +11,7 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system
|
|||||||
# we don't want an error here, so we can handle things later, in the build-system-checks target
|
# we don't want an error here, so we can handle things later, in the build-system-checks target
|
||||||
-include $(BUILD_SYSTEM_DIR)/makefiles/variables.mk
|
-include $(BUILD_SYSTEM_DIR)/makefiles/variables.mk
|
||||||
|
|
||||||
TOOLS := beacon_node validator_keygen bench_bls_sig_agggregation state_sim
|
TOOLS := beacon_node bench_bls_sig_agggregation state_sim
|
||||||
TOOLS_DIRS := beacon_chain benchmarks research
|
TOOLS_DIRS := beacon_chain benchmarks research
|
||||||
TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
|
TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
|
||||||
|
|
||||||
@ -75,8 +75,8 @@ $(TOOLS): | build deps nat-libs p2pd
|
|||||||
clean_eth2_network_simulation_files:
|
clean_eth2_network_simulation_files:
|
||||||
rm -rf tests/simulation/{data,validators}
|
rm -rf tests/simulation/{data,validators}
|
||||||
|
|
||||||
eth2_network_simulation: | beacon_node validator_keygen clean_eth2_network_simulation_files
|
eth2_network_simulation: | build deps nat-libs p2pd clean_eth2_network_simulation_files
|
||||||
SKIP_BUILDS=1 GIT_ROOT="$$PWD" BUILD_OUTPUTS_DIR="./build" $(ENV_SCRIPT) tests/simulation/start.sh
|
GIT_ROOT="$$PWD" BUILD_OUTPUTS_DIR="./build" $(ENV_SCRIPT) tests/simulation/start.sh
|
||||||
|
|
||||||
testnet0 testnet1: | build deps nat-libs p2pd
|
testnet0 testnet1: | build deps nat-libs p2pd
|
||||||
NIM_PARAMS="$(NIM_PARAMS)" $(ENV_SCRIPT) scripts/build_testnet_node.sh $@
|
NIM_PARAMS="$(NIM_PARAMS)" $(ENV_SCRIPT) scripts/build_testnet_node.sh $@
|
||||||
|
@ -11,7 +11,6 @@ license = "MIT or Apache License 2.0"
|
|||||||
installDirs = @["beacon_chain", "research"]
|
installDirs = @["beacon_chain", "research"]
|
||||||
bin = @[
|
bin = @[
|
||||||
"beacon_chain/beacon_node",
|
"beacon_chain/beacon_node",
|
||||||
"beacon_chain/validator_keygen",
|
|
||||||
"research/serialized_sizes",
|
"research/serialized_sizes",
|
||||||
"research/state_sim",
|
"research/state_sim",
|
||||||
]
|
]
|
||||||
|
1
beacon_chain/.gitignore
vendored
1
beacon_chain/.gitignore
vendored
@ -1,2 +1 @@
|
|||||||
beacon_node
|
beacon_node
|
||||||
validator_keygen
|
|
||||||
|
@ -9,7 +9,7 @@ import
|
|||||||
conf, time, state_transition, fork_choice, ssz, beacon_chain_db,
|
conf, time, state_transition, fork_choice, ssz, beacon_chain_db,
|
||||||
validator_pool, extras, attestation_pool, block_pool, eth2_network,
|
validator_pool, extras, attestation_pool, block_pool, eth2_network,
|
||||||
beacon_node_types, mainchain_monitor, trusted_state_snapshots, version,
|
beacon_node_types, mainchain_monitor, trusted_state_snapshots, version,
|
||||||
sync_protocol, request_manager, genesis
|
sync_protocol, request_manager, genesis, validator_keygen, interop
|
||||||
|
|
||||||
const
|
const
|
||||||
topicBeaconBlocks = "/eth2/beacon_block/ssz"
|
topicBeaconBlocks = "/eth2/beacon_block/ssz"
|
||||||
@ -281,19 +281,14 @@ proc updateHead(node: BeaconNode, slot: Slot): BlockRef =
|
|||||||
justifiedHead = node.blockPool.latestJustifiedBlock()
|
justifiedHead = node.blockPool.latestJustifiedBlock()
|
||||||
|
|
||||||
debug "Preparing for fork choice",
|
debug "Preparing for fork choice",
|
||||||
justifiedHeadRoot = shortLog(justifiedHead.root),
|
justifiedHeadRoot = shortLog(justifiedHead.blck.root),
|
||||||
justifiedHeadSlot = shortLog(justifiedHead.slot),
|
justifiedHeadSlot = shortLog(justifiedHead.slot),
|
||||||
justifiedHeadEpoch = shortLog(justifiedHead.slot.compute_epoch_of_slot),
|
justifiedHeadEpoch = shortLog(justifiedHead.slot.compute_epoch_of_slot),
|
||||||
connectedPeers = node.network.peersCount
|
connectedPeers = node.network.peersCount
|
||||||
|
|
||||||
# TODO slot number is wrong here, it should be the start of the epoch that
|
|
||||||
# got finalized:
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/issues/768
|
|
||||||
let newHead = node.blockPool.withState(
|
let newHead = node.blockPool.withState(
|
||||||
node.justifiedStateCache,
|
node.justifiedStateCache, justifiedHead):
|
||||||
BlockSlot(blck: justifiedHead, slot: justifiedHead.slot)):
|
lmdGhost(node.attestationPool, state, justifiedHead.blck)
|
||||||
|
|
||||||
lmdGhost(node.attestationPool, state, justifiedHead)
|
|
||||||
|
|
||||||
info "Fork chosen",
|
info "Fork chosen",
|
||||||
newHeadSlot = shortLog(newHead.slot),
|
newHeadSlot = shortLog(newHead.slot),
|
||||||
@ -356,10 +351,13 @@ proc proposeBlock(node: BeaconNode,
|
|||||||
node.stateCache, BlockSlot(blck: head, slot: slot - 1)):
|
node.stateCache, BlockSlot(blck: head, slot: slot - 1)):
|
||||||
# To create a block, we'll first apply a partial block to the state, skipping
|
# To create a block, we'll first apply a partial block to the state, skipping
|
||||||
# some validations.
|
# some validations.
|
||||||
|
# TODO monitor main chain here: node.mainchainMonitor.getBeaconBlockRef()
|
||||||
|
|
||||||
let
|
let
|
||||||
blockBody = BeaconBlockBody(
|
blockBody = BeaconBlockBody(
|
||||||
randao_reveal: validator.genRandaoReveal(state, slot),
|
randao_reveal: validator.genRandaoReveal(state, slot),
|
||||||
eth1_data: node.mainchainMonitor.getBeaconBlockRef(),
|
eth1_data: get_eth1data_stub(
|
||||||
|
state.eth1_deposit_index, slot.compute_epoch_of_slot()),
|
||||||
attestations:
|
attestations:
|
||||||
node.attestationPool.getAttestationsForBlock(state, slot))
|
node.attestationPool.getAttestationsForBlock(state, slot))
|
||||||
|
|
||||||
@ -793,13 +791,13 @@ when isMainModule:
|
|||||||
except SerializationError as err:
|
except SerializationError as err:
|
||||||
stderr.write "Error while loading a deposit file:\n"
|
stderr.write "Error while loading a deposit file:\n"
|
||||||
stderr.write err.formatMsg(depositFile), "\n"
|
stderr.write err.formatMsg(depositFile), "\n"
|
||||||
stderr.write "Please regenerate the deposit files by running validator_keygen again\n"
|
stderr.write "Please regenerate the deposit files by running makeDeposits again\n"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
let initialState = initialize_beacon_state_from_eth1(
|
let initialState = initialize_beacon_state_from_eth1(
|
||||||
deposits,
|
deposits,
|
||||||
uint64(times.toUnix(times.getTime()) + config.genesisOffset),
|
uint64(times.toUnix(times.getTime()) + config.genesisOffset),
|
||||||
Eth1Data(), {skipValidation})
|
get_eth1data_stub(deposits.len().uint64, 0.Epoch), {skipValidation})
|
||||||
|
|
||||||
doAssert initialState.validators.len > 0
|
doAssert initialState.validators.len > 0
|
||||||
|
|
||||||
@ -861,3 +859,11 @@ when isMainModule:
|
|||||||
dynamicLogScope(node = node.nickname): node.start(node.stateCache.data.data)
|
dynamicLogScope(node = node.nickname): node.start(node.stateCache.data.data)
|
||||||
else:
|
else:
|
||||||
node.start(node.stateCache.data.data)
|
node.start(node.stateCache.data.data)
|
||||||
|
|
||||||
|
of makeDeposits:
|
||||||
|
let deposits = generateDeposits(
|
||||||
|
config.totalDeposits, config.depositDir, config.randomKeys)
|
||||||
|
|
||||||
|
if config.depositWeb3Url.len() > 0 and config.depositContractAddress.len() > 0:
|
||||||
|
waitFor sendDeposits(
|
||||||
|
deposits, config.depositWeb3Url, config.depositContractAddress)
|
||||||
|
@ -592,7 +592,7 @@ proc updateHead*(pool: BlockPool, state: var StateData, blck: BlockRef) =
|
|||||||
not pool.heads[n].blck.isAncestorOf(pool.finalizedHead.blck):
|
not pool.heads[n].blck.isAncestorOf(pool.finalizedHead.blck):
|
||||||
pool.heads.del(n)
|
pool.heads.del(n)
|
||||||
|
|
||||||
proc latestJustifiedBlock*(pool: BlockPool): BlockRef =
|
proc latestJustifiedBlock*(pool: BlockPool): BlockSlot =
|
||||||
## Return the most recent block that is justified and at least as recent
|
## Return the most recent block that is justified and at least as recent
|
||||||
## as the latest finalized block
|
## as the latest finalized block
|
||||||
|
|
||||||
@ -602,10 +602,10 @@ proc latestJustifiedBlock*(pool: BlockPool): BlockRef =
|
|||||||
"Genesis block will be head, if nothing else"
|
"Genesis block will be head, if nothing else"
|
||||||
|
|
||||||
# Prefer stability: use justified block from current head to break ties!
|
# Prefer stability: use justified block from current head to break ties!
|
||||||
result = pool.head.justified.blck
|
result = pool.head.justified
|
||||||
for head in pool.heads[1 ..< ^0]:
|
for head in pool.heads[1 ..< ^0]:
|
||||||
if head.justified.blck.slot > result.slot:
|
if head.justified.slot > result.slot:
|
||||||
result = head.justified.blck
|
result = head.justified
|
||||||
|
|
||||||
proc preInit*(
|
proc preInit*(
|
||||||
T: type BlockPool, db: BeaconChainDB, state: BeaconState, blck: BeaconBlock) =
|
T: type BlockPool, db: BeaconChainDB, state: BeaconState, blck: BeaconBlock) =
|
||||||
|
@ -17,6 +17,7 @@ type
|
|||||||
importValidator
|
importValidator
|
||||||
createTestnet
|
createTestnet
|
||||||
updateTestnet
|
updateTestnet
|
||||||
|
makeDeposits
|
||||||
|
|
||||||
BeaconNodeConf* = object
|
BeaconNodeConf* = object
|
||||||
logLevel* {.
|
logLevel* {.
|
||||||
@ -35,6 +36,14 @@ type
|
|||||||
shortform: "d"
|
shortform: "d"
|
||||||
defaultValue: config.defaultDataDir().}: OutDir
|
defaultValue: config.defaultDataDir().}: OutDir
|
||||||
|
|
||||||
|
depositWeb3Url* {.
|
||||||
|
desc: "URL of the Web3 server to observe Eth1",
|
||||||
|
defaultValue: ""}: string
|
||||||
|
|
||||||
|
depositContractAddress* {.
|
||||||
|
desc: "Address of the deposit contract",
|
||||||
|
defaultValue: ""}: string
|
||||||
|
|
||||||
case cmd* {.
|
case cmd* {.
|
||||||
command
|
command
|
||||||
defaultValue: noCommand.}: StartUpCommand
|
defaultValue: noCommand.}: StartUpCommand
|
||||||
@ -64,7 +73,7 @@ type
|
|||||||
|
|
||||||
validators* {.
|
validators* {.
|
||||||
required
|
required
|
||||||
desc: "Path to a validator private key, as generated by validator_keygen"
|
desc: "Path to a validator private key, as generated by makeDeposits"
|
||||||
longform: "validator"
|
longform: "validator"
|
||||||
shortform: "v".}: seq[ValidatorKeyPath]
|
shortform: "v".}: seq[ValidatorKeyPath]
|
||||||
|
|
||||||
@ -77,14 +86,6 @@ type
|
|||||||
"If you set this to 'auto', a persistent automatically generated ID will be seleceted for each --dataDir folder"
|
"If you set this to 'auto', a persistent automatically generated ID will be seleceted for each --dataDir folder"
|
||||||
defaultValue: ""}: string
|
defaultValue: ""}: string
|
||||||
|
|
||||||
depositWeb3Url* {.
|
|
||||||
desc: "URL of the Web3 server to observe Eth1",
|
|
||||||
defaultValue: ""}: string
|
|
||||||
|
|
||||||
depositContractAddress* {.
|
|
||||||
desc: "Address of the deposit contract",
|
|
||||||
defaultValue: ""}: string
|
|
||||||
|
|
||||||
of createTestnet:
|
of createTestnet:
|
||||||
networkId* {.
|
networkId* {.
|
||||||
desc: "An unique numeric identifier for the network".}: uint8
|
desc: "An unique numeric identifier for the network".}: uint8
|
||||||
@ -131,6 +132,16 @@ type
|
|||||||
of updateTestnet:
|
of updateTestnet:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
of makeDeposits:
|
||||||
|
totalDeposits* {.
|
||||||
|
desc: "Total number of deposits and keys to generate".}: int
|
||||||
|
|
||||||
|
depositDir* {.
|
||||||
|
desc: "Folder to write deposits to", defaultValue: "validators".}: string
|
||||||
|
|
||||||
|
randomKeys* {.
|
||||||
|
desc: "Use random keys (instead of interop keys)", defaultValue: false.}: bool
|
||||||
|
|
||||||
proc defaultPort*(config: BeaconNodeConf): int =
|
proc defaultPort*(config: BeaconNodeConf): int =
|
||||||
if config.network == "testnet1": 9100
|
if config.network == "testnet1": 9100
|
||||||
else: 9000
|
else: 9000
|
||||||
@ -155,4 +166,3 @@ proc defaultDataDir*(conf: BeaconNodeConf): string =
|
|||||||
proc validatorFileBaseName*(validatorIdx: int): string =
|
proc validatorFileBaseName*(validatorIdx: int): string =
|
||||||
# there can apparently be tops 4M validators so we use 7 digits..
|
# there can apparently be tops 4M validators so we use 7 digits..
|
||||||
fmt"v{validatorIdx:07}"
|
fmt"v{validatorIdx:07}"
|
||||||
|
|
||||||
|
@ -12,7 +12,10 @@ proc get_ancestor(blck: BlockRef, slot: Slot): BlockRef =
|
|||||||
else:
|
else:
|
||||||
get_ancestor(blck.parent, slot)
|
get_ancestor(blck.parent, slot)
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.4.0/specs/core/0_beacon-chain.md#beacon-chain-fork-choice-rule
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.3/specs/core/0_fork-choice.md
|
||||||
|
# The structure of this code differs from the spec since we use a different
|
||||||
|
# strategy for storing states and justification points - it should nonetheless
|
||||||
|
# be close in terms of functionality.
|
||||||
proc lmdGhost*(
|
proc lmdGhost*(
|
||||||
pool: AttestationPool, start_state: BeaconState,
|
pool: AttestationPool, start_state: BeaconState,
|
||||||
start_block: BlockRef): BlockRef =
|
start_block: BlockRef): BlockRef =
|
||||||
@ -22,28 +25,22 @@ proc lmdGhost*(
|
|||||||
# Nim implementation for cumulative frequencies at
|
# Nim implementation for cumulative frequencies at
|
||||||
# https://github.com/numforge/laser/blob/990e59fffe50779cdef33aa0b8f22da19e1eb328/benchmarks/random_sampling/fenwicktree.nim
|
# https://github.com/numforge/laser/blob/990e59fffe50779cdef33aa0b8f22da19e1eb328/benchmarks/random_sampling/fenwicktree.nim
|
||||||
|
|
||||||
const FORK_CHOICE_BALANCE_INCREMENT = 2'u64^0 * 10'u64^9
|
|
||||||
|
|
||||||
let
|
let
|
||||||
active_validator_indices =
|
active_validator_indices =
|
||||||
get_active_validator_indices(
|
get_active_validator_indices(
|
||||||
start_state, compute_epoch_of_slot(start_state.slot))
|
start_state, compute_epoch_of_slot(start_state.slot))
|
||||||
|
|
||||||
var attestation_targets: seq[tuple[validator: ValidatorIndex, blck: BlockRef]]
|
var latest_messages: seq[tuple[validator: ValidatorIndex, blck: BlockRef]]
|
||||||
for i in active_validator_indices:
|
for i in active_validator_indices:
|
||||||
let pubKey = start_state.validators[i].pubkey
|
let pubKey = start_state.validators[i].pubkey
|
||||||
if (let vote = pool.latestAttestation(pubKey); not vote.isNil):
|
if (let vote = pool.latestAttestation(pubKey); not vote.isNil):
|
||||||
attestation_targets.add((i, vote))
|
latest_messages.add((i, vote))
|
||||||
|
|
||||||
template get_vote_count(blck: BlockRef): uint64 =
|
template get_latest_attesting_balance(blck: BlockRef): uint64 =
|
||||||
var res: uint64
|
var res: uint64
|
||||||
for validator_index, target in attestation_targets.items():
|
for validator_index, target in latest_messages.items():
|
||||||
if get_ancestor(target, blck.slot) == blck:
|
if get_ancestor(target, blck.slot) == blck:
|
||||||
# The div on the balance is to chop off the insignification bits that
|
res += start_state.validators[validator_index].effective_balance
|
||||||
# fluctuate a lot epoch to epoch to have a more stable fork choice
|
|
||||||
res +=
|
|
||||||
start_state.validators[validator_index].effective_balance div
|
|
||||||
FORK_CHOICE_BALANCE_INCREMENT
|
|
||||||
res
|
res
|
||||||
|
|
||||||
var head = start_block
|
var head = start_block
|
||||||
@ -53,9 +50,9 @@ proc lmdGhost*(
|
|||||||
|
|
||||||
head = head.children[0]
|
head = head.children[0]
|
||||||
var
|
var
|
||||||
headCount = get_vote_count(head)
|
headCount = get_latest_attesting_balance(head)
|
||||||
|
|
||||||
for i in 1..<head.children.len:
|
for i in 1..<head.children.len:
|
||||||
if (let hc = get_vote_count(head.children[i]); hc > headCount):
|
if (let hc = get_latest_attesting_balance(head.children[i]); hc > headCount):
|
||||||
head = head.children[i]
|
head = head.children[i]
|
||||||
headCount = hc
|
headCount = hc
|
||||||
|
60
beacon_chain/interop.nim
Normal file
60
beacon_chain/interop.nim
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import
|
||||||
|
os, ospaths,
|
||||||
|
stew/endians2, stint,
|
||||||
|
./conf, ./extras, ./ssz,
|
||||||
|
spec/[crypto, datatypes, digest, helpers]
|
||||||
|
|
||||||
|
func get_eth1data_stub*(deposit_count: uint64, current_epoch: Epoch): Eth1Data =
|
||||||
|
# https://github.com/ethereum/eth2.0-pm/blob/e596c70a19e22c7def4fd3519e20ae4022349390/interop/mocked_eth1data/README.md
|
||||||
|
let
|
||||||
|
epochs_per_period = SLOTS_PER_ETH1_VOTING_PERIOD div SLOTS_PER_EPOCH
|
||||||
|
voting_period = current_epoch.uint64 div epochs_per_period.uint64
|
||||||
|
|
||||||
|
Eth1Data(
|
||||||
|
deposit_root: hash_tree_root(voting_period),
|
||||||
|
deposit_count: deposit_count,
|
||||||
|
block_hash: hash_tree_root(hash_tree_root(voting_period).data),
|
||||||
|
)
|
||||||
|
|
||||||
|
when ValidatorPrivKey is BlsValue:
|
||||||
|
func makeInteropPrivKey*(i: int): ValidatorPrivKey =
|
||||||
|
discard
|
||||||
|
{.fatal: "todo/unused?".}
|
||||||
|
else:
|
||||||
|
func makeInteropPrivKey*(i: int): ValidatorPrivKey =
|
||||||
|
var bytes: array[32, byte]
|
||||||
|
bytes[0..7] = uint64(i).toBytesLE()
|
||||||
|
|
||||||
|
let
|
||||||
|
# BLS381-12 curve order - same as milagro but formatted different
|
||||||
|
curveOrder =
|
||||||
|
"52435875175126190479447740508185965837690552500527637822603658699938581184513".parse(UInt256)
|
||||||
|
|
||||||
|
privkeyBytes = eth2hash(bytes)
|
||||||
|
key = (UInt256.fromBytesLE(privkeyBytes.data) mod curveOrder).toBytesBE()
|
||||||
|
|
||||||
|
ValidatorPrivKey.init(key)
|
||||||
|
|
||||||
|
func makeWithdrawalCredentials*(k: ValidatorPubKey): Eth2Digest =
|
||||||
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.3/specs/core/0_deposit-contract.md#withdrawal-credentials
|
||||||
|
var bytes = eth2hash(k.getBytes())
|
||||||
|
bytes.data[0] = BLS_WITHDRAWAL_PREFIX.uint8
|
||||||
|
bytes
|
||||||
|
|
||||||
|
func makeDeposit*(
|
||||||
|
pubkey: ValidatorPubKey, privkey: ValidatorPrivKey, epoch = 0.Epoch,
|
||||||
|
amount: Gwei = MAX_EFFECTIVE_BALANCE.Gwei,
|
||||||
|
flags: UpdateFlags = {}): Deposit =
|
||||||
|
var
|
||||||
|
ret = Deposit(
|
||||||
|
data: DepositData(
|
||||||
|
amount: amount,
|
||||||
|
pubkey: pubkey,
|
||||||
|
withdrawal_credentials: makeWithdrawalCredentials(pubkey)))
|
||||||
|
|
||||||
|
if skipValidation notin flags:
|
||||||
|
ret.data.signature =
|
||||||
|
bls_sign(
|
||||||
|
privkey, signing_root(ret.data).data, compute_domain(DOMAIN_DEPOSIT))
|
||||||
|
|
||||||
|
ret
|
@ -79,10 +79,9 @@ func process_deposit*(
|
|||||||
|
|
||||||
if index == -1:
|
if index == -1:
|
||||||
# Verify the deposit signature (proof of possession)
|
# Verify the deposit signature (proof of possession)
|
||||||
# TODO should be get_domain(state, DOMAIN_DEPOSIT)
|
|
||||||
if skipValidation notin flags and not bls_verify(
|
if skipValidation notin flags and not bls_verify(
|
||||||
pubkey, signing_root(deposit.data).data, deposit.data.signature,
|
pubkey, signing_root(deposit.data).data, deposit.data.signature,
|
||||||
3'u64):
|
compute_domain(DOMAIN_DEPOSIT)):
|
||||||
return false
|
return false
|
||||||
|
|
||||||
# Add validator and balance entries
|
# Add validator and balance entries
|
||||||
|
@ -98,7 +98,7 @@ func `$`*(x: BlsValue): string =
|
|||||||
else:
|
else:
|
||||||
# r: is short for random. The prefix must be short
|
# r: is short for random. The prefix must be short
|
||||||
# due to the mechanics of the `shortLog` function.
|
# due to the mechanics of the `shortLog` function.
|
||||||
"r:" & toHex(x.blob)
|
"r:" & toHex(x.blob, true)
|
||||||
|
|
||||||
func `==`*(a, b: BlsValue): bool =
|
func `==`*(a, b: BlsValue): bool =
|
||||||
if a.kind != b.kind: return false
|
if a.kind != b.kind: return false
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
# we call this function `eth2hash`, and it outputs a `Eth2Digest`. Easy to sed :)
|
# we call this function `eth2hash`, and it outputs a `Eth2Digest`. Easy to sed :)
|
||||||
|
|
||||||
import
|
import
|
||||||
nimcrypto/[sha2, hash], eth/common/eth_types_json_serialization,
|
chronicles,
|
||||||
|
nimcrypto/[sha2, hash, utils], eth/common/eth_types_json_serialization,
|
||||||
hashes
|
hashes
|
||||||
|
|
||||||
export
|
export
|
||||||
@ -30,9 +31,12 @@ type
|
|||||||
Eth2Digest* = MDigest[32 * 8] ## `hash32` from spec
|
Eth2Digest* = MDigest[32 * 8] ## `hash32` from spec
|
||||||
Eth2Hash* = sha256 ## Context for hash function
|
Eth2Hash* = sha256 ## Context for hash function
|
||||||
|
|
||||||
|
chronicles.formatIt Eth2Digest:
|
||||||
|
mixin toHex
|
||||||
|
it.data.toHex(true)
|
||||||
|
|
||||||
func shortLog*(x: Eth2Digest): string =
|
func shortLog*(x: Eth2Digest): string =
|
||||||
# result = is needed to fix https://github.com/status-im/nim-beacon-chain/issues/209
|
x.data.toHex(true)[0..7]
|
||||||
result = ($x)[0..7]
|
|
||||||
|
|
||||||
# TODO: expose an in-place digest function
|
# TODO: expose an in-place digest function
|
||||||
# when hashing in loop or into a buffer
|
# when hashing in loop or into a buffer
|
||||||
|
@ -145,8 +145,9 @@ func int_to_bytes4*(x: uint64): array[4, byte] =
|
|||||||
result[3] = ((x shr 24) and 0xff).byte
|
result[3] = ((x shr 24) and 0xff).byte
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.3/specs/core/0_beacon-chain.md#compute_domain
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.8.3/specs/core/0_beacon-chain.md#compute_domain
|
||||||
func compute_domain*(domain_type: DomainType, fork_version: array[4, byte]):
|
func compute_domain*(
|
||||||
uint64 =
|
domain_type: DomainType,
|
||||||
|
fork_version: array[4, byte] = [0'u8, 0, 0, 0]): uint64 =
|
||||||
var buf: array[8, byte]
|
var buf: array[8, byte]
|
||||||
buf[0..3] = int_to_bytes4(domain_type.uint64)
|
buf[0..3] = int_to_bytes4(domain_type.uint64)
|
||||||
buf[4..7] = fork_version
|
buf[4..7] = fork_version
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import
|
import
|
||||||
os, ospaths, strutils, strformat, json,
|
os, ospaths, strutils, strformat,
|
||||||
chronos, blscurve, nimcrypto, json_serialization, confutils, web3, stint,
|
chronicles, chronos, blscurve, nimcrypto, json_serialization, web3, stint,
|
||||||
spec/[datatypes, digest, crypto], conf, time, ssz,
|
spec/[datatypes, digest, crypto], conf, time, ssz, interop
|
||||||
../tests/testutil
|
|
||||||
|
|
||||||
contract(DepositContract):
|
contract(DepositContract):
|
||||||
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96)
|
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96)
|
||||||
@ -15,20 +14,12 @@ proc writeFile(filename: string, value: auto) =
|
|||||||
Json.saveFile(filename, value, pretty = true)
|
Json.saveFile(filename, value, pretty = true)
|
||||||
echo "Wrote ", filename
|
echo "Wrote ", filename
|
||||||
|
|
||||||
|
|
||||||
proc ethToWei(eth: UInt256): UInt256 =
|
proc ethToWei(eth: UInt256): UInt256 =
|
||||||
eth * 1000000000000000000.u256
|
eth * 1000000000000000000.u256
|
||||||
|
|
||||||
proc main(totalValidators: int, outputDir: string, generateFakeKeys: bool, depositWeb3Url, depositContractAddress: string) {.async.} =
|
proc generateDeposits*(
|
||||||
var web3: Web3
|
totalValidators: int, outputDir: string, randomKeys: bool): seq[Deposit] =
|
||||||
var contractAddress: Address
|
info "Generating deposits", totalValidators, outputDir, randomKeys
|
||||||
var eth1Addresses: seq[Address]
|
|
||||||
|
|
||||||
if depositWeb3Url.len > 0:
|
|
||||||
web3 = await newWeb3(depositWeb3Url)
|
|
||||||
contractAddress = Address.fromHex(depositContractAddress)
|
|
||||||
eth1Addresses = await web3.provider.eth_accounts()
|
|
||||||
|
|
||||||
for i in 0 ..< totalValidators:
|
for i in 0 ..< totalValidators:
|
||||||
let
|
let
|
||||||
v = validatorFileBaseName(i)
|
v = validatorFileBaseName(i)
|
||||||
@ -36,44 +27,49 @@ proc main(totalValidators: int, outputDir: string, generateFakeKeys: bool, depos
|
|||||||
privKeyFn = outputDir / v & ".privkey"
|
privKeyFn = outputDir / v & ".privkey"
|
||||||
|
|
||||||
if existsFile(depositFn) and existsFile(privKeyFn):
|
if existsFile(depositFn) and existsFile(privKeyFn):
|
||||||
|
try:
|
||||||
|
result.add Json.loadFile(depositFn, Deposit)
|
||||||
continue
|
continue
|
||||||
|
except: # CatchableError?
|
||||||
|
discard
|
||||||
|
|
||||||
let
|
let
|
||||||
privKey = if generateFakeKeys: makeFakeValidatorPrivKey(i)
|
privKey = if randomKeys: ValidatorPrivKey.random
|
||||||
else: ValidatorPrivKey.random
|
else: makeInteropPrivKey(i)
|
||||||
pubKey = privKey.pubKey()
|
pubKey = privKey.pubKey()
|
||||||
|
|
||||||
let
|
let dp = makeDeposit(pubKey, privKey)
|
||||||
withdrawalCredentials = makeFakeHash(i)
|
|
||||||
domain = 3'u64
|
|
||||||
|
|
||||||
var
|
|
||||||
dp = Deposit(
|
|
||||||
data: DepositData(
|
|
||||||
amount: MAX_EFFECTIVE_BALANCE,
|
|
||||||
pubkey: pubKey,
|
|
||||||
withdrawal_credentials: withdrawalCredentials))
|
|
||||||
|
|
||||||
dp.data.signature =
|
|
||||||
bls_sign(privkey, signing_root(dp.data).data,
|
|
||||||
domain)
|
|
||||||
|
|
||||||
writeTextFile(privKeyFn, $privKey)
|
writeTextFile(privKeyFn, $privKey)
|
||||||
writeFile(depositFn, dp)
|
writeFile(depositFn, dp)
|
||||||
|
|
||||||
if not web3.isNil:
|
result.add(dp)
|
||||||
|
|
||||||
|
proc sendDeposits*(
|
||||||
|
deposits: seq[Deposit],
|
||||||
|
depositWeb3Url, depositContractAddress: string) {.async.} =
|
||||||
|
let
|
||||||
|
web3 = await newWeb3(depositWeb3Url)
|
||||||
|
contractAddress = Address.fromHex(depositContractAddress)
|
||||||
|
eth1Addresses = await web3.provider.eth_accounts()
|
||||||
|
|
||||||
|
for i, dp in deposits:
|
||||||
web3.defaultAccount = eth1Addresses[i]
|
web3.defaultAccount = eth1Addresses[i]
|
||||||
let depositContract = web3.contractSender(DepositContract, contractAddress)
|
let depositContract = web3.contractSender(DepositContract, contractAddress)
|
||||||
let tx = await depositContract.deposit(Bytes48(pubKey.getBytes()), Bytes32(withdrawalCredentials.data), Bytes96(dp.data.signature.getBytes())).send(value = 32.u256.ethToWei)
|
let tx = await depositContract.deposit(
|
||||||
|
Bytes48(dp.data.pubKey.getBytes()),
|
||||||
if generateFakeKeys:
|
Bytes32(dp.data.withdrawal_credentials.data),
|
||||||
echo "Keys generated by this tool are only for testing!"
|
Bytes96(dp.data.signature.getBytes())).send(value = 32.u256.ethToWei)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
import confutils
|
||||||
|
|
||||||
cli do (totalValidators: int = 125000,
|
cli do (totalValidators: int = 125000,
|
||||||
outputDir: string = "validators",
|
outputDir: string = "validators",
|
||||||
generateFakeKeys = false,
|
randomKeys: bool = false,
|
||||||
depositWeb3Url: string = "",
|
depositWeb3Url: string = "",
|
||||||
depositContractAddress: string = ""):
|
depositContractAddress: string = ""):
|
||||||
|
let deposits = generateDeposits(totalValidators, outputDir, randomKeys)
|
||||||
|
|
||||||
waitFor main(totalValidators, outputDir, generateFakeKeys, depositWeb3Url, depositContractAddress)
|
if depositWeb3Url.len() > 0 and depositContractAddress.len() > 0:
|
||||||
|
waitFor sendDeposits(deposits, depositWeb3Url, depositContractAddress)
|
||||||
|
3
interop/.gitignore
vendored
Normal file
3
interop/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
data
|
||||||
|
lighthouse
|
||||||
|
validators
|
37
interop/README.md
Normal file
37
interop/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
This folder contains scripts for launching the nimbus beacon chain node in a configuration appropriate for [interop](https://github.com/ethereum/eth2.0-pm/tree/master/interop).
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
In general, follow the build instructions of `nim-beacon-chain` as documented in the main repo - make sure to set up your build environment with all necessary system libraries as documented there:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone repo
|
||||||
|
git clone https://github.com/status-im/nim-beacon-chain.git
|
||||||
|
|
||||||
|
cd nim-beacon-chain
|
||||||
|
|
||||||
|
make # prepare build system (cloning the correct submodules)
|
||||||
|
make update deps # build dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
Look in the scripts for options - the default config is a small setup using the `minimal` state spec.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Clear data from previous run, then start a new simulation
|
||||||
|
rm -rf data ; ./start.sh
|
||||||
|
|
||||||
|
# In a separate terminal, can run another beacon node, such as lighthouse:
|
||||||
|
./run_lighthouse.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Diagnostics
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Nimbus genesis state
|
||||||
|
less data/state_snapshot.json
|
||||||
|
|
||||||
|
# Lighthouse genesis state
|
||||||
|
curl localhost:5052/beacon/state?slot=0 | jq . | sed 's/"0x/"/' | /tmp/lighthouse_state.json
|
||||||
|
```
|
32
interop/run_lighthouse.sh
Executable file
32
interop/run_lighthouse.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Helper script for running a lighthouse node and connecting to the beacon node
|
||||||
|
# that's set up by start.sh
|
||||||
|
|
||||||
|
# https://github.com/sigp/lighthouse/blob/master/docs/interop.md
|
||||||
|
|
||||||
|
cargo_path=$(which cargo)
|
||||||
|
[[ -x "$cargo_path" ]] || { echo "install rust first (https://rust-lang.org)"; exit 1; }
|
||||||
|
|
||||||
|
[[ -d "lighthouse" ]] || {
|
||||||
|
git clone https://github.com/sigp/lighthouse.git
|
||||||
|
cd lighthouse
|
||||||
|
git checkout interop # temporary interop branch - will get merged soon I expect!
|
||||||
|
cargo update
|
||||||
|
cd ..
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch genesis time, as set up by start.sh
|
||||||
|
genesis_time=$(grep -oP '(?<=genesis_time": )\w+(?=,)' data/state_snapshot.json)
|
||||||
|
|
||||||
|
cd lighthouse
|
||||||
|
cargo build
|
||||||
|
|
||||||
|
cd target/debug
|
||||||
|
|
||||||
|
#$export RUST_LOG=libp2p=trace,multistream=trace,gossipsub=trace
|
||||||
|
|
||||||
|
# fresh start!
|
||||||
|
rm -rf ~/.lighthouse
|
||||||
|
|
||||||
|
./beacon_node --libp2p-addresses="/ip4/127.0.0.1/tcp/50000" --api --rpc testnet --spec minimal quick 16 $genesis_time
|
35
interop/run_node.sh
Executable file
35
interop/run_node.sh
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
. $(dirname $0)/vars.sh
|
||||||
|
cd "$GIT_ROOT"
|
||||||
|
|
||||||
|
DATA_DIR="${SIMULATION_DIR}/node-${1}"
|
||||||
|
|
||||||
|
V_PREFIX="${VALIDATORS_DIR}/v$(printf '%06d' ${1})"
|
||||||
|
PORT=$(printf '5%04d' ${1})
|
||||||
|
|
||||||
|
NAT_FLAG="--nat:none"
|
||||||
|
if [ "${NAT:-}" == "1" ]; then
|
||||||
|
NAT_FLAG="--nat:any"
|
||||||
|
fi
|
||||||
|
|
||||||
|
FIRST_VALIDATOR_IDX=$(( (NUM_VALIDATORS / ($NUM_NODES + $NUM_MISSING_NODES)) * $1 ))
|
||||||
|
LAST_VALIDATOR_IDX=$(( (NUM_VALIDATORS / ($NUM_NODES + $NUM_MISSING_NODES)) * ($1 + 1) - 1 ))
|
||||||
|
|
||||||
|
mkdir -p $DATA_DIR/validators
|
||||||
|
rm -f $DATA_DIR/validators/*
|
||||||
|
|
||||||
|
pushd $VALIDATORS_DIR
|
||||||
|
cp $(seq -s " " -f v%07g.privkey $FIRST_VALIDATOR_IDX $LAST_VALIDATOR_IDX) $DATA_DIR/validators
|
||||||
|
popd
|
||||||
|
|
||||||
|
$BEACON_NODE_BIN \
|
||||||
|
--network:$NETWORK_METADATA_FILE \
|
||||||
|
--dataDir:$DATA_DIR \
|
||||||
|
--nodename:${1} \
|
||||||
|
--tcpPort:$PORT \
|
||||||
|
--udpPort:$PORT \
|
||||||
|
$NAT_FLAG \
|
||||||
|
--stateSnapshot:$SNAPSHOT_FILE
|
100
interop/start.sh
Executable file
100
interop/start.sh
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Read in variables
|
||||||
|
. "$(dirname "$0")/vars.sh"
|
||||||
|
|
||||||
|
cd "$SIM_ROOT"
|
||||||
|
mkdir -p "$SIMULATION_DIR"
|
||||||
|
mkdir -p "$VALIDATORS_DIR"
|
||||||
|
|
||||||
|
cd "$GIT_ROOT"
|
||||||
|
|
||||||
|
make update deps
|
||||||
|
|
||||||
|
NIMFLAGS="-d:chronicles_log_level=DEBUG --hints:off --opt:speed --debuginfo"
|
||||||
|
|
||||||
|
# For interop, we run the minimal config
|
||||||
|
DEFS="-d:const_preset=minimal"
|
||||||
|
|
||||||
|
LAST_VALIDATOR_NUM=$(( NUM_VALIDATORS - 1 ))
|
||||||
|
LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.json"
|
||||||
|
|
||||||
|
[[ -x "$BEACON_NODE_BIN" ]] || {
|
||||||
|
echo "Building $BEACON_NODE_BIN ($DEFS)"
|
||||||
|
"$SIM_ROOT/../env.sh" nim c -o:"$BEACON_NODE_BIN" $NIMFLAGS $DEFS beacon_chain/beacon_node
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ! -f "${LAST_VALIDATOR}" ]; then
|
||||||
|
$BEACON_NODE_BIN makeDeposits \
|
||||||
|
--totalDeposits="${NUM_VALIDATORS}" \
|
||||||
|
--depositDir="$VALIDATORS_DIR" \
|
||||||
|
--randomKeys=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "${SNAPSHOT_FILE}" ]; then
|
||||||
|
$BEACON_NODE_BIN \
|
||||||
|
--dataDir="${SIMULATION_DIR}/node-0" \
|
||||||
|
createTestnet \
|
||||||
|
--networkId=1000 \
|
||||||
|
--validatorsDir="${VALIDATORS_DIR}" \
|
||||||
|
--totalValidators="${NUM_VALIDATORS}" \
|
||||||
|
--outputGenesis="${SNAPSHOT_FILE}" \
|
||||||
|
--outputNetwork="${NETWORK_METADATA_FILE}" \
|
||||||
|
--bootstrapAddress=127.0.0.1 \
|
||||||
|
--bootstrapPort=50000 \
|
||||||
|
--genesisOffset=5 # Delay in seconds
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Delete any leftover address files from a previous session
|
||||||
|
if [ -f "${MASTER_NODE_ADDRESS_FILE}" ]; then
|
||||||
|
rm "${MASTER_NODE_ADDRESS_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# multitail support
|
||||||
|
MULTITAIL="${MULTITAIL:-multitail}" # to allow overriding the program name
|
||||||
|
USE_MULTITAIL="${USE_MULTITAIL:-no}" # make it an opt-in
|
||||||
|
type "$MULTITAIL" &>/dev/null || USE_MULTITAIL="no"
|
||||||
|
|
||||||
|
# Kill child processes on Ctrl-C by sending SIGTERM to the whole process group,
|
||||||
|
# passing the negative PID of this shell instance to the "kill" command.
|
||||||
|
# Trap and ignore SIGTERM, so we don't kill this process along with its children.
|
||||||
|
if [ "$USE_MULTITAIL" = "no" ]; then
|
||||||
|
trap '' SIGTERM
|
||||||
|
trap 'kill -- -$$' SIGINT EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMANDS=()
|
||||||
|
LAST_NODE=$(( NUM_NODES - 1 ))
|
||||||
|
|
||||||
|
for i in $(seq 0 $LAST_NODE); do
|
||||||
|
if [[ "$i" == "0" ]]; then
|
||||||
|
sleep 0
|
||||||
|
elif [ "$USE_MULTITAIL" = "no" ]; then
|
||||||
|
# Wait for the master node to write out its address file
|
||||||
|
while [ ! -f "${MASTER_NODE_ADDRESS_FILE}" ]; do
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
CMD="${SIM_ROOT}/run_node.sh $i"
|
||||||
|
|
||||||
|
if [ "$USE_MULTITAIL" != "no" ]; then
|
||||||
|
if [ "$i" = "0" ]; then
|
||||||
|
SLEEP="0"
|
||||||
|
else
|
||||||
|
SLEEP="2"
|
||||||
|
fi
|
||||||
|
# "multitail" closes the corresponding panel when a command exits, so let's make sure it doesn't exit
|
||||||
|
COMMANDS+=( " -cT ansi -t 'node #$i' -l 'sleep $SLEEP; $CMD; echo [node execution completed]; while true; do sleep 100; done'" )
|
||||||
|
else
|
||||||
|
eval "${CMD}" &
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$USE_MULTITAIL" != "no" ]; then
|
||||||
|
eval $MULTITAIL -s 3 -M 0 -x \"Nimbus beacon chain\" "${COMMANDS[@]}"
|
||||||
|
else
|
||||||
|
wait # Stop when all nodes have gone down
|
||||||
|
fi
|
25
interop/vars.sh
Normal file
25
interop/vars.sh
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
PWD_CMD="pwd"
|
||||||
|
# get native Windows paths on Mingw
|
||||||
|
uname | grep -qi mingw && PWD_CMD="pwd -W"
|
||||||
|
|
||||||
|
cd $(dirname $0)
|
||||||
|
|
||||||
|
SIM_ROOT="$($PWD_CMD)"
|
||||||
|
|
||||||
|
# Set a default value for the env vars usually supplied by a Makefile
|
||||||
|
cd $(git rev-parse --show-toplevel)
|
||||||
|
: ${GIT_ROOT:="$($PWD_CMD)"}
|
||||||
|
cd - &>/dev/null
|
||||||
|
|
||||||
|
NUM_VALIDATORS=${VALIDATORS:-16}
|
||||||
|
NUM_NODES=${NODES:-3}
|
||||||
|
NUM_MISSING_NODES=${MISSING_NODES:-1}
|
||||||
|
|
||||||
|
SIMULATION_DIR="${SIM_ROOT}/data"
|
||||||
|
VALIDATORS_DIR="${SIM_ROOT}/validators"
|
||||||
|
SNAPSHOT_FILE="${SIMULATION_DIR}/state_snapshot.json"
|
||||||
|
NETWORK_METADATA_FILE="${SIMULATION_DIR}/network.json"
|
||||||
|
BEACON_NODE_BIN="${SIMULATION_DIR}/beacon_node"
|
||||||
|
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-0/beacon_node.address"
|
@ -19,14 +19,17 @@ NETWORK_DIR=$WWW_DIR/$NETWORK_NAME
|
|||||||
|
|
||||||
NIM_FLAGS="-d:release -d:SECONDS_PER_SLOT=$SECONDS_PER_SLOT -d:SHARD_COUNT=$SHARD_COUNT -d:SLOTS_PER_EPOCH=$SLOTS_PER_EPOCH ${2:-}"
|
NIM_FLAGS="-d:release -d:SECONDS_PER_SLOT=$SECONDS_PER_SLOT -d:SHARD_COUNT=$SHARD_COUNT -d:SLOTS_PER_EPOCH=$SLOTS_PER_EPOCH ${2:-}"
|
||||||
|
|
||||||
|
nim c -d:"network_type=$NETWORK_TYPE" $NIM_FLAGS beacon_chain/beacon_node
|
||||||
|
|
||||||
if [ ! -f $NETWORK_DIR/genesis.json ]; then
|
if [ ! -f $NETWORK_DIR/genesis.json ]; then
|
||||||
rm -f $NETWORK_DIR/*
|
rm -f $NETWORK_DIR/*
|
||||||
nim c -r $NIM_FLAGS beacon_chain/validator_keygen \
|
beacon_chain/beacon_node makeDeposits \
|
||||||
--totalValidators=$VALIDATOR_COUNT \
|
--totalDeposits=$VALIDATOR_COUNT \
|
||||||
--outputDir="$NETWORK_DIR"
|
--depositDir="$NETWORK_DIR" \
|
||||||
|
--randomKeys=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nim c -d:"network_type=$NETWORK_TYPE" -r $NIM_FLAGS beacon_chain/beacon_node \
|
beacon_chain/beacon_node \
|
||||||
--network=$NETWORK_NAME \
|
--network=$NETWORK_NAME \
|
||||||
--dataDir=$DATA_DIR/node-0 \
|
--dataDir=$DATA_DIR/node-0 \
|
||||||
createTestnet \
|
createTestnet \
|
||||||
@ -39,4 +42,3 @@ nim c -d:"network_type=$NETWORK_TYPE" -r $NIM_FLAGS beacon_chain/beacon_node \
|
|||||||
--bootstrapAddress=$PUBLIC_IP \
|
--bootstrapAddress=$PUBLIC_IP \
|
||||||
--bootstrapPort=$BOOTSTRAP_PORT \
|
--bootstrapPort=$BOOTSTRAP_PORT \
|
||||||
--genesisOffset=600 # Delay in seconds
|
--genesisOffset=600 # Delay in seconds
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import # Unit test
|
|||||||
./test_beaconstate,
|
./test_beaconstate,
|
||||||
./test_block_pool,
|
./test_block_pool,
|
||||||
./test_helpers,
|
./test_helpers,
|
||||||
|
./test_interop,
|
||||||
./test_ssz,
|
./test_ssz,
|
||||||
./test_state_transition,
|
./test_state_transition,
|
||||||
./test_sync_protocol
|
./test_sync_protocol
|
||||||
|
@ -15,10 +15,12 @@ mkdir -p "$SIMULATION_DIR"
|
|||||||
mkdir -p "$VALIDATORS_DIR"
|
mkdir -p "$VALIDATORS_DIR"
|
||||||
|
|
||||||
cd "$GIT_ROOT"
|
cd "$GIT_ROOT"
|
||||||
mkdir -p "${BUILD_OUTPUTS_DIR}"
|
|
||||||
|
NIMFLAGS="-d:chronicles_log_level=DEBUG --hints:off --opt:speed --debuginfo"
|
||||||
|
|
||||||
# Run with "SHARD_COUNT=4 ./start.sh" to change these
|
# Run with "SHARD_COUNT=4 ./start.sh" to change these
|
||||||
DEFS="-d:chronicles_log_level=DEBUG "
|
DEFS=""
|
||||||
|
|
||||||
DEFS+="-d:SHARD_COUNT=${SHARD_COUNT:-16} " # Spec default: 1024
|
DEFS+="-d:SHARD_COUNT=${SHARD_COUNT:-16} " # Spec default: 1024
|
||||||
DEFS+="-d:SLOTS_PER_EPOCH=${SLOTS_PER_EPOCH:-16} " # Spec default: 64
|
DEFS+="-d:SLOTS_PER_EPOCH=${SLOTS_PER_EPOCH:-16} " # Spec default: 64
|
||||||
DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-6} " # Spec default: 6
|
DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-6} " # Spec default: 6
|
||||||
@ -26,30 +28,26 @@ DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-6} " # Spec default: 6
|
|||||||
LAST_VALIDATOR_NUM=$(( NUM_VALIDATORS - 1 ))
|
LAST_VALIDATOR_NUM=$(( NUM_VALIDATORS - 1 ))
|
||||||
LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.json"
|
LAST_VALIDATOR="$VALIDATORS_DIR/v$(printf '%07d' $LAST_VALIDATOR_NUM).deposit.json"
|
||||||
|
|
||||||
if [ ! -f "${LAST_VALIDATOR}" ]; then
|
echo "Building $BEACON_NODE_BIN ($DEFS)"
|
||||||
if [[ -z "$SKIP_BUILDS" ]]; then
|
"$SIM_ROOT/../../env.sh" nim c -o:"$BEACON_NODE_BIN" $NIMFLAGS $DEFS beacon_chain/beacon_node
|
||||||
nim c -o:"$VALIDATOR_KEYGEN_BIN" $DEFS -d:release beacon_chain/validator_keygen
|
|
||||||
nim c -o:"$DEPLOY_DEPOSIT_CONTRACT_BIN" $DEFS -d:release beacon_chain/deploy_deposit_contract
|
|
||||||
|
|
||||||
fi
|
if [ ! -f "${LAST_VALIDATOR}" ]; then
|
||||||
|
echo Building $DEPLOY_DEPOSIT_CONTRACT_BIN
|
||||||
|
"$SIM_ROOT/../../env.sh" nim c -o:"$DEPLOY_DEPOSIT_CONTRACT_BIN" $NIMFLAGS $DEFS --hints:off -d:release beacon_chain/deploy_deposit_contract
|
||||||
|
|
||||||
if [ "$DEPOSIT_WEB3_URL_ARG" != "" ]; then
|
if [ "$DEPOSIT_WEB3_URL_ARG" != "" ]; then
|
||||||
DEPOSIT_CONTRACT_ADDRESS=$($DEPLOY_DEPOSIT_CONTRACT_BIN $DEPOSIT_WEB3_URL_ARG)
|
DEPOSIT_CONTRACT_ADDRESS=$($DEPLOY_DEPOSIT_CONTRACT_BIN $DEPOSIT_WEB3_URL_ARG)
|
||||||
export DEPOSIT_CONTRACT_ADDRESS
|
export DEPOSIT_CONTRACT_ADDRESS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$VALIDATOR_KEYGEN_BIN \
|
$BEACON_NODE_BIN makeDeposits \
|
||||||
--totalValidators="${NUM_VALIDATORS}" \
|
--totalDeposits="${NUM_VALIDATORS}" \
|
||||||
--outputDir="$VALIDATORS_DIR" \
|
--depositDir="$VALIDATORS_DIR" \
|
||||||
--generateFakeKeys=yes \
|
--randomKeys=false \
|
||||||
$DEPOSIT_WEB3_URL_ARG \
|
$DEPOSIT_WEB3_URL_ARG \
|
||||||
--depositContractAddress="${DEPOSIT_CONTRACT_ADDRESS}"
|
--depositContractAddress="${DEPOSIT_CONTRACT_ADDRESS}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$SKIP_BUILDS" ]]; then
|
|
||||||
nim c -o:"$BEACON_NODE_BIN" $DEFS --opt:speed --debuginfo beacon_chain/beacon_node
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "${SNAPSHOT_FILE}" ]; then
|
if [ ! -f "${SNAPSHOT_FILE}" ]; then
|
||||||
$BEACON_NODE_BIN \
|
$BEACON_NODE_BIN \
|
||||||
--dataDir="${SIMULATION_DIR}/node-0" \
|
--dataDir="${SIMULATION_DIR}/node-0" \
|
||||||
|
@ -5,14 +5,13 @@ PWD_CMD="pwd"
|
|||||||
uname | grep -qi mingw && PWD_CMD="pwd -W"
|
uname | grep -qi mingw && PWD_CMD="pwd -W"
|
||||||
|
|
||||||
cd $(dirname $0)
|
cd $(dirname $0)
|
||||||
|
|
||||||
SIM_ROOT="$($PWD_CMD)"
|
SIM_ROOT="$($PWD_CMD)"
|
||||||
|
|
||||||
# Set a default value for the env vars usually supplied by a Makefile
|
# Set a default value for the env vars usually supplied by a Makefile
|
||||||
cd $(git rev-parse --show-toplevel)
|
cd $(git rev-parse --show-toplevel)
|
||||||
: ${GIT_ROOT:="$($PWD_CMD)"}
|
: ${GIT_ROOT:="$($PWD_CMD)"}
|
||||||
cd - &>/dev/null
|
cd - &>/dev/null
|
||||||
: ${SKIP_BUILDS:=""}
|
|
||||||
: ${BUILD_OUTPUTS_DIR:="$GIT_ROOT/build"}
|
|
||||||
|
|
||||||
NUM_VALIDATORS=${VALIDATORS:-1000}
|
NUM_VALIDATORS=${VALIDATORS:-1000}
|
||||||
NUM_NODES=${NODES:-4}
|
NUM_NODES=${NODES:-4}
|
||||||
@ -22,7 +21,6 @@ SIMULATION_DIR="${SIM_ROOT}/data"
|
|||||||
VALIDATORS_DIR="${SIM_ROOT}/validators"
|
VALIDATORS_DIR="${SIM_ROOT}/validators"
|
||||||
SNAPSHOT_FILE="${SIMULATION_DIR}/state_snapshot.json"
|
SNAPSHOT_FILE="${SIMULATION_DIR}/state_snapshot.json"
|
||||||
NETWORK_METADATA_FILE="${SIMULATION_DIR}/network.json"
|
NETWORK_METADATA_FILE="${SIMULATION_DIR}/network.json"
|
||||||
BEACON_NODE_BIN="${BUILD_OUTPUTS_DIR}/beacon_node"
|
BEACON_NODE_BIN="${SIMULATION_DIR}/beacon_node"
|
||||||
VALIDATOR_KEYGEN_BIN="${BUILD_OUTPUTS_DIR}/validator_keygen"
|
DEPLOY_DEPOSIT_CONTRACT_BIN="${SIMULATION_DIR}/deploy_deposit_contract"
|
||||||
DEPLOY_DEPOSIT_CONTRACT_BIN="${BUILD_OUTPUTS_DIR}/deploy_deposit_contract"
|
|
||||||
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-0/beacon_node.address"
|
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-0/beacon_node.address"
|
||||||
|
30
tests/test_interop.nim
Normal file
30
tests/test_interop.nim
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import
|
||||||
|
unittest, stint, blscurve,
|
||||||
|
../beacon_chain/interop
|
||||||
|
|
||||||
|
# Interop test yaml, found here:
|
||||||
|
# https://github.com/ethereum/eth2.0-pm/blob/a0b9d22fad424574b1307828f867b30237758468/interop/mocked_start/keygen_10_validators.yaml
|
||||||
|
|
||||||
|
const privateKeys = [
|
||||||
|
"0x25295f0d1d592a90b333e26e85149708208e9f8e8bc18f6c77bd62f8ad7a6866",
|
||||||
|
"0x51d0b65185db6989ab0b560d6deed19c7ead0e24b9b6372cbecb1f26bdfad000",
|
||||||
|
"0x315ed405fafe339603932eebe8dbfd650ce5dafa561f6928664c75db85f97857",
|
||||||
|
"0x25b1166a43c109cb330af8945d364722757c65ed2bfed5444b5a2f057f82d391",
|
||||||
|
"0x3f5615898238c4c4f906b507ee917e9ea1bb69b93f1dbd11a34d229c3b06784b",
|
||||||
|
"0x055794614bc85ed5436c1f5cab586aab6ca84835788621091f4f3b813761e7a8",
|
||||||
|
"0x1023c68852075965e0f7352dee3f76a84a83e7582c181c10179936c6d6348893",
|
||||||
|
"0x3a941600dc41e5d20e818473b817a28507c23cdfdb4b659c15461ee5c71e41f5",
|
||||||
|
"0x066e3bdc0415530e5c7fed6382d5c822c192b620203cf669903e1810a8c67d06",
|
||||||
|
"0x2b3b88a041168a1c4cd04bdd8de7964fd35238f95442dc678514f9dadb81ec34",
|
||||||
|
]
|
||||||
|
|
||||||
|
suite "Interop":
|
||||||
|
test "Mocked start private key":
|
||||||
|
for i, k in privateKeys:
|
||||||
|
let
|
||||||
|
key = makeInteropPrivKey(i)
|
||||||
|
v = k.parse(UInt256, 16)
|
||||||
|
|
||||||
|
check:
|
||||||
|
# getBytes is bigendian and returns full 48 bytes of key..
|
||||||
|
Uint256.fromBytesBE(key.getBytes()[48-32..<48]) == v
|
Loading…
x
Reference in New Issue
Block a user