mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-08 20:54:33 +00:00
Smooth out the differences between Ganache and Infura; Working local sim and Altona target
This commit is contained in:
parent
14274587cf
commit
7211a99086
14
Makefile
14
Makefile
@ -133,7 +133,7 @@ $(TOOLS): | build deps
|
|||||||
$(ENV_SCRIPT) nim c -o:build/$@ $(NIM_PARAMS) "$${TOOL_DIR}/$@.nim"
|
$(ENV_SCRIPT) nim c -o:build/$@ $(NIM_PARAMS) "$${TOOL_DIR}/$@.nim"
|
||||||
|
|
||||||
clean_eth2_network_simulation_data:
|
clean_eth2_network_simulation_data:
|
||||||
rm -rf tests/simulation/{data}
|
rm -rf tests/simulation/data
|
||||||
|
|
||||||
clean_eth2_network_simulation_all:
|
clean_eth2_network_simulation_all:
|
||||||
rm -rf tests/simulation/{data,validators}
|
rm -rf tests/simulation/{data,validators}
|
||||||
@ -153,14 +153,14 @@ testnet0 testnet1: | build deps
|
|||||||
source scripts/$@.env; \
|
source scripts/$@.env; \
|
||||||
NIM_PARAMS="$(subst ",\",$(NIM_PARAMS))" LOG_LEVEL="$(LOG_LEVEL)" $(ENV_SCRIPT) nim $(NIM_PARAMS) scripts/connect_to_testnet.nims $(SCRIPT_PARAMS) --const-preset=$$CONST_PRESET --dev-build $@
|
NIM_PARAMS="$(subst ",\",$(NIM_PARAMS))" LOG_LEVEL="$(LOG_LEVEL)" $(ENV_SCRIPT) nim $(NIM_PARAMS) scripts/connect_to_testnet.nims $(SCRIPT_PARAMS) --const-preset=$$CONST_PRESET --dev-build $@
|
||||||
|
|
||||||
clean-schlesi:
|
clean-altona:
|
||||||
rm -rf build/data/shared_schlesi*
|
rm -rf build/data/shared_altona*
|
||||||
|
|
||||||
schlesi: | build deps
|
altona: | build deps
|
||||||
NIM_PARAMS="$(subst ",\",$(NIM_PARAMS))" LOG_LEVEL="$(LOG_LEVEL)" $(ENV_SCRIPT) nim $(NIM_PARAMS) scripts/connect_to_testnet.nims $(SCRIPT_PARAMS) shared/schlesi
|
NIM_PARAMS="$(subst ",\",$(NIM_PARAMS))" LOG_LEVEL="$(LOG_LEVEL)" $(ENV_SCRIPT) nim $(NIM_PARAMS) scripts/connect_to_testnet.nims --spec=v0.12.1 $(SCRIPT_PARAMS) shared/altona
|
||||||
|
|
||||||
schlesi-dev: | build deps
|
altona-dev: | build deps
|
||||||
NIM_PARAMS="$(subst ",\",$(NIM_PARAMS))" LOG_LEVEL="DEBUG; TRACE:discv5,networking; REQUIRED:none; DISABLED:none" $(ENV_SCRIPT) nim $(NIM_PARAMS) scripts/connect_to_testnet.nims $(SCRIPT_PARAMS) shared/schlesi
|
NIM_PARAMS="$(subst ",\",$(NIM_PARAMS))" LOG_LEVEL="DEBUG; TRACE:discv5,networking; REQUIRED:none; DISABLED:none" $(ENV_SCRIPT) nim $(NIM_PARAMS) scripts/connect_to_testnet.nims $(SCRIPT_PARAMS) shared/altona
|
||||||
|
|
||||||
clean-witti:
|
clean-witti:
|
||||||
rm -rf build/data/shared_witti*
|
rm -rf build/data/shared_witti*
|
||||||
|
@ -18,7 +18,7 @@ import
|
|||||||
eth/p2p/enode, eth/[keys, async_utils], eth/p2p/discoveryv5/[protocol, enr],
|
eth/p2p/enode, eth/[keys, async_utils], eth/p2p/discoveryv5/[protocol, enr],
|
||||||
|
|
||||||
# Local modules
|
# Local modules
|
||||||
spec/[datatypes, digest, crypto, beaconstate, helpers, network],
|
spec/[datatypes, digest, crypto, beaconstate, helpers, network, signatures],
|
||||||
spec/presets/custom,
|
spec/presets/custom,
|
||||||
conf, time, beacon_chain_db, validator_pool, extras,
|
conf, time, beacon_chain_db, validator_pool, extras,
|
||||||
attestation_pool, block_pool, eth2_network, eth2_discovery,
|
attestation_pool, block_pool, eth2_network, eth2_discovery,
|
||||||
@ -153,7 +153,7 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
|||||||
mainchainMonitor = MainchainMonitor.init(
|
mainchainMonitor = MainchainMonitor.init(
|
||||||
web3Provider(conf.web3Url),
|
web3Provider(conf.web3Url),
|
||||||
conf.depositContractAddress,
|
conf.depositContractAddress,
|
||||||
Eth2Digest())
|
conf.depositContractDeployedAt)
|
||||||
mainchainMonitor.start()
|
mainchainMonitor.start()
|
||||||
else:
|
else:
|
||||||
error "No initial state, need genesis state or deposit contract address"
|
error "No initial state, need genesis state or deposit contract address"
|
||||||
@ -195,7 +195,7 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
|||||||
mainchainMonitor = MainchainMonitor.init(
|
mainchainMonitor = MainchainMonitor.init(
|
||||||
web3Provider(conf.web3Url),
|
web3Provider(conf.web3Url),
|
||||||
conf.depositContractAddress,
|
conf.depositContractAddress,
|
||||||
blockPool.headState.data.data.eth1_data.block_hash)
|
some blockPool.headState.data.data.eth1_data.block_hash)
|
||||||
# TODO if we don't have any validators attached, we don't need a mainchain
|
# TODO if we don't have any validators attached, we don't need a mainchain
|
||||||
# monitor
|
# monitor
|
||||||
mainchainMonitor.start()
|
mainchainMonitor.start()
|
||||||
@ -838,7 +838,7 @@ proc createPidFile(filename: string) =
|
|||||||
proc initializeNetworking(node: BeaconNode) {.async.} =
|
proc initializeNetworking(node: BeaconNode) {.async.} =
|
||||||
node.network.startListening()
|
node.network.startListening()
|
||||||
|
|
||||||
let addressFile = node.config.dataDir / "beacon_node.address"
|
let addressFile = node.config.dataDir / "beacon_node.enr"
|
||||||
writeFile(addressFile, node.network.announcedENR.toURI)
|
writeFile(addressFile, node.network.announcedENR.toURI)
|
||||||
|
|
||||||
await node.network.startLookingForPeers()
|
await node.network.startLookingForPeers()
|
||||||
|
@ -5,7 +5,7 @@ import
|
|||||||
chronicles, confutils, json_serialization,
|
chronicles, confutils, json_serialization,
|
||||||
confutils/defs, confutils/std/net,
|
confutils/defs, confutils/std/net,
|
||||||
chronicles/options as chroniclesOptions,
|
chronicles/options as chroniclesOptions,
|
||||||
spec/[crypto, keystore]
|
spec/[crypto, keystore, digest]
|
||||||
|
|
||||||
export
|
export
|
||||||
defs, enabledLogLevel, parseCmdArg, completeCmdArg
|
defs, enabledLogLevel, parseCmdArg, completeCmdArg
|
||||||
@ -62,6 +62,10 @@ type
|
|||||||
desc: "Address of the deposit contract."
|
desc: "Address of the deposit contract."
|
||||||
name: "deposit-contract" }: string
|
name: "deposit-contract" }: string
|
||||||
|
|
||||||
|
depositContractDeployedAt* {.
|
||||||
|
desc: "The Eth1 block hash where the deposit contract has been deployed."
|
||||||
|
name: "deposit-contract-block" }: Option[Eth2Digest]
|
||||||
|
|
||||||
nonInteractive* {.
|
nonInteractive* {.
|
||||||
desc: "Do not display interative prompts. Quit on missing configuration."
|
desc: "Do not display interative prompts. Quit on missing configuration."
|
||||||
name: "non-interactive" }: bool
|
name: "non-interactive" }: bool
|
||||||
@ -366,6 +370,13 @@ proc createDumpDirs*(conf: BeaconNodeConf) =
|
|||||||
# Dumping is mainly a debugging feature, so ignore these..
|
# Dumping is mainly a debugging feature, so ignore these..
|
||||||
warn "Cannot create dump directories", msg = err.msg
|
warn "Cannot create dump directories", msg = err.msg
|
||||||
|
|
||||||
|
func parseCmdArg*(T: type Eth2Digest, input: TaintedString): T
|
||||||
|
{.raises: [ValueError, Defect].} =
|
||||||
|
fromHex(T, string input)
|
||||||
|
|
||||||
|
func completeCmdArg*(T: type Eth2Digest, input: TaintedString): seq[string] =
|
||||||
|
return @[]
|
||||||
|
|
||||||
func validatorsDir*(conf: BeaconNodeConf|ValidatorClientConf): string =
|
func validatorsDir*(conf: BeaconNodeConf|ValidatorClientConf): string =
|
||||||
string conf.validatorsDirFlag.get(InputDir(conf.dataDir / "validators"))
|
string conf.validatorsDirFlag.get(InputDir(conf.dataDir / "validators"))
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ proc loadBootstrapFile*(bootstrapFile: string,
|
|||||||
localPubKey: PublicKey) =
|
localPubKey: PublicKey) =
|
||||||
if bootstrapFile.len == 0: return
|
if bootstrapFile.len == 0: return
|
||||||
let ext = splitFile(bootstrapFile).ext
|
let ext = splitFile(bootstrapFile).ext
|
||||||
if cmpIgnoreCase(ext, ".txt") == 0:
|
if cmpIgnoreCase(ext, ".txt") == 0 or cmpIgnoreCase(ext, ".enr") == 0 :
|
||||||
try:
|
try:
|
||||||
for ln in lines(bootstrapFile):
|
for ln in lines(bootstrapFile):
|
||||||
addBootstrapNode(ln, bootstrapEnrs, localPubKey)
|
addBootstrapNode(ln, bootstrapEnrs, localPubKey)
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import
|
import
|
||||||
deques, tables, hashes, options,
|
deques, tables, hashes, options, strformat,
|
||||||
chronos, web3, json, chronicles, eth/async_utils,
|
chronos, web3, web3/ethtypes, json, chronicles, eth/async_utils,
|
||||||
spec/[datatypes, digest, crypto, beaconstate, helpers],
|
spec/[datatypes, digest, crypto, beaconstate, helpers, signatures],
|
||||||
merkle_minimal
|
merkle_minimal
|
||||||
|
|
||||||
|
export
|
||||||
|
ethtypes
|
||||||
|
|
||||||
contract(DepositContract):
|
contract(DepositContract):
|
||||||
proc deposit(pubkey: Bytes48,
|
proc deposit(pubkey: Bytes48,
|
||||||
withdrawalCredentials: Bytes32,
|
withdrawalCredentials: Bytes32,
|
||||||
@ -38,8 +41,9 @@ type
|
|||||||
blocksByHash: Table[BlockHash, Eth1Block]
|
blocksByHash: Table[BlockHash, Eth1Block]
|
||||||
|
|
||||||
MainchainMonitor* = ref object
|
MainchainMonitor* = ref object
|
||||||
startBlock: BlockHash
|
|
||||||
depositContractAddress: Address
|
depositContractAddress: Address
|
||||||
|
startBlock: Option[Eth2Digest]
|
||||||
|
|
||||||
dataProviderFactory*: DataProviderFactory
|
dataProviderFactory*: DataProviderFactory
|
||||||
|
|
||||||
genesisState: NilableBeaconStateRef
|
genesisState: NilableBeaconStateRef
|
||||||
@ -108,7 +112,7 @@ func is_candidate_block(blk: Eth1Block, period_start: uint64): bool =
|
|||||||
(blk.timestamp + SECONDS_PER_ETH1_BLOCK.uint64 * ETH1_FOLLOW_DISTANCE.uint64 <= period_start) and
|
(blk.timestamp + SECONDS_PER_ETH1_BLOCK.uint64 * ETH1_FOLLOW_DISTANCE.uint64 <= period_start) and
|
||||||
(blk.timestamp + SECONDS_PER_ETH1_BLOCK.uint64 * ETH1_FOLLOW_DISTANCE.uint64 * 2 >= period_start)
|
(blk.timestamp + SECONDS_PER_ETH1_BLOCK.uint64 * ETH1_FOLLOW_DISTANCE.uint64 * 2 >= period_start)
|
||||||
|
|
||||||
func asEth2Digest(x: BlockHash): Eth2Digest =
|
func asEth2Digest*(x: BlockHash): Eth2Digest =
|
||||||
Eth2Digest(data: array[32, byte](x))
|
Eth2Digest(data: array[32, byte](x))
|
||||||
|
|
||||||
template asBlockHash(x: Eth2Digest): BlockHash =
|
template asBlockHash(x: Eth2Digest): BlockHash =
|
||||||
@ -149,23 +153,6 @@ proc findParent*(eth1Chain: Eth1Chain, blk: BlockObject): Eth1Block =
|
|||||||
parentHash = blk.parentHash.toHex, parentNumber = result.number
|
parentHash = blk.parentHash.toHex, parentNumber = result.number
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
when false:
|
|
||||||
func getCacheIdx(eth1Chain: Eth1Chain, blockNumber: Eth1BlockNumber): int =
|
|
||||||
if eth1Chain.blocks.len == 0:
|
|
||||||
return -1
|
|
||||||
|
|
||||||
let idx = blockNumber - eth1Chain.blocks[0].number
|
|
||||||
if idx < 0 or idx >= eth1Chain.blocks.len:
|
|
||||||
return -1
|
|
||||||
|
|
||||||
idx
|
|
||||||
|
|
||||||
func `{}`*(eth1Chain: Eth1Chain, blockNumber: Eth1BlockNumber): Eth1Block =
|
|
||||||
## Finds a block in our cache that corresponds to a particular Eth block
|
|
||||||
## number. May return `nil` if we don't have such a block in the cache.
|
|
||||||
let idx = eth1Chain.getCacheIdx(blockNumber)
|
|
||||||
if idx != -1: eth1Chain.blocks[idx] else: nil
|
|
||||||
|
|
||||||
func latestCandidateBlock(eth1Chain: Eth1Chain, periodStart: uint64): Eth1Block =
|
func latestCandidateBlock(eth1Chain: Eth1Chain, periodStart: uint64): Eth1Block =
|
||||||
for i in countdown(eth1Chain.blocks.len - 1, 0):
|
for i in countdown(eth1Chain.blocks.len - 1, 0):
|
||||||
let blk = eth1Chain.blocks[i]
|
let blk = eth1Chain.blocks[i]
|
||||||
@ -209,6 +196,9 @@ func allDeposits*(eth1Chain: Eth1Chain): seq[Deposit] =
|
|||||||
for blk in eth1Chain.blocks:
|
for blk in eth1Chain.blocks:
|
||||||
result.add blk.deposits
|
result.add blk.deposits
|
||||||
|
|
||||||
|
func clear*(eth1Chain: var Eth1Chain) =
|
||||||
|
eth1Chain = default(Eth1Chain)
|
||||||
|
|
||||||
template hash*(x: Eth1Block): Hash =
|
template hash*(x: Eth1Block): Hash =
|
||||||
hash(x.voteData.block_hash.data)
|
hash(x.voteData.block_hash.data)
|
||||||
|
|
||||||
@ -221,8 +211,7 @@ method getBlockByHash*(p: DataProviderRef, hash: BlockHash): Future[BlockObject]
|
|||||||
locks: 0
|
locks: 0
|
||||||
# raises: [Defect]
|
# raises: [Defect]
|
||||||
.} =
|
.} =
|
||||||
discard
|
notImplemented
|
||||||
# notImplemented
|
|
||||||
|
|
||||||
method onDisconnect*(p: DataProviderRef, handler: DisconnectHandler) {.
|
method onDisconnect*(p: DataProviderRef, handler: DisconnectHandler) {.
|
||||||
base
|
base
|
||||||
@ -250,6 +239,15 @@ method close*(p: DataProviderRef): Future[void] {.
|
|||||||
.} =
|
.} =
|
||||||
notImplemented
|
notImplemented
|
||||||
|
|
||||||
|
method hasDepositContract*(p: DataProviderRef,
|
||||||
|
web3Block: BlockObject): Future[bool] {.
|
||||||
|
base
|
||||||
|
gcsafe
|
||||||
|
locks: 0
|
||||||
|
# raises: [Defect, CatchableError]
|
||||||
|
.} =
|
||||||
|
notImplemented
|
||||||
|
|
||||||
method fetchDepositData*(p: DataProviderRef,
|
method fetchDepositData*(p: DataProviderRef,
|
||||||
web3Block: BlockObject): Future[Eth1Block] {.
|
web3Block: BlockObject): Future[Eth1Block] {.
|
||||||
base
|
base
|
||||||
@ -298,13 +296,11 @@ template getBlockProposalData*(m: MainchainMonitor, state: BeaconState): untyped
|
|||||||
proc init*(T: type MainchainMonitor,
|
proc init*(T: type MainchainMonitor,
|
||||||
dataProviderFactory: DataProviderFactory,
|
dataProviderFactory: DataProviderFactory,
|
||||||
depositContractAddress: string,
|
depositContractAddress: string,
|
||||||
startBlock: Eth2Digest): T =
|
startBlock: Option[Eth2Digest]): T =
|
||||||
T(depositContractAddress: Address.fromHex(depositContractAddress),
|
T(depositQueue: newAsyncQueue[DepositQueueElem](),
|
||||||
depositQueue: newAsyncQueue[DepositQueueElem](),
|
dataProviderFactory: dataProviderFactory,
|
||||||
startBlock: BlockHash(startBlock.data),
|
depositContractAddress: Address.fromHex(depositContractAddress),
|
||||||
dataProviderFactory: dataProviderFactory)
|
startBlock: startBlock)
|
||||||
|
|
||||||
const MIN_GENESIS_TIME = 0
|
|
||||||
|
|
||||||
proc readJsonDeposits(depositsList: JsonNode): seq[Deposit] =
|
proc readJsonDeposits(depositsList: JsonNode): seq[Deposit] =
|
||||||
if depositsList.kind != JArray:
|
if depositsList.kind != JArray:
|
||||||
@ -321,11 +317,11 @@ proc readJsonDeposits(depositsList: JsonNode): seq[Deposit] =
|
|||||||
index: Bytes8
|
index: Bytes8
|
||||||
|
|
||||||
var offset = 0
|
var offset = 0
|
||||||
offset = decode(logData, offset, pubkey)
|
offset += decode(logData, offset, pubkey)
|
||||||
offset = decode(logData, offset, withdrawalCredentials)
|
offset += decode(logData, offset, withdrawalCredentials)
|
||||||
offset = decode(logData, offset, amount)
|
offset += decode(logData, offset, amount)
|
||||||
offset = decode(logData, offset, signature)
|
offset += decode(logData, offset, signature)
|
||||||
offset = decode(logData, offset, index)
|
offset += decode(logData, offset, index)
|
||||||
|
|
||||||
result.add Deposit(
|
result.add Deposit(
|
||||||
data: DepositData(
|
data: DepositData(
|
||||||
@ -352,22 +348,20 @@ proc checkForGenesisEvent(m: MainchainMonitor) =
|
|||||||
startTime, genesisDeposits, {})
|
startTime, genesisDeposits, {})
|
||||||
if is_valid_genesis_state(s[]):
|
if is_valid_genesis_state(s[]):
|
||||||
# https://github.com/ethereum/eth2.0-pm/tree/6e41fcf383ebeb5125938850d8e9b4e9888389b4/interop/mocked_start#create-genesis-state
|
# https://github.com/ethereum/eth2.0-pm/tree/6e41fcf383ebeb5125938850d8e9b4e9888389b4/interop/mocked_start#create-genesis-state
|
||||||
s.genesis_time = startTime
|
|
||||||
|
|
||||||
info "Eth2 genesis state detected",
|
info "Eth2 genesis state detected",
|
||||||
genesisTime = startTime,
|
genesisTime = startTime,
|
||||||
genesisEth1Block = lastBlock.voteData.block_hash
|
genesisEth1Block = lastBlock.voteData.block_hash
|
||||||
|
|
||||||
|
s.genesis_time = startTime
|
||||||
m.genesisState = s
|
m.genesisState = s
|
||||||
|
|
||||||
if not m.genesisStateFut.isNil:
|
if not m.genesisStateFut.isNil:
|
||||||
m.genesisStateFut.complete()
|
m.genesisStateFut.complete()
|
||||||
m.genesisStateFut = nil
|
m.genesisStateFut = nil
|
||||||
|
|
||||||
proc processDeposits(m: MainchainMonitor, dataProvider: DataProviderRef) {.
|
proc processDeposits(m: MainchainMonitor,
|
||||||
async
|
dataProvider: DataProviderRef,
|
||||||
# raises: [Defect]
|
startBlkNum: Eth1BlockNumber) {.async.} =
|
||||||
.} =
|
|
||||||
# ATTENTION!
|
# ATTENTION!
|
||||||
# Please note that this code is using a queue to guarantee the
|
# Please note that this code is using a queue to guarantee the
|
||||||
# strict serial order of processing of deposits. If we had the
|
# strict serial order of processing of deposits. If we had the
|
||||||
@ -386,50 +380,60 @@ proc processDeposits(m: MainchainMonitor, dataProvider: DataProviderRef) {.
|
|||||||
let cachedBlock = m.eth1Chain.findBlock(blockHash)
|
let cachedBlock = m.eth1Chain.findBlock(blockHash)
|
||||||
if cachedBlock == nil:
|
if cachedBlock == nil:
|
||||||
try:
|
try:
|
||||||
let
|
let web3Block = await dataProvider.getBlockByHash(blockHash)
|
||||||
web3Block = await dataProvider.getBlockByHash(blockHash)
|
doAssert Eth1BlockNumber(web3Block.number) > startBlkNum
|
||||||
eth1Block = await dataProvider.fetchDepositData(web3Block)
|
let eth1Block = await dataProvider.fetchDepositData(web3Block)
|
||||||
|
|
||||||
if m.eth1Chain.blocks.len > 0:
|
var cachedParent = m.eth1Chain.findParent(web3Block)
|
||||||
var cachedParent = m.eth1Chain.findParent(web3Block)
|
if cachedParent == nil:
|
||||||
if cachedParent == nil:
|
# We are missing the parent block.
|
||||||
# We are missing the parent block.
|
# This shouldn't be happening if the deposits events are reported in
|
||||||
# This shouldn't be happening if the deposits events are reported in
|
# proper order, but nevertheless let's try to repair our chain:
|
||||||
# proper order, but nevertheless let's try to repair our chain:
|
var chainOfParents = newSeq[Eth1Block]()
|
||||||
var chainOfParents = newSeq[Eth1Block]()
|
var parentHash = web3Block.parentHash
|
||||||
var parentHash = web3Block.parentHash
|
|
||||||
var expectedParentBlockNumber = web3Block.number.uint64 - 1
|
|
||||||
warn "Eth1 parent block missing. Attempting to request from the network",
|
|
||||||
parentHash = parentHash.toHex
|
|
||||||
|
|
||||||
while true:
|
var expectedParentBlockNumber = web3Block.number.uint64 - 1
|
||||||
if chainOfParents.len > reorgDepthLimit:
|
debug "Eth1 parent block missing. Attempting to request from the network",
|
||||||
error "Detected Eth1 re-org exceeded the maximum depth limit",
|
parentHash = parentHash.toHex, expectedParentBlockNumber
|
||||||
headBlockHash = web3Block.hash.toHex,
|
|
||||||
ourHeadHash = m.eth1Chain.blocks.peekLast.voteData.block_hash
|
|
||||||
raise newException(ReorgDepthLimitExceeded, "Reorg depth limit exceeded")
|
|
||||||
|
|
||||||
let parentWeb3Block = await dataProvider.getBlockByHash(parentHash)
|
while true:
|
||||||
if parentWeb3Block.number.uint64 != expectedParentBlockNumber:
|
if chainOfParents.len > reorgDepthLimit:
|
||||||
error "Eth1 data provider supplied invalid parent block",
|
error "Detected Eth1 re-org exceeded the maximum depth limit",
|
||||||
parentBlockNumber = parentWeb3Block.number.uint64,
|
headBlockHash = web3Block.hash.toHex,
|
||||||
expectedParentBlockNumber, parentHash = parentHash.toHex
|
ourHeadHash = m.eth1Chain.blocks.peekLast.voteData.block_hash
|
||||||
raise newException(CorruptDataProvider,
|
raise newException(ReorgDepthLimitExceeded, "Reorg depth limit exceeded")
|
||||||
"Parent block with incorrect number")
|
|
||||||
|
|
||||||
chainOfParents.add(await dataProvider.fetchDepositData(parentWeb3Block))
|
let parentWeb3Block = await dataProvider.getBlockByHash(parentHash)
|
||||||
let localParent = m.eth1Chain.findParent(parentWeb3Block)
|
if parentWeb3Block.number.uint64 != expectedParentBlockNumber:
|
||||||
if localParent != nil:
|
error "Eth1 data provider supplied invalid parent block",
|
||||||
m.eth1Chain.purgeDescendants(localParent)
|
parentBlockNumber = parentWeb3Block.number.uint64,
|
||||||
for i in countdown(chainOfParents.len - 1, 0):
|
expectedParentBlockNumber, parentHash = parentHash.toHex
|
||||||
m.eth1Chain.addBlock chainOfParents[i]
|
raise newException(CorruptDataProvider,
|
||||||
cachedParent = m.eth1Chain.blocks.peekLast
|
"Parent block with incorrect number")
|
||||||
break
|
|
||||||
|
|
||||||
dec expectedParentBlockNumber
|
if expectedParentBlockNumber <= startBlkNum or
|
||||||
parentHash = parentWeb3Block.parentHash
|
startBlkNum == 0 and not await dataProvider.hasDepositContract(parentWeb3Block):
|
||||||
|
# We've reached the deposit contract creation
|
||||||
|
# No more deposit events are expected
|
||||||
|
m.eth1Chain.clear()
|
||||||
|
for i in countdown(chainOfParents.len - 1, 0):
|
||||||
|
m.eth1Chain.addBlock chainOfParents[i]
|
||||||
|
cachedParent = m.eth1Chain.blocks.peekLast
|
||||||
|
break
|
||||||
|
|
||||||
m.eth1Chain.purgeDescendants(cachedParent)
|
chainOfParents.add(await dataProvider.fetchDepositData(parentWeb3Block))
|
||||||
|
let localParent = m.eth1Chain.findParent(parentWeb3Block)
|
||||||
|
if localParent != nil:
|
||||||
|
m.eth1Chain.purgeDescendants(localParent)
|
||||||
|
for i in countdown(chainOfParents.len - 1, 0):
|
||||||
|
m.eth1Chain.addBlock chainOfParents[i]
|
||||||
|
cachedParent = m.eth1Chain.blocks.peekLast
|
||||||
|
break
|
||||||
|
|
||||||
|
dec expectedParentBlockNumber
|
||||||
|
parentHash = parentWeb3Block.parentHash
|
||||||
|
|
||||||
|
m.eth1Chain.purgeDescendants(cachedParent)
|
||||||
|
|
||||||
# TODO: We may check that the new deposits produce a merkle
|
# TODO: We may check that the new deposits produce a merkle
|
||||||
# root matching the `deposit_root` value from the block.
|
# root matching the `deposit_root` value from the block.
|
||||||
@ -462,21 +466,26 @@ proc getGenesis*(m: MainchainMonitor): Future[BeaconStateRef] {.async.} =
|
|||||||
raiseAssert "Unreachable code"
|
raiseAssert "Unreachable code"
|
||||||
|
|
||||||
method getBlockByHash*(p: Web3DataProviderRef, hash: BlockHash): Future[BlockObject] =
|
method getBlockByHash*(p: Web3DataProviderRef, hash: BlockHash): Future[BlockObject] =
|
||||||
p.web3.provider.eth_getBlockByHash(hash, false)
|
return p.web3.provider.eth_getBlockByHash(hash, false)
|
||||||
|
|
||||||
method close*(p: Web3DataProviderRef): Future[void] {.async, locks: 0.} =
|
method close*(p: Web3DataProviderRef): Future[void] {.async, locks: 0.} =
|
||||||
if p.subscription != nil:
|
if p.subscription != nil:
|
||||||
await p.subscription.unsubscribe()
|
await p.subscription.unsubscribe()
|
||||||
await p.web3.close()
|
await p.web3.close()
|
||||||
|
|
||||||
|
method hasDepositContract*(p: Web3DataProviderRef,
|
||||||
|
web3Block: BlockObject): Future[bool] {.async, locks: 0.} =
|
||||||
|
result = await p.ns.isDeployed(web3Block.blockId)
|
||||||
|
|
||||||
method fetchDepositData*(p: Web3DataProviderRef,
|
method fetchDepositData*(p: Web3DataProviderRef,
|
||||||
web3Block: BlockObject): Future[Eth1Block] {.async, locks: 0.} =
|
web3Block: BlockObject): Future[Eth1Block] {.async, locks: 0.} =
|
||||||
let
|
let
|
||||||
blockHash = web3Block.hash
|
blockHash = web3Block.hash
|
||||||
|
blockId = web3Block.blockId
|
||||||
depositRoot = await p.ns.get_deposit_root.call(blockNumber = web3Block.number.uint64)
|
depositRoot = await p.ns.get_deposit_root.call(blockNumber = web3Block.number.uint64)
|
||||||
rawCount = await p.ns.get_deposit_count.call(blockNumber = web3Block.number.uint64)
|
rawCount = await p.ns.get_deposit_count.call(blockNumber = web3Block.number.uint64)
|
||||||
depositCount = bytes_to_int(array[8, byte](rawCount))
|
depositCount = bytes_to_int(array[8, byte](rawCount))
|
||||||
depositsJson = await p.ns.getJsonLogs(DepositEvent, blockHash = some(blockHash))
|
depositsJson = await p.ns.getJsonLogs(DepositEvent, fromBlock = some(blockId), toBlock = some(blockId))
|
||||||
deposits = readJsonDeposits(depositsJson)
|
deposits = readJsonDeposits(depositsJson)
|
||||||
|
|
||||||
return Eth1Block(
|
return Eth1Block(
|
||||||
@ -506,15 +515,15 @@ method onDepositEvent*(p: Web3DataProviderRef,
|
|||||||
await p.subscription.unsubscribe()
|
await p.subscription.unsubscribe()
|
||||||
|
|
||||||
p.subscription = await p.ns.subscribe(
|
p.subscription = await p.ns.subscribe(
|
||||||
DepositEvent, %*{"fromBlock": startBlock}, handler)
|
DepositEvent, %*{"fromBlock": &"0x{startBlock:X}"}, handler)
|
||||||
|
|
||||||
proc getBlockNumber(p: DataProviderRef, hash: BlockHash): Future[Quantity] {.async.} =
|
proc getBlockNumber(p: DataProviderRef, hash: BlockHash): Future[Eth1BlockNumber] {.async.} =
|
||||||
debug "Querying block number", hash = $hash
|
debug "Querying block number", hash = $hash
|
||||||
|
|
||||||
try:
|
try:
|
||||||
let blk = awaitWithTimeout(p.getBlockByHash(hash), web3Timeouts):
|
let blk = awaitWithTimeout(p.getBlockByHash(hash), web3Timeouts):
|
||||||
return Quantity(0'u64)
|
return 0
|
||||||
return blk.number
|
return Eth1BlockNumber(blk.number)
|
||||||
except CatchableError as exc:
|
except CatchableError as exc:
|
||||||
notice "Failed to get Eth1 block number from hash",
|
notice "Failed to get Eth1 block number from hash",
|
||||||
hash = $hash, err = exc.msg
|
hash = $hash, err = exc.msg
|
||||||
@ -550,19 +559,12 @@ proc run(m: MainchainMonitor, delayBeforeStart: Duration) {.async.} =
|
|||||||
error "Failed to initialize Eth1 data provider",
|
error "Failed to initialize Eth1 data provider",
|
||||||
provider = m.dataProviderFactory.desc
|
provider = m.dataProviderFactory.desc
|
||||||
raise newException(CatchableError, "Failed to initialize Eth1 data provider")
|
raise newException(CatchableError, "Failed to initialize Eth1 data provider")
|
||||||
defer: await close(dataProvider)
|
|
||||||
|
|
||||||
let processFut = m.processDeposits(dataProvider)
|
|
||||||
try:
|
try:
|
||||||
dataProvider.onDisconnect do:
|
let startBlkNum = if m.startBlock.isSome:
|
||||||
warn "Eth1 data provider disconnected",
|
await dataProvider.getBlockNumber(m.startBlock.get.asBlockHash)
|
||||||
provider = m.dataProviderFactory.desc
|
|
||||||
processFut.cancel()
|
|
||||||
|
|
||||||
let startBlkNum = if m.startBlock != default(BlockHash):
|
|
||||||
await dataProvider.getBlockNumber(m.startBlock)
|
|
||||||
else:
|
else:
|
||||||
Quantity(0'u64)
|
0
|
||||||
|
|
||||||
info "Monitoring eth1 deposits",
|
info "Monitoring eth1 deposits",
|
||||||
fromBlock = startBlkNum.uint64,
|
fromBlock = startBlkNum.uint64,
|
||||||
@ -591,8 +593,10 @@ proc run(m: MainchainMonitor, delayBeforeStart: Duration) {.async.} =
|
|||||||
raise (ref Defect)(err)
|
raise (ref Defect)(err)
|
||||||
else:
|
else:
|
||||||
warn "Received invalid deposit", err = err.msg, j
|
warn "Received invalid deposit", err = err.msg, j
|
||||||
|
|
||||||
|
await m.processDeposits(dataProvider, startBlkNum)
|
||||||
finally:
|
finally:
|
||||||
await processFut
|
await close(dataProvider)
|
||||||
|
|
||||||
proc start(m: MainchainMonitor, delayBeforeStart: Duration) =
|
proc start(m: MainchainMonitor, delayBeforeStart: Duration) =
|
||||||
if m.runFut.isNil:
|
if m.runFut.isNil:
|
||||||
|
@ -6,6 +6,7 @@ const
|
|||||||
bootstrapTxtFileName = "bootstrap_nodes.txt"
|
bootstrapTxtFileName = "bootstrap_nodes.txt"
|
||||||
bootstrapYamlFileName = "boot_enr.yaml"
|
bootstrapYamlFileName = "boot_enr.yaml"
|
||||||
depositContractFileName = "deposit_contract.txt"
|
depositContractFileName = "deposit_contract.txt"
|
||||||
|
depositContractBlockFileName = "deposit_contract_block.txt"
|
||||||
genesisFile = "genesis.ssz"
|
genesisFile = "genesis.ssz"
|
||||||
configFile = "config.yaml"
|
configFile = "config.yaml"
|
||||||
testnetsRepo = "eth2-testnets"
|
testnetsRepo = "eth2-testnets"
|
||||||
@ -26,6 +27,10 @@ proc validateTestnetName(parts: openarray[string]): auto =
|
|||||||
cli do (skipGoerliKey {.
|
cli do (skipGoerliKey {.
|
||||||
desc: "Don't prompt for an Eth1 Goerli key to become a validator" .}: bool,
|
desc: "Don't prompt for an Eth1 Goerli key to become a validator" .}: bool,
|
||||||
|
|
||||||
|
specVersion {.
|
||||||
|
desc: "Spec version"
|
||||||
|
name: "spec" .}: string = "v0.11.3",
|
||||||
|
|
||||||
constPreset {.
|
constPreset {.
|
||||||
desc: "The Ethereum 2.0 const preset of the network (optional)"
|
desc: "The Ethereum 2.0 const preset of the network (optional)"
|
||||||
name: "const-preset" .} = "",
|
name: "const-preset" .} = "",
|
||||||
@ -60,19 +65,18 @@ cli do (skipGoerliKey {.
|
|||||||
var
|
var
|
||||||
depositContractOpt = ""
|
depositContractOpt = ""
|
||||||
bootstrapFileOpt = ""
|
bootstrapFileOpt = ""
|
||||||
|
genesisFileOpt = ""
|
||||||
|
|
||||||
|
let
|
||||||
|
testnetDir = allTestnetsDir / team / testnet
|
||||||
|
genesisFilePath = testnetDir / genesisFile
|
||||||
|
|
||||||
let testnetDir = allTestnetsDir / team / testnet
|
|
||||||
if not system.dirExists(testnetDir):
|
if not system.dirExists(testnetDir):
|
||||||
echo &"No metadata files exists for the '{testnetName}' testnet"
|
echo &"No metadata files exists for the '{testnetName}' testnet"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
proc checkRequiredFile(fileName: string) =
|
if system.fileExists(genesisFilePath):
|
||||||
let filePath = testnetDir / fileName
|
genesisFileOpt = &"--state-snapshot=\"{genesisFilePath}\""
|
||||||
if not system.fileExists(filePath):
|
|
||||||
echo &"The required file {fileName} is not present in '{testnetDir}'."
|
|
||||||
quit 1
|
|
||||||
|
|
||||||
checkRequiredFile genesisFile
|
|
||||||
|
|
||||||
let bootstrapTxtFile = testnetDir / bootstrapTxtFileName
|
let bootstrapTxtFile = testnetDir / bootstrapTxtFileName
|
||||||
if system.fileExists(bootstrapTxtFile):
|
if system.fileExists(bootstrapTxtFile):
|
||||||
@ -98,7 +102,7 @@ cli do (skipGoerliKey {.
|
|||||||
secretsDir = dataDir / "secrets"
|
secretsDir = dataDir / "secrets"
|
||||||
beaconNodeBinary = buildDir / "beacon_node_" & dataDirName
|
beaconNodeBinary = buildDir / "beacon_node_" & dataDirName
|
||||||
var
|
var
|
||||||
nimFlags = "-d:chronicles_log_level=TRACE " & getEnv("NIM_PARAMS")
|
nimFlags = &"-d:chronicles_log_level=TRACE -d:ETH2_SPEC={specVersion} " & getEnv("NIM_PARAMS")
|
||||||
|
|
||||||
# write the logs to a file
|
# write the logs to a file
|
||||||
nimFlags.add """ -d:"chronicles_sinks=textlines,json[file(nbc""" & staticExec("date +\"%Y%m%d%H%M%S\"") & """.log)]" """
|
nimFlags.add """ -d:"chronicles_sinks=textlines,json[file(nbc""" & staticExec("date +\"%Y%m%d%H%M%S\"") & """.log)]" """
|
||||||
@ -107,6 +111,10 @@ cli do (skipGoerliKey {.
|
|||||||
if system.fileExists(depositContractFile):
|
if system.fileExists(depositContractFile):
|
||||||
depositContractOpt = "--deposit-contract=" & readFile(depositContractFile).strip
|
depositContractOpt = "--deposit-contract=" & readFile(depositContractFile).strip
|
||||||
|
|
||||||
|
let depositContractBlockFile = testnetDir / depositContractBlockFileName
|
||||||
|
if system.fileExists(depositContractBlockFile):
|
||||||
|
depositContractOpt.add " --deposit-contract-block=" & readFile(depositContractBlockFile).strip
|
||||||
|
|
||||||
if system.dirExists(dataDir):
|
if system.dirExists(dataDir):
|
||||||
block resetDataDir:
|
block resetDataDir:
|
||||||
# We reset the testnet data dir if the existing data dir is
|
# We reset the testnet data dir if the existing data dir is
|
||||||
@ -177,5 +185,5 @@ cli do (skipGoerliKey {.
|
|||||||
{bootstrapFileOpt}
|
{bootstrapFileOpt}
|
||||||
{logLevelOpt}
|
{logLevelOpt}
|
||||||
{depositContractOpt}
|
{depositContractOpt}
|
||||||
--state-snapshot="{testnetDir/genesisFile}" """, "\n", " ")
|
{genesisFileOpt} """, "\n", " ")
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ for NUM_NODE in $(seq 0 $((NUM_NODES - 1))); do
|
|||||||
BOOTSTRAP_ARG="--bootstrap-file=${NETWORK_DIR}/bootstrap_nodes.txt"
|
BOOTSTRAP_ARG="--bootstrap-file=${NETWORK_DIR}/bootstrap_nodes.txt"
|
||||||
# Wait for the master node to write out its address file
|
# Wait for the master node to write out its address file
|
||||||
START_TIMESTAMP=$(date +%s)
|
START_TIMESTAMP=$(date +%s)
|
||||||
while [ ! -f "${DATA_DIR}/node0/beacon_node.address" ]; do
|
while [ ! -f "${DATA_DIR}/node0/beacon_node.enr" ]; do
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
NOW_TIMESTAMP=$(date +%s)
|
NOW_TIMESTAMP=$(date +%s)
|
||||||
if [[ "$(( NOW_TIMESTAMP - START_TIMESTAMP - GENESIS_OFFSET ))" -ge "$BOOTSTRAP_TIMEOUT" ]]; then
|
if [[ "$(( NOW_TIMESTAMP - START_TIMESTAMP - GENESIS_OFFSET ))" -ge "$BOOTSTRAP_TIMEOUT" ]]; then
|
||||||
|
@ -20,13 +20,13 @@ BOOTSTRAP_ARG=""
|
|||||||
|
|
||||||
if [[ ! -z "$1" ]]; then
|
if [[ ! -z "$1" ]]; then
|
||||||
BOOTSTRAP_NODE_ID=$1
|
BOOTSTRAP_NODE_ID=$1
|
||||||
BOOTSTRAP_ADDRESS_FILE="${SIMULATION_DIR}/node-${BOOTSTRAP_NODE_ID}/beacon_node.address"
|
|
||||||
shift
|
shift
|
||||||
else
|
else
|
||||||
BOOTSTRAP_NODE_ID=$MASTER_NODE
|
BOOTSTRAP_NODE_ID=$MASTER_NODE
|
||||||
BOOTSTRAP_ADDRESS_FILE=$NETWORK_BOOTSTRAP_FILE
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
BOOTSTRAP_ADDRESS_FILE="${SIMULATION_DIR}/node-${BOOTSTRAP_NODE_ID}/beacon_node.enr"
|
||||||
|
|
||||||
if [[ "$NODE_ID" != "$MASTER_NODE" ]]; then
|
if [[ "$NODE_ID" != "$MASTER_NODE" ]]; then
|
||||||
BOOTSTRAP_ARG="--bootstrap-file=$BOOTSTRAP_ADDRESS_FILE"
|
BOOTSTRAP_ARG="--bootstrap-file=$BOOTSTRAP_ADDRESS_FILE"
|
||||||
fi
|
fi
|
||||||
@ -88,7 +88,6 @@ fi
|
|||||||
|
|
||||||
cd "$NODE_DATA_DIR"
|
cd "$NODE_DATA_DIR"
|
||||||
|
|
||||||
# if you want tracing messages, add "--log-level=TRACE" below
|
|
||||||
$BEACON_NODE_BIN \
|
$BEACON_NODE_BIN \
|
||||||
--log-level=${LOG_LEVEL:-DEBUG} \
|
--log-level=${LOG_LEVEL:-DEBUG} \
|
||||||
$BOOTSTRAP_ARG \
|
$BOOTSTRAP_ARG \
|
||||||
|
@ -35,7 +35,7 @@ fi
|
|||||||
|
|
||||||
USE_CTAIL="${USE_CTAIL:-yes}"
|
USE_CTAIL="${USE_CTAIL:-yes}"
|
||||||
if [[ "$USE_CTAIL" == "yes" ]]; then
|
if [[ "$USE_CTAIL" == "yes" ]]; then
|
||||||
type "$CTAIL_CMD" &>/dev/null || { echo $CTAIL_CMD is missing; USE_CTAIL="no"; }
|
type "$CTAIL_CMD" &>/dev/null || { USE_CTAIL="no"; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Read in variables
|
# Read in variables
|
||||||
@ -53,7 +53,7 @@ CUSTOM_NIMFLAGS="${NIMFLAGS} -d:useSysAsserts -d:chronicles_sinks:textlines,json
|
|||||||
|
|
||||||
# Run with "SLOTS_PER_EPOCH=8 ./start.sh" to change these
|
# Run with "SLOTS_PER_EPOCH=8 ./start.sh" to change these
|
||||||
DEFS=""
|
DEFS=""
|
||||||
DEFS+="-d:MIN_GENESIS_ACTIVE_VALIDATOR_COUNT=${NUM_VALIDATORS} "
|
DEFS+="-d:MIN_GENESIS_ACTIVE_VALIDATOR_COUNT=${NUM_VALIDATORS} -d:MIN_GENESIS_TIME=0 "
|
||||||
DEFS+="-d:MAX_COMMITTEES_PER_SLOT=${MAX_COMMITTEES_PER_SLOT:-1} " # Spec default: 64
|
DEFS+="-d:MAX_COMMITTEES_PER_SLOT=${MAX_COMMITTEES_PER_SLOT:-1} " # Spec default: 64
|
||||||
DEFS+="-d:SLOTS_PER_EPOCH=${SLOTS_PER_EPOCH:-6} " # Spec default: 32
|
DEFS+="-d:SLOTS_PER_EPOCH=${SLOTS_PER_EPOCH:-6} " # Spec default: 32
|
||||||
DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-6} " # Spec default: 12
|
DEFS+="-d:SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-6} " # Spec default: 12
|
||||||
@ -75,7 +75,7 @@ COMMANDS=()
|
|||||||
|
|
||||||
if [[ "$USE_GANACHE" == "yes" ]]; then
|
if [[ "$USE_GANACHE" == "yes" ]]; then
|
||||||
if [[ "$USE_TMUX" == "yes" ]]; then
|
if [[ "$USE_TMUX" == "yes" ]]; then
|
||||||
$TMUX_CMD new-window -d -t $TMUX_SESSION_NAME -n "$GANACHE_CMD" "$GANACHE_CMD --blockTime 5 --gasLimit 100000000 -e 100000"
|
$TMUX_CMD new-window -d -t $TMUX_SESSION_NAME -n "$GANACHE_CMD" "$GANACHE_CMD --blockTime 5 --gasLimit 100000000 -e 100000 --verbose"
|
||||||
else
|
else
|
||||||
echo NOTICE: $GANACHE_CMD will be started automatically only with USE_TMUX=1
|
echo NOTICE: $GANACHE_CMD will be started automatically only with USE_TMUX=1
|
||||||
USE_GANACHE="no"
|
USE_GANACHE="no"
|
||||||
|
@ -35,7 +35,7 @@ DEPOSIT_CONTRACT_FILE="${SIMULATION_DIR}/deposit_contract.txt"
|
|||||||
BEACON_NODE_BIN="${GIT_ROOT}/build/beacon_node"
|
BEACON_NODE_BIN="${GIT_ROOT}/build/beacon_node"
|
||||||
VALIDATOR_CLIENT_BIN="${GIT_ROOT}/build/validator_client"
|
VALIDATOR_CLIENT_BIN="${GIT_ROOT}/build/validator_client"
|
||||||
DEPLOY_DEPOSIT_CONTRACT_BIN="${GIT_ROOT}/build/deposit_contract"
|
DEPLOY_DEPOSIT_CONTRACT_BIN="${GIT_ROOT}/build/deposit_contract"
|
||||||
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-${MASTER_NODE}/beacon_node.address"
|
MASTER_NODE_ADDRESS_FILE="${SIMULATION_DIR}/node-${MASTER_NODE}/beacon_node.enr"
|
||||||
|
|
||||||
WEB3_ARG="--web3-url=ws://localhost:8545"
|
WEB3_ARG="--web3-url=ws://localhost:8545"
|
||||||
|
|
||||||
|
2
vendor/nim-json-rpc
vendored
2
vendor/nim-json-rpc
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 8c1a8ef8d9fd1705d4e8640b4c30df2caee76881
|
Subproject commit 244254632b15c745b6e15537aafd401f360d9928
|
2
vendor/nim-web3
vendored
2
vendor/nim-web3
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f1d3e94dda3435b3dadfbc966fa584f5ab64ff9d
|
Subproject commit 05f2a17ba444433d615c5b3d0e1a1de0b0beae65
|
Loading…
x
Reference in New Issue
Block a user