Crypto rng (#1284)

* use bearssl rng throughout

* bump

* bump

* move keygen out of crypto
This commit is contained in:
Jacek Sieka 2020-07-07 17:51:02 +02:00 committed by GitHub
parent 6ef2e71468
commit 6fe0a623f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 116 additions and 94 deletions

View File

@ -7,7 +7,7 @@
import
# Standard library
algorithm, os, tables, strutils, times, math, terminal, random,
algorithm, os, tables, strutils, times, math, terminal, bearssl, random,
# Nimble packages
stew/[objects, byteutils], stew/shims/macros,
@ -129,9 +129,11 @@ func enrForkIdFromState(state: BeaconState): ENRForkID =
next_fork_version: forkVer,
next_fork_epoch: FAR_FUTURE_EPOCH)
proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async.} =
proc init*(
T: type BeaconNode, rng: ref BrHmacDrbgContext,
conf: BeaconNodeConf): Future[BeaconNode] {.async.} =
let
netKeys = getPersistentNetKeys(conf)
netKeys = getPersistentNetKeys(rng[], conf)
nickname = if conf.nodeName == "auto": shortForm(netKeys)
else: conf.nodeName
db = BeaconChainDB.init(kvStore SqStoreRef.init(conf.databaseDir, "nbc").tryGet())
@ -221,7 +223,7 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
enrForkId = enrForkIdFromState(blockPool.headState.data.data)
topicBeaconBlocks = getBeaconBlocksTopic(enrForkId.forkDigest)
topicAggregateAndProofs = getAggregateAndProofsTopic(enrForkId.forkDigest)
network = await createEth2Node(conf, enrForkId)
network = await createEth2Node(rng, conf, enrForkId)
var res = BeaconNode(
nickname: nickname,
@ -1030,12 +1032,14 @@ when hasPrompt:
# var t: Thread[ptr Prompt]
# createThread(t, processPromptCommands, addr p)
proc createWalletInteractively(conf: BeaconNodeConf): OutFile {.raises: [Defect].} =
proc createWalletInteractively(
rng: var BrHmacDrbgContext,
conf: BeaconNodeConf): OutFile {.raises: [Defect].} =
if conf.nonInteractive:
fatal "Wallets can be created only in interactive mode"
quit 1
var mnemonic = generateMnemonic()
var mnemonic = generateMnemonic(rng)
defer: keystore_management.burnMem(mnemonic)
template readLine: string =
@ -1102,7 +1106,8 @@ proc createWalletInteractively(conf: BeaconNodeConf): OutFile {.raises: [Defect]
continue
break
let (uuid, walletContent) = KdfPbkdf2.createWalletContent(mnemonic, name)
let (uuid, walletContent) = KdfPbkdf2.createWalletContent(
rng, mnemonic, name)
try:
var outWalletFile: OutFile
@ -1133,6 +1138,10 @@ programMain:
setupMainProc(config.logLevel)
# Single RNG instance for the application - will be seeded on construction
# and avoid using system resources (such as urandom) after that
let rng = keys.newRng()
case config.cmd
of createTestnet:
var
@ -1188,7 +1197,7 @@ programMain:
let bootstrapFile = config.outputBootstrapFile.string
if bootstrapFile.len > 0:
let
networkKeys = getPersistentNetKeys(config)
networkKeys = getPersistentNetKeys(rng[], config)
metadata = getPersistentNetMetadata(config)
bootstrapEnr = enr.Record.init(
1, # sequence number
@ -1212,7 +1221,7 @@ programMain:
config.createDumpDirs()
var node = waitFor BeaconNode.init(config)
var node = waitFor BeaconNode.init(rng, config)
ctrlCHandling: status = BeaconNodeStatus.Stopping
@ -1238,6 +1247,7 @@ programMain:
createDir(config.outSecretsDir)
let deposits = generateDeposits(
rng[],
config.totalDeposits,
config.outValidatorsDir,
config.outSecretsDir)
@ -1270,7 +1280,7 @@ programMain:
of wallets:
case config.walletsCmd:
of WalletsCmd.create:
let walletFile = createWalletInteractively(config)
let walletFile = createWalletInteractively(rng[], config)
of WalletsCmd.list:
# TODO
discard

View File

@ -1,6 +1,6 @@
import
os, strutils, options, json,
chronos, nimcrypto, confutils, web3, stint,
chronos, confutils, web3, stint,
eth/keys
# Compiled version of /scripts/depositContract.v.py in this repo

View File

@ -2,7 +2,7 @@
import
os, sequtils, strutils,
chronicles, stew/shims/net, stew/results, eth/keys, eth/trie/db,
chronicles, stew/shims/net, stew/results, eth/keys, eth/trie/db, bearssl,
eth/p2p/discoveryv5/[enr, protocol, discovery_db, node],
conf
@ -76,7 +76,7 @@ proc new*(T: type Eth2DiscoveryProtocol,
conf: BeaconNodeConf,
ip: Option[ValidIpAddress], tcpPort, udpPort: Port,
pk: PrivateKey,
enrFields: openarray[(string, seq[byte])]):
enrFields: openarray[(string, seq[byte])], rng: ref BrHmacDrbgContext):
T {.raises: [Exception, Defect].} =
# TODO
# Implement more configuration options:
@ -97,4 +97,5 @@ proc new*(T: type Eth2DiscoveryProtocol,
loadBootstrapFile(persistentBootstrapFile, bootstrapEnrs, ourPubKey)
let enrFieldPairs = mapIt(enrFields, toFieldPair(it[0], it[1]))
newProtocol(pk, db, ip, tcpPort, udpPort, enrFieldPairs, bootstrapEnrs)
newProtocol(
pk, db, ip, tcpPort, udpPort, enrFieldPairs, bootstrapEnrs, rng = rng)

View File

@ -4,7 +4,7 @@ import
options as stdOptions,
# Status libs
stew/[varints, base58, base64, endians2, results, byteutils],
stew/[varints, base58, base64, endians2, results, byteutils], bearssl,
stew/shims/net as stewNet,
stew/shims/[macros, tables],
faststreams/[inputs, outputs, buffers], snappy, snappy/framing,
@ -65,6 +65,7 @@ type
connWorkers: seq[Future[void]]
connTable: Table[PeerID, PeerInfo]
forkId: ENRForkID
rng*: ref BrHmacDrbgContext
EthereumNode = Eth2Node # needed for the definitions in p2p_backends_helpers
@ -796,7 +797,7 @@ proc getPersistentNetMetadata*(conf: BeaconNodeConf): Eth2Metadata =
proc init*(T: type Eth2Node, conf: BeaconNodeConf, enrForkId: ENRForkID,
switch: Switch, ip: Option[ValidIpAddress], tcpPort, udpPort: Port,
privKey: keys.PrivateKey): T =
privKey: keys.PrivateKey, rng: ref BrHmacDrbgContext): T =
new result
result.switch = switch
result.wantedPeers = conf.maxPeers
@ -810,7 +811,8 @@ proc init*(T: type Eth2Node, conf: BeaconNodeConf, enrForkId: ENRForkID,
result.forkId = enrForkId
result.discovery = Eth2DiscoveryProtocol.new(
conf, ip, tcpPort, udpPort, privKey,
{"eth2": SSZ.encode(result.forkId), "attnets": SSZ.encode(result.metadata.attnets)})
{"eth2": SSZ.encode(result.forkId), "attnets": SSZ.encode(result.metadata.attnets)},
rng)
newSeq result.protocolStates, allProtocols.len
for proto in allProtocols:
@ -1064,13 +1066,14 @@ proc initAddress*(T: type MultiAddress, str: string): T =
template tcpEndPoint(address, port): auto =
MultiAddress.init(address, tcpProtocol, port)
proc getPersistentNetKeys*(conf: BeaconNodeConf): KeyPair =
proc getPersistentNetKeys*(
rng: var BrHmacDrbgContext, conf: BeaconNodeConf): KeyPair =
let
privKeyPath = conf.dataDir / networkKeyFilename
privKey =
if not fileExists(privKeyPath):
createDir conf.dataDir.string
let key = PrivateKey.random(Secp256k1).tryGet()
let key = PrivateKey.random(Secp256k1, rng).tryGet()
writeFile(privKeyPath, key.getBytes().tryGet())
key
else:
@ -1086,7 +1089,7 @@ func gossipId(data: openArray[byte]): string =
func msgIdProvider(m: messages.Message): string =
gossipId(m.data)
proc createEth2Node*(conf: BeaconNodeConf, enrForkId: ENRForkID): Future[Eth2Node] {.async, gcsafe.} =
proc createEth2Node*(rng: ref BrHmacDrbgContext, conf: BeaconNodeConf, enrForkId: ENRForkID): Future[Eth2Node] {.async, gcsafe.} =
var
(extIp, extTcpPort, extUdpPort) = setupNat(conf)
hostAddress = tcpEndPoint(conf.libp2pAddress, conf.tcpPort)
@ -1096,7 +1099,7 @@ proc createEth2Node*(conf: BeaconNodeConf, enrForkId: ENRForkID): Future[Eth2Nod
info "Initializing networking", hostAddress,
announcedAddresses
let keys = conf.getPersistentNetKeys
let keys = getPersistentNetKeys(rng[], conf)
# TODO nim-libp2p still doesn't have support for announcing addresses
# that are different from the host address (this is relevant when we
# are running behind a NAT).
@ -1104,14 +1107,15 @@ proc createEth2Node*(conf: BeaconNodeConf, enrForkId: ENRForkID): Future[Eth2Nod
triggerSelf = true, gossip = true,
sign = false, verifySignature = false,
transportFlags = {ServerFlags.ReuseAddr},
msgIdProvider = msgIdProvider)
msgIdProvider = msgIdProvider,
rng = rng)
result = Eth2Node.init(conf, enrForkId, switch,
extIp, extTcpPort, extUdpPort,
keys.seckey.asEthKey)
keys.seckey.asEthKey, rng = rng)
proc getPersistenBootstrapAddr*(conf: BeaconNodeConf,
proc getPersistenBootstrapAddr*(rng: var BrHmacDrbgContext, conf: BeaconNodeConf,
ip: ValidIpAddress, port: Port): EnrResult[enr.Record] =
let pair = getPersistentNetKeys(conf)
let pair = getPersistentNetKeys(rng, conf)
return enr.Record.init(1'u64, # sequence number
pair.seckey.asEthKey,
some(ip), port, port, @[])

View File

@ -593,6 +593,7 @@ proc run(conf: InspectorConf) {.async.} =
var pubsubPeers = newTable[PeerID, PeerInfo]()
var resolveQueue = newAsyncQueue[PeerID](10)
var connectQueue = newAsyncQueue[PeerInfo](10)
let rng = lcrypto.newRng()
let bootnodes = loadBootstrapNodes(conf)
if len(bootnodes) == 0:
@ -667,7 +668,7 @@ proc run(conf: InspectorConf) {.async.} =
bootstrap_fork_digest = forkDigest.get()
forkDigest = argForkDigest
let seckey = lcrypto.PrivateKey.random(PKScheme.Secp256k1).tryGet()
let seckey = lcrypto.PrivateKey.random(PKScheme.Secp256k1, rng[]).tryGet()
# let pubkey = seckey.getKey()
let hostAddress = tryGetMultiAddress(conf.bindAddress)
@ -677,7 +678,7 @@ proc run(conf: InspectorConf) {.async.} =
var switch = newStandardSwitch(some(seckey), hostAddress.get(),
triggerSelf = true, gossip = true,
sign = false, verifySignature = false)
sign = false, verifySignature = false, rng = rng)
if len(conf.topics) > 0:
for item in conf.topics:

View File

@ -1,8 +1,9 @@
import
os, strutils, terminal,
chronicles, chronos, blscurve, nimcrypto, json_serialization, serialization,
web3, stint, eth/keys, confutils,
spec/[datatypes, digest, crypto, keystore], conf, ssz/merkleization, merkle_minimal
os, strutils, terminal, stew/byteutils,
chronicles, chronos, blscurve, json_serialization, serialization,
web3, stint, eth/keys, confutils, bearssl,
spec/[datatypes, digest, crypto, keystore],
conf, ssz/merkleization, merkle_minimal
export
keystore
@ -101,20 +102,19 @@ type
FailedToCreateKeystoreFile
FailedToCreateDepositFile
proc generateDeposits*(totalValidators: int,
proc generateDeposits*(rng: var BrHmacDrbgContext, totalValidators: int,
validatorsDir: string,
secretsDir: string): Result[seq[Deposit], GenerateDepositsError] =
var deposits: seq[Deposit]
info "Generating deposits", totalValidators, validatorsDir, secretsDir
for i in 0 ..< totalValidators:
let password = KeyStorePass getRandomBytesOrPanic(32).toHex
let credentials = generateCredentials(password = password)
let password = KeyStorePass getRandomBytes(rng, 32).toHex
let credentials = generateCredentials(rng, password = password)
let
keyName = intToStr(i, 6) & "_" & $(credentials.signingKey.toPubKey)
validatorDir = validatorsDir / keyName
passphraseFile = secretsDir / keyName
depositFile = validatorDir / depositFileName
keystoreFile = validatorDir / keystoreFileName

View File

@ -28,7 +28,6 @@ import
./digest,
# Status
stew/[endians2, objects, results, byteutils],
nimcrypto/sysrand,
blscurve,
chronicles,
json_serialization,
@ -175,25 +174,6 @@ func blsFastAggregateVerify*(
fastAggregateVerify(unwrapped, message, signature.blsValue)
proc newKeyPair*(): BlsResult[tuple[pub: ValidatorPubKey, priv: ValidatorPrivKey]] =
## Generates a new public-private keypair
## This requires entropy on the system
# The input-keying-material requires 32 bytes at least for security
# The generation is deterministic and the input-keying-material
# must be protected against side-channel attacks
var ikm: array[32, byte]
if randomBytes(ikm) != 32:
return err "bls: no random bytes"
var
sk: SecretKey
pk: PublicKey
if keyGen(ikm, pk, sk):
ok((ValidatorPubKey(kind: Real, blsValue: pk), ValidatorPrivKey(sk)))
else:
err "bls: cannot generate keypair"
proc toGaugeValue*(hash: Eth2Digest): int64 =
# Only the last 8 bytes are taken into consideration in accordance
# to the ETH2 metrics spec:
@ -362,16 +342,3 @@ func init*(T: typedesc[ValidatorSig], data: array[RawSigSize, byte]): T {.noInit
if v.isErr:
raise (ref ValueError)(msg: $v.error)
return v[]
proc getRandomBytes*(n: Natural): seq[byte]
{.raises: [RandomSourceDepleted, Defect].} =
result = newSeq[byte](n)
if randomBytes(result) != result.len:
raise newException(RandomSourceDepleted, "Failed to generate random bytes")
proc getRandomBytesOrPanic*(output: var openArray[byte]) =
doAssert randomBytes(output) == output.len
proc getRandomBytesOrPanic*(n: Natural): seq[byte] =
result = newSeq[byte](n)
getRandomBytesOrPanic(result)

View File

@ -6,10 +6,10 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
json, math, strutils, strformat, typetraits,
json, math, strutils, strformat, typetraits, bearssl,
stew/[results, byteutils, bitseqs, bitops2], stew/shims/macros,
eth/keyfile/uuid, blscurve, json_serialization,
nimcrypto/[sha2, rijndael, pbkdf2, bcmode, hash, sysrand, utils],
nimcrypto/[sha2, rijndael, pbkdf2, bcmode, hash, utils],
./datatypes, ./crypto, ./digest, ./signatures
export
@ -132,6 +132,11 @@ template burnMem*(m: var (SensitiveData|TaintedString)) =
# to make its usage less error-prone.
utils.burnMem(string m)
proc getRandomBytes*(rng: var BrHmacDrbgContext, n: Natural): seq[byte]
{.raises: [Defect].} =
result = newSeq[byte](n)
brHmacDrbgGenerate(rng, result)
macro wordListArray(filename: static string): array[wordListLen, cstring] =
result = newTree(nnkBracket)
var words = slurp(filename).split()
@ -180,14 +185,17 @@ func getSeed*(mnemonic: Mnemonic, password: KeyStorePass): KeySeed =
let salt = "mnemonic-" & password.string
KeySeed sha512.pbkdf2(mnemonic.string, salt, 2048, 64)
proc generateMnemonic*(words: openarray[cstring] = englishWords,
proc generateMnemonic*(
rng: var BrHmacDrbgContext,
words: openarray[cstring] = englishWords,
entropyParam: openarray[byte] = @[]): Mnemonic =
# https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic
doAssert words.len == wordListLen
var entropy: seq[byte]
if entropyParam.len == 0:
entropy = getRandomBytesOrPanic(32)
setLen(entropy, 32)
brHmacDrbgGenerate(rng, entropy)
else:
doAssert entropyParam.len >= 128 and
entropyParam.len <= 256 and
@ -325,6 +333,7 @@ proc decryptKeystore*(data: KeyStoreContent,
ValidatorPrivKey.fromRaw(? secret)
proc createCryptoField(T: type[KdfParams],
rng: var BrHmacDrbgContext,
secret: openarray[byte],
password = KeyStorePass "",
salt: openarray[byte] = @[],
@ -340,13 +349,13 @@ proc createCryptoField(T: type[KdfParams],
doAssert salt.len == saltSize
@salt
else:
getRandomBytesOrPanic(saltSize)
getRandomBytes(rng, saltSize)
let aesIv = if iv.len > 0:
doAssert iv.len == AES.sizeBlock
@iv
else:
getRandomBytesOrPanic(AES.sizeBlock)
getRandomBytes(rng, AES.sizeBlock)
when T is KdfPbkdf2:
decKey = sha256.pbkdf2(password.string, kdfSalt, pbkdf2Params.c,
@ -374,6 +383,7 @@ proc createCryptoField(T: type[KdfParams],
message: byteutils.toHex(cipherMsg)))
proc encryptKeystore*(T: type[KdfParams],
rng: var BrHmacDrbgContext,
privKey: ValidatorPrivkey,
password = KeyStorePass "",
path = KeyPath "",
@ -382,7 +392,7 @@ proc encryptKeystore*(T: type[KdfParams],
pretty = true): KeyStoreContent =
let
secret = privKey.toRaw[^32..^1]
cryptoField = createCryptoField(T, secret, password, salt, iv)
cryptoField = createCryptoField(T, rng, secret, password, salt, iv)
pubkey = privKey.toPubKey()
uuid = uuidGenerate().expect("Random bytes should be available")
keystore = Keystore[T](
@ -396,6 +406,7 @@ proc encryptKeystore*(T: type[KdfParams],
else: $(%keystore)
proc createWallet*(T: type[KdfParams],
rng: var BrHmacDrbgContext,
mnemonic: Mnemonic,
name = WalletName "",
salt: openarray[byte] = @[],
@ -409,7 +420,7 @@ proc createWallet*(T: type[KdfParams],
# we want the wallet restoration procedure to depend only on the
# mnemonic (the user is asked to treat the mnemonic as a password).
seed = getSeed(mnemonic, KeyStorePass"")
cryptoField = %createCryptoField(T, distinctBase seed, password, salt, iv)
cryptoField = %createCryptoField(T,rng, distinctBase seed, password, salt, iv)
Wallet(
uuid: uuid,
@ -422,6 +433,7 @@ proc createWallet*(T: type[KdfParams],
nextAccount: nextAccount.get(0))
proc createWalletContent*(T: type[KdfParams],
rng: var BrHmacDrbgContext,
mnemonic: Mnemonic,
name = WalletName "",
salt: openarray[byte] = @[],
@ -429,10 +441,12 @@ proc createWalletContent*(T: type[KdfParams],
password = KeyStorePass "",
nextAccount = none(Natural),
pretty = true): (UUID, WalletContent) =
let wallet = createWallet(T, mnemonic, name, salt, iv, password, nextAccount, pretty)
let wallet = createWallet(
T, rng, mnemonic, name, salt, iv, password, nextAccount, pretty)
(wallet.uuid, WalletContent Json.encode(wallet, pretty = pretty))
proc restoreCredentials*(mnemonic: Mnemonic,
proc restoreCredentials*(rng: var BrHmacDrbgContext,
mnemonic: Mnemonic,
password = KeyStorePass ""): Credentials =
let
withdrawalKeyPath = makeKeyPath(0, withdrawalKeyKind)
@ -443,14 +457,15 @@ proc restoreCredentials*(mnemonic: Mnemonic,
Credentials(
mnemonic: mnemonic,
keyStore: encryptKeystore(KdfPbkdf2, signingKey, password, signingKeyPath),
keyStore: encryptKeystore(KdfPbkdf2, rng, signingKey, password, signingKeyPath),
signingKey: signingKey,
withdrawalKey: withdrawalKey)
proc generateCredentials*(entropy: openarray[byte] = @[],
proc generateCredentials*(rng: var BrHmacDrbgContext,
entropy: openarray[byte] = @[],
password = KeyStorePass ""): Credentials =
let mnemonic = generateMnemonic(englishWords, entropy)
restoreCredentials(mnemonic, password)
let mnemonic = generateMnemonic(rng, englishWords, entropy)
restoreCredentials(rng, mnemonic, password)
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/deposit-contract.md#withdrawal-credentials
proc makeWithdrawalCredentials*(k: ValidatorPubKey): Eth2Digest =

View File

@ -9,14 +9,35 @@
# ---------------------------------------------------------------
import
bearssl, eth/keys,
# Specs
blscurve/bls_signature_scheme,
../../beacon_chain/spec/[datatypes, crypto]
proc newKeyPair(rng: var BrHmacDrbgContext): BlsResult[tuple[pub: ValidatorPubKey, priv: ValidatorPrivKey]] =
## Generates a new public-private keypair
## This requires entropy on the system
# The input-keying-material requires 32 bytes at least for security
# The generation is deterministic and the input-keying-material
# must be protected against side-channel attacks
var ikm: array[32, byte]
brHmacDrbgGenerate(rng, ikm)
var
sk: SecretKey
pk: bls_signature_scheme.PublicKey
if keyGen(ikm, pk, sk):
ok((ValidatorPubKey(kind: Real, blsValue: pk), ValidatorPrivKey(sk)))
else:
err "bls: cannot generate keypair"
# this is being indexed inside "mock_deposits.nim" by a value up to `validatorCount`
# which is `num_validators` which is `MIN_GENESIS_ACTIVE_VALIDATOR_COUNT`
proc genMockPrivKeys(privkeys: var array[MIN_GENESIS_ACTIVE_VALIDATOR_COUNT, ValidatorPrivKey]) =
let rng = newRng()
for i in 0 ..< privkeys.len:
let pair = newKeyPair()[]
let pair = newKeyPair(rng[])[]
privkeys[i] = pair.priv
func genMockPubKeys(

View File

@ -9,7 +9,7 @@
import
unittest, ./testutil, json,
stew/byteutils, blscurve,
stew/byteutils, blscurve, eth/keys,
../beacon_chain/spec/[crypto, keystore]
from strutils import replace
@ -86,6 +86,9 @@ const
salt = hexToSeqByte("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
iv = hexToSeqByte("264daa3f303d7259501c93d997d84fe6")
let
rng = newRng()
suiteReport "Keystore":
setup:
let secret = ValidatorPrivKey.fromRaw(secretBytes).get
@ -97,7 +100,7 @@ suiteReport "Keystore":
check secret == decrypt.get()
timedTest "Pbkdf2 encryption":
let encrypt = encryptKeystore(KdfPbkdf2, secret,
let encrypt = encryptKeystore(KdfPbkdf2, rng[], secret,
KeyStorePass password,
salt=salt, iv=iv,
path = validateKeyPath "m/12381/60/0/0")
@ -111,10 +114,10 @@ suiteReport "Keystore":
timedTest "Pbkdf2 errors":
expect Defect:
echo encryptKeystore(KdfPbkdf2, secret, salt = [byte 1]).string
echo encryptKeystore(KdfPbkdf2, rng[], secret, salt = [byte 1]).string
expect Defect:
echo encryptKeystore(KdfPbkdf2, secret, iv = [byte 1]).string
echo encryptKeystore(KdfPbkdf2, rng[], secret, iv = [byte 1]).string
check decryptKeystore(KeyStoreContent pbkdf2Vector,
KeyStorePass "wrong pass").isErr

View File

@ -9,7 +9,7 @@
import
unittest, options, json_serialization,
nimcrypto, serialization/testing/generic_suite,
serialization/testing/generic_suite,
./testutil,
../beacon_chain/spec/[datatypes, digest],
../beacon_chain/ssz, ../beacon_chain/ssz/[navigator, dynamic_navigator]

2
vendor/nim-bearssl vendored

@ -1 +1 @@
Subproject commit 68c6d27304245c948526487b37e10951acf7dbc8
Subproject commit 33b2303fc3b64359970b77bb09274c3e012ff37f

2
vendor/nim-eth vendored

@ -1 +1 @@
Subproject commit bfda38ba82d73ed3f7bf41a41a51d69ba1c2cbe5
Subproject commit 484fbcab1b25072b4c45f496a88d361fc9479be4

2
vendor/nim-libp2p vendored

@ -1 +1 @@
Subproject commit b49c619ca851ec6e832243b633efee4c57af5e40
Subproject commit d522537b19a532bc4af94fcd146f779c1f23bad0

@ -1 +1 @@
Subproject commit be989635994377e0e421e4a039230098ba5ccd28
Subproject commit bf6cc94a3cbab16cf7ffadad11b50c52f161d0a8

2
vendor/nim-web3 vendored

@ -1 +1 @@
Subproject commit a75519fe1264ea861fb65eb2ffec1d6566ebd033
Subproject commit dd132ba024fd8784aab7b5c306c4ec61c86e8613