Smooth out the differences between Ganache and Infura; Working local sim and Altona target

This commit is contained in:
Zahary Karadjov 2020-06-19 20:42:28 +03:00 committed by zah
parent 14274587cf
commit 7211a99086
12 changed files with 152 additions and 130 deletions

View File

@ -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*

View File

@ -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()

View File

@ -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"))

View File

@ -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)

View File

@ -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:

View File

@ -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", " ")

View File

@ -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

View File

@ -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 \

View File

@ -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"

View File

@ -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

@ -1 +1 @@
Subproject commit 8c1a8ef8d9fd1705d4e8640b4c30df2caee76881 Subproject commit 244254632b15c745b6e15537aafd401f360d9928

2
vendor/nim-web3 vendored

@ -1 +1 @@
Subproject commit f1d3e94dda3435b3dadfbc966fa584f5ab64ff9d Subproject commit 05f2a17ba444433d615c5b3d0e1a1de0b0beae65