mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-02 09:46:26 +00:00
WIP Goerli testnet
This commit is contained in:
parent
43b70c0330
commit
9d3889cbab
2
Makefile
2
Makefile
@ -13,7 +13,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 bench_bls_sig_agggregation state_sim ncli_hash_tree_root ncli_pretty ncli_signing_root ncli_transition process_dashboard
|
TOOLS := beacon_node bench_bls_sig_agggregation state_sim ncli_hash_tree_root ncli_pretty ncli_signing_root ncli_transition process_dashboard deposit_contract
|
||||||
TOOLS_DIRS := beacon_chain benchmarks research ncli tests/simulation
|
TOOLS_DIRS := beacon_chain benchmarks research ncli tests/simulation
|
||||||
TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
|
TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import
|
|||||||
os, net, sequtils, tables, osproc, random, strutils, times, strformat,
|
os, net, sequtils, tables, osproc, random, strutils, times, strformat,
|
||||||
|
|
||||||
# Nimble packages
|
# Nimble packages
|
||||||
stew/[objects, bitseqs],
|
stew/[objects, bitseqs, byteutils],
|
||||||
chronos, chronicles, confutils, metrics,
|
chronos, chronicles, confutils, metrics,
|
||||||
json_serialization/std/[options, sets], serialization/errors,
|
json_serialization/std/[options, sets], serialization/errors,
|
||||||
eth/trie/db, eth/trie/backends/rocksdb_backend, eth/async_utils,
|
eth/trie/db, eth/trie/backends/rocksdb_backend, eth/async_utils,
|
||||||
@ -19,7 +19,7 @@ const
|
|||||||
dataDirValidators = "validators"
|
dataDirValidators = "validators"
|
||||||
networkMetadataFile = "network.json"
|
networkMetadataFile = "network.json"
|
||||||
genesisFile = "genesis.json"
|
genesisFile = "genesis.json"
|
||||||
testnetsBaseUrl = "https://serenity-testnets.status.im"
|
testnetsBaseUrl = "https://raw.githubusercontent.com/status-im/nim-eth2-testnet-data/master/www"
|
||||||
hasPrompt = not defined(withoutPrompt)
|
hasPrompt = not defined(withoutPrompt)
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
||||||
@ -109,27 +109,23 @@ proc saveValidatorKey(keyName, key: string, conf: BeaconNodeConf) =
|
|||||||
writeFile(outputFile, key)
|
writeFile(outputFile, key)
|
||||||
info "Imported validator key", file = outputFile
|
info "Imported validator key", file = outputFile
|
||||||
|
|
||||||
proc initGenesis(node: BeaconNode) {.async.} =
|
func stateSnapshotPath*(conf: BeaconNodeConf): string =
|
||||||
template conf: untyped = node.config
|
if conf.stateSnapshot.isSome:
|
||||||
var tailState: BeaconState
|
conf.stateSnapshot.get.string
|
||||||
if conf.depositWeb3Url.len != 0:
|
|
||||||
info "Waiting for genesis state from eth1"
|
|
||||||
tailState = await node.mainchainMonitor.getGenesis()
|
|
||||||
else:
|
else:
|
||||||
var snapshotFile = conf.dataDir / genesisFile
|
conf.dataDir / genesisFile
|
||||||
|
|
||||||
|
proc getStateFromSnapshot(node: BeaconNode, state: var BeaconState): bool =
|
||||||
|
template conf: untyped = node.config
|
||||||
|
let snapshotFile = conf.stateSnapshotPath
|
||||||
|
|
||||||
|
if fileExists(snapshotFile):
|
||||||
|
template loadSnapshot(Format) =
|
||||||
|
info "Importing snapshot file", path = snapshotFile
|
||||||
|
state = loadFile(Format, snapshotFile, BeaconState)
|
||||||
|
|
||||||
|
let ext = splitFile(snapshotFile).ext
|
||||||
try:
|
try:
|
||||||
if conf.stateSnapshot.isSome:
|
|
||||||
snapshotFile = conf.stateSnapshot.get.string
|
|
||||||
|
|
||||||
if not fileExists(snapshotFile):
|
|
||||||
error "Nimbus database not initialized. Please specify the initial state snapshot file."
|
|
||||||
quit 1
|
|
||||||
|
|
||||||
template loadSnapshot(Format) =
|
|
||||||
info "Importing snapshot file", path = snapshotFile
|
|
||||||
tailState = loadFile(Format, snapshotFile, BeaconState)
|
|
||||||
|
|
||||||
let ext = splitFile(snapshotFile).ext
|
|
||||||
if cmpIgnoreCase(ext, ".ssz") == 0:
|
if cmpIgnoreCase(ext, ".ssz") == 0:
|
||||||
loadSnapshot SSZ
|
loadSnapshot SSZ
|
||||||
elif cmpIgnoreCase(ext, ".json") == 0:
|
elif cmpIgnoreCase(ext, ".json") == 0:
|
||||||
@ -137,15 +133,16 @@ proc initGenesis(node: BeaconNode) {.async.} =
|
|||||||
else:
|
else:
|
||||||
error "The --stateSnapshot option expects a json or a ssz file."
|
error "The --stateSnapshot option expects a json or a ssz file."
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
except SerializationError as err:
|
except SerializationError as err:
|
||||||
stderr.write "Failed to import ", snapshotFile, "\n"
|
stderr.write "Failed to import ", snapshotFile, "\n"
|
||||||
stderr.write err.formatMsg(snapshotFile), "\n"
|
stderr.write err.formatMsg(snapshotFile), "\n"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
result = true
|
||||||
|
|
||||||
|
proc commitGenesisState(node: BeaconNode, tailState: BeaconState) =
|
||||||
info "Got genesis state", hash = hash_tree_root(tailState)
|
info "Got genesis state", hash = hash_tree_root(tailState)
|
||||||
node.forkVersion = tailState.fork.current_version
|
node.forkVersion = tailState.fork.current_version
|
||||||
|
|
||||||
try:
|
try:
|
||||||
let tailBlock = get_initial_beacon_block(tailState)
|
let tailBlock = get_initial_beacon_block(tailState)
|
||||||
BlockPool.preInit(node.db, tailState, tailBlock)
|
BlockPool.preInit(node.db, tailState, tailBlock)
|
||||||
@ -219,9 +216,6 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
|||||||
result.bootstrapNodes.add BootstrapAddr.init(string ln)
|
result.bootstrapNodes.add BootstrapAddr.init(string ln)
|
||||||
|
|
||||||
result.attachedValidators = ValidatorPool.init
|
result.attachedValidators = ValidatorPool.init
|
||||||
if conf.depositWeb3Url.len != 0:
|
|
||||||
result.mainchainMonitor = MainchainMonitor.init(conf.depositWeb3Url, conf.depositContractAddress)
|
|
||||||
result.mainchainMonitor.start()
|
|
||||||
|
|
||||||
let trieDB = trieDB newChainDb(string conf.databaseDir)
|
let trieDB = trieDB newChainDb(string conf.databaseDir)
|
||||||
result.db = BeaconChainDB.init(trieDB)
|
result.db = BeaconChainDB.init(trieDB)
|
||||||
@ -231,8 +225,25 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
|||||||
# specified on command line? potentially, this should be the other way
|
# specified on command line? potentially, this should be the other way
|
||||||
# around...
|
# around...
|
||||||
|
|
||||||
|
var eth1MonitorStartBlock: Eth2Digest
|
||||||
if result.db.getHeadBlock().isNone():
|
if result.db.getHeadBlock().isNone():
|
||||||
await result.initGenesis()
|
var state: BeaconState
|
||||||
|
if not result.getStateFromSnapshot(state):
|
||||||
|
if conf.depositWeb3Url.len != 0:
|
||||||
|
result.mainchainMonitor = MainchainMonitor.init(conf.depositWeb3Url, conf.depositContractAddress, eth1MonitorStartBlock)
|
||||||
|
result.mainchainMonitor.start()
|
||||||
|
else:
|
||||||
|
stderr.write "No state snapshot (or web3 URL) provided\n"
|
||||||
|
quit 1
|
||||||
|
|
||||||
|
state = await result.mainchainMonitor.getGenesis()
|
||||||
|
else:
|
||||||
|
eth1MonitorStartBlock = state.eth1Data.block_hash
|
||||||
|
result.commitGenesisState(state)
|
||||||
|
|
||||||
|
if result.mainchainMonitor.isNil and conf.depositWeb3Url.len != 0:
|
||||||
|
result.mainchainMonitor = MainchainMonitor.init(conf.depositWeb3Url, conf.depositContractAddress, eth1MonitorStartBlock)
|
||||||
|
result.mainchainMonitor.start()
|
||||||
|
|
||||||
result.blockPool = BlockPool.init(result.db)
|
result.blockPool = BlockPool.init(result.db)
|
||||||
result.attestationPool = AttestationPool.init(result.blockPool)
|
result.attestationPool = AttestationPool.init(result.blockPool)
|
||||||
@ -1010,10 +1021,15 @@ when isMainModule:
|
|||||||
stderr.write "Please regenerate the deposit files by running makeDeposits again\n"
|
stderr.write "Please regenerate the deposit files by running makeDeposits again\n"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
let eth1Hash = if config.depositWeb3Url.len == 0:
|
||||||
|
eth1BlockHash
|
||||||
|
else:
|
||||||
|
waitFor getLatestEth1BlockHash(config.depositWeb3Url)
|
||||||
|
|
||||||
var
|
var
|
||||||
startTime = uint64(times.toUnix(times.getTime()) + config.genesisOffset)
|
startTime = uint64(times.toUnix(times.getTime()) + config.genesisOffset)
|
||||||
initialState = initialize_beacon_state_from_eth1(
|
initialState = initialize_beacon_state_from_eth1(
|
||||||
eth1BlockHash, startTime, deposits, {skipValidation})
|
eth1Hash, startTime, deposits, {skipValidation})
|
||||||
|
|
||||||
# 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
|
||||||
initialState.genesis_time = startTime
|
initialState.genesis_time = startTime
|
||||||
@ -1044,6 +1060,9 @@ when isMainModule:
|
|||||||
totalValidators: config.totalValidators,
|
totalValidators: config.totalValidators,
|
||||||
lastUserValidator: config.lastUserValidator)
|
lastUserValidator: config.lastUserValidator)
|
||||||
|
|
||||||
|
if config.depositContractAddress.len != 0:
|
||||||
|
testnetMetadata.depositContractAddress = hexToByteArray[20](config.depositContractAddress).some
|
||||||
|
|
||||||
Json.saveFile(config.outputNetworkMetadata.string, testnetMetadata, pretty = true)
|
Json.saveFile(config.outputNetworkMetadata.string, testnetMetadata, pretty = true)
|
||||||
echo "Wrote ", config.outputNetworkMetadata.string
|
echo "Wrote ", config.outputNetworkMetadata.string
|
||||||
|
|
||||||
|
@ -247,6 +247,7 @@ type
|
|||||||
NetworkMetadata* = object
|
NetworkMetadata* = object
|
||||||
networkGeneration*: uint64
|
networkGeneration*: uint64
|
||||||
genesisRoot*: Option[Eth2Digest]
|
genesisRoot*: Option[Eth2Digest]
|
||||||
|
depositContractAddress*: Option[array[20, byte]]
|
||||||
bootstrapNodes*: seq[BootstrapAddr]
|
bootstrapNodes*: seq[BootstrapAddr]
|
||||||
numShards*: uint64
|
numShards*: uint64
|
||||||
slotDuration*: uint64
|
slotDuration*: uint64
|
||||||
|
@ -35,8 +35,10 @@ type
|
|||||||
contract(Deposit):
|
contract(Deposit):
|
||||||
proc drain()
|
proc drain()
|
||||||
|
|
||||||
|
proc getTransactionReceipt(web3: Web3, tx: TxHash): Future[ReceiptObject] {.async.} =
|
||||||
|
result = await web3.provider.eth_getTransactionReceipt(tx)
|
||||||
|
|
||||||
proc deployContract*(web3: Web3, code: string): Future[Address] {.async.} =
|
proc deployContract*(web3: Web3, code: string): Future[Address] {.async.} =
|
||||||
let provider = web3.provider
|
|
||||||
var code = code
|
var code = code
|
||||||
if code[1] notin {'x', 'X'}:
|
if code[1] notin {'x', 'X'}:
|
||||||
code = "0x" & code
|
code = "0x" & code
|
||||||
@ -47,7 +49,7 @@ proc deployContract*(web3: Web3, code: string): Future[Address] {.async.} =
|
|||||||
gasPrice: 1.some)
|
gasPrice: 1.some)
|
||||||
|
|
||||||
let r = await web3.send(tr)
|
let r = await web3.send(tr)
|
||||||
let receipt = await provider.eth_getTransactionReceipt(r)
|
let receipt = await web3.getTransactionReceipt(r)
|
||||||
result = receipt.contractAddress.get
|
result = receipt.contractAddress.get
|
||||||
|
|
||||||
proc sendEth(web3: Web3, to: string, valueEth: int): Future[TxHash] =
|
proc sendEth(web3: Web3, to: string, valueEth: int): Future[TxHash] =
|
||||||
|
@ -23,11 +23,12 @@ type
|
|||||||
QueueElement = (BlockHash, DepositData)
|
QueueElement = (BlockHash, DepositData)
|
||||||
|
|
||||||
|
|
||||||
proc init*(T: type MainchainMonitor, web3Url, depositContractAddress: string): T =
|
proc init*(T: type MainchainMonitor, web3Url, depositContractAddress: string, startBlock: Eth2Digest): T =
|
||||||
result.new()
|
result.new()
|
||||||
result.web3Url = web3Url
|
result.web3Url = web3Url
|
||||||
result.depositContractAddress = Address.fromHex(depositContractAddress)
|
result.depositContractAddress = Address.fromHex(depositContractAddress)
|
||||||
result.depositQueue = newAsyncQueue[QueueElement]()
|
result.depositQueue = newAsyncQueue[QueueElement]()
|
||||||
|
result.eth1Block = BlockHash(startBlock.data)
|
||||||
|
|
||||||
contract(DepositContract):
|
contract(DepositContract):
|
||||||
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96, deposit_data_root: FixedBytes[32])
|
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96, deposit_data_root: FixedBytes[32])
|
||||||
@ -83,7 +84,7 @@ proc run(m: MainchainMonitor) {.async.} =
|
|||||||
m.web3 = await newWeb3(m.web3Url)
|
m.web3 = await newWeb3(m.web3Url)
|
||||||
let ns = m.web3.contractSender(DepositContract, m.depositContractAddress)
|
let ns = m.web3.contractSender(DepositContract, m.depositContractAddress)
|
||||||
|
|
||||||
let s = await ns.subscribe(DepositEvent, %*{"fromBlock": "0x0"}) do(pubkey: Bytes48, withdrawalCredentials: Bytes32, amount: Bytes8, signature: Bytes96, merkleTreeIndex: Bytes8, j: JsonNode):
|
let s = await ns.subscribe(DepositEvent, %*{"fromBlock": m.eth1Block}) do(pubkey: Bytes48, withdrawalCredentials: Bytes32, amount: Bytes8, signature: Bytes96, merkleTreeIndex: Bytes8, j: JsonNode):
|
||||||
|
|
||||||
let blkHash = BlockHash.fromHex(j["blockHash"].getStr())
|
let blkHash = BlockHash.fromHex(j["blockHash"].getStr())
|
||||||
let amount = bytes_to_int(array[8, byte](amount))
|
let amount = bytes_to_int(array[8, byte](amount))
|
||||||
@ -125,3 +126,9 @@ proc getPendingDeposits*(m: MainchainMonitor): seq[Deposit] =
|
|||||||
# # rather a more readable description of the change that can be packed
|
# # rather a more readable description of the change that can be packed
|
||||||
# # in a SpecialRecord by the client of the API.
|
# # in a SpecialRecord by the client of the API.
|
||||||
# discard
|
# discard
|
||||||
|
|
||||||
|
proc getLatestEth1BlockHash*(url: string): Future[Eth2Digest] {.async.} =
|
||||||
|
let web3 = await newWeb3(url)
|
||||||
|
let blk = await web3.provider.eth_getBlockByNumber("latest", false)
|
||||||
|
result.data = array[32, byte](blk.hash)
|
||||||
|
await web3.close()
|
||||||
|
@ -13,6 +13,6 @@ mkdir -p $VALIDATORS_DIR
|
|||||||
FIRST_IDX=$(printf '%07d' $FIRST_VALIDATOR)
|
FIRST_IDX=$(printf '%07d' $FIRST_VALIDATOR)
|
||||||
LAST_IDX=$(printf '%07d' $LAST_VALIDATOR)
|
LAST_IDX=$(printf '%07d' $LAST_VALIDATOR)
|
||||||
|
|
||||||
curl "https://serenity-testnets.status.im/${NETWORK_NAME}/v[$FIRST_IDX-$LAST_IDX].privkey" \
|
curl "https://raw.githubusercontent.com/status-im/nim-eth2-testnet-data/master/www/${NETWORK_NAME}/v[$FIRST_IDX-$LAST_IDX].privkey" \
|
||||||
-o "$VALIDATORS_DIR/v#1.privkey" -s -w '%{url_effective} > %{filename_effective}\n'
|
-o "$VALIDATORS_DIR/v#1.privkey" -s -w '%{url_effective} > %{filename_effective}\n'
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ source "$NETWORK_NAME.env"
|
|||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
if [ -f .env ]; then
|
if [ -f .env ]; then
|
||||||
# allow server overrides for ETH2_TESTNET_DATA_DIR and DATA_DIR
|
# allow server overrides for ETH2_TESTNET_DATA_DIR, DATA_DIR and ETH1_PRIVATE_KEY
|
||||||
source .env
|
source .env
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -41,8 +41,19 @@ ETH2_TESTNET_DATA_DIR_ABS=$(cd "$ETH2_TESTNET_DATA_DIR"; pwd)
|
|||||||
DATA_DIR_ABS=$(mkdir -p "$DATA_DIR"; cd "$DATA_DIR"; pwd)
|
DATA_DIR_ABS=$(mkdir -p "$DATA_DIR"; cd "$DATA_DIR"; pwd)
|
||||||
NETWORK_DIR_ABS="$ETH2_TESTNET_DATA_DIR_ABS/www/$NETWORK_NAME"
|
NETWORK_DIR_ABS="$ETH2_TESTNET_DATA_DIR_ABS/www/$NETWORK_NAME"
|
||||||
|
|
||||||
|
if [ "$WEB3_URL" != "" ]; then
|
||||||
|
WEB3_URL_ARG="--depositWeb3Url=$WEB3_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
DOCKER_BEACON_NODE="docker run -v $NETWORK_DIR_ABS:/network_dir -v $DATA_DIR_ABS:/data_dir statusteam/nimbus_beacon_node:$NETWORK_NAME"
|
DOCKER_BEACON_NODE="docker run -v $NETWORK_DIR_ABS:/network_dir -v $DATA_DIR_ABS:/data_dir statusteam/nimbus_beacon_node:$NETWORK_NAME"
|
||||||
|
|
||||||
|
make deposit_contract
|
||||||
|
|
||||||
|
if [ "$ETH1_PRIVATE_KEY" != "" ]; then
|
||||||
|
DEPOSIT_CONTRACT_ADDRESS=$(./build/deposit_contract deploy $WEB3_URL_ARG --privateKey=$ETH1_PRIVATE_KEY)
|
||||||
|
DEPOSIT_CONTRACT_ADDRESS_ARG="--depositContractAddress=$DEPOSIT_CONTRACT_ADDRESS"
|
||||||
|
fi
|
||||||
|
|
||||||
cd docker
|
cd docker
|
||||||
|
|
||||||
export GIT_REVISION=$(git rev-parse HEAD)
|
export GIT_REVISION=$(git rev-parse HEAD)
|
||||||
@ -68,6 +79,7 @@ $DOCKER_BEACON_NODE \
|
|||||||
--outputNetworkMetadata=/network_dir/network.json \
|
--outputNetworkMetadata=/network_dir/network.json \
|
||||||
--bootstrapAddress=$BOOTSTRAP_IP \
|
--bootstrapAddress=$BOOTSTRAP_IP \
|
||||||
--bootstrapPort=$BOOTSTRAP_PORT \
|
--bootstrapPort=$BOOTSTRAP_PORT \
|
||||||
|
$WEB3_URL_ARG $DEPOSIT_CONTRACT_ADDRESS_ARG \
|
||||||
--genesisOffset=60 # Delay in seconds
|
--genesisOffset=60 # Delay in seconds
|
||||||
|
|
||||||
if [[ $PUBLISH_TESTNET_RESETS != "0" ]]; then
|
if [[ $PUBLISH_TESTNET_RESETS != "0" ]]; then
|
||||||
@ -78,14 +90,6 @@ if [[ $PUBLISH_TESTNET_RESETS != "0" ]]; then
|
|||||||
git push
|
git push
|
||||||
popd
|
popd
|
||||||
|
|
||||||
echo Updating https://serenity-testnets.status.im/${NETWORK_NAME}...
|
|
||||||
ssh $BOOTSTRAP_HOST <<-SSH
|
|
||||||
cd /opt/nim-eth2-testnet-data
|
|
||||||
git reset --hard HEAD
|
|
||||||
git checkout master
|
|
||||||
git pull
|
|
||||||
SSH
|
|
||||||
|
|
||||||
echo Redistributing validator keys to server nodes...
|
echo Redistributing validator keys to server nodes...
|
||||||
# TODO If we try to use direct piping here, bash doesn't execute all of the commands.
|
# TODO If we try to use direct piping here, bash doesn't execute all of the commands.
|
||||||
# The reasons for this are unclear at the moment.
|
# The reasons for this are unclear at the moment.
|
||||||
|
@ -7,4 +7,4 @@ SECONDS_PER_SLOT=6
|
|||||||
VALIDATOR_COUNT=1000
|
VALIDATOR_COUNT=1000
|
||||||
LAST_USER_VALIDATOR=199
|
LAST_USER_VALIDATOR=199
|
||||||
BOOTSTRAP_PORT=9100
|
BOOTSTRAP_PORT=9100
|
||||||
|
WEB3_URL=wss://goerli.infura.io/ws/v3/809a18497dd74102b5f37d25aae3c85a
|
||||||
|
2
vendor/news
vendored
2
vendor/news
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 0c44ff9cd31e0f644f10d9adfbfc8e0c181ea724
|
Subproject commit 8ea2ee260207c57a4b495931508569e181bb7b93
|
2
vendor/nim-bearssl
vendored
2
vendor/nim-bearssl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit f6133ec47de1900cc17db91fc0f929d0dcbaa63f
|
Subproject commit 993372dd78fa935e051e2d1f3c874d068d7171e6
|
2
vendor/nim-libp2p
vendored
2
vendor/nim-libp2p
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 21af0810663901abc832ff7f29e3920a9f22392a
|
Subproject commit 6d8f21b611c715d19ac73901e981bf463267e797
|
2
vendor/nim-metrics
vendored
2
vendor/nim-metrics
vendored
@ -1 +1 @@
|
|||||||
Subproject commit dc9873ebacb789c971d5496737cca0cbebcc7a9f
|
Subproject commit d4492f0d0ae9d2c46cc3dde2d947bc175ae420de
|
Loading…
x
Reference in New Issue
Block a user