mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-09 05:52:45 +00:00
f5e9d3ffe4
Annotate the `research` and `test` files for which no further changes are needed to successfully compile them, to not interfere with periodic tasks such as spec reference bumps.
927 lines
33 KiB
Nim
927 lines
33 KiB
Nim
# beacon_chain
|
|
# Copyright (c) 2021-2024 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.push raises: [].}
|
|
{.used.}
|
|
|
|
import
|
|
std/[os, options, json, typetraits, uri, algorithm],
|
|
unittest2, chronos, chronicles, stint, json_serialization,
|
|
blscurve,
|
|
libp2p/crypto/crypto as lcrypto,
|
|
stew/[io2, byteutils],
|
|
../beacon_chain/filepath,
|
|
../beacon_chain/spec/eth2_merkleization,
|
|
../beacon_chain/spec/datatypes/base,
|
|
../beacon_chain/spec/[crypto, keystore],
|
|
../beacon_chain/validators/keystore_management,
|
|
./testutil
|
|
|
|
const
|
|
simulationDepositsCount = 2
|
|
testDataDir = "./test_keystore_management"
|
|
testValidatorsDir = testDataDir / "validators"
|
|
testSecretsDir = testDataDir / "secrets"
|
|
|
|
proc directoryItemsCount(dir: string): int {.raises: [OSError].} =
|
|
for el in walkDir(dir):
|
|
result += 1
|
|
|
|
proc validatorPubKeysInDir(dir: string): seq[string] {.raises: [OSError].} =
|
|
for kind, file in walkDir(dir):
|
|
if kind == pcDir:
|
|
result.add(splitFile(file).name)
|
|
|
|
proc contentEquals(
|
|
filePath, expectedContent: string): bool {.raises: [IOError].} =
|
|
var file: File
|
|
|
|
discard open(file, filePath)
|
|
defer: close(file)
|
|
|
|
expectedContent == readAll(file)
|
|
|
|
let
|
|
rng = HmacDrbgContext.new()
|
|
mnemonic = generateMnemonic(rng[])
|
|
seed = getSeed(mnemonic, KeystorePass.init "")
|
|
cfg = defaultRuntimeConfig
|
|
validatorDirRes = secureCreatePath(testValidatorsDir)
|
|
|
|
proc namesEqual(a, b: openArray[string]): bool =
|
|
sorted(a) == sorted(b)
|
|
|
|
when not defined(windows):
|
|
proc isEmptyDir(dir: string): bool {.raises: [OSError].} =
|
|
directoryItemsCount(dir) == 0
|
|
|
|
if validatorDirRes.isErr():
|
|
warn "Could not create validators folder",
|
|
path = testValidatorsDir, err = ioErrorMsg(validatorDirRes.error)
|
|
|
|
let secretDirRes = secureCreatePath(testSecretsDir)
|
|
if secretDirRes.isErr():
|
|
warn "Could not create secrets folder",
|
|
path = testSecretsDir, err = ioErrorMsg(secretDirRes.error)
|
|
|
|
let deposits = generateDeposits(
|
|
cfg,
|
|
rng[],
|
|
seed,
|
|
0, simulationDepositsCount,
|
|
testValidatorsDir,
|
|
testSecretsDir)
|
|
|
|
if deposits.isErr:
|
|
fatal "Failed to generate deposits", err = deposits.error
|
|
quit 1
|
|
|
|
let validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
const
|
|
MultiplePassword = string.fromBytes(
|
|
hexToSeqByte("7465737470617373776f7264f09f9491"))
|
|
MultipleSalt = hexToSeqByte(
|
|
"d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
|
|
MultipleIv = hexToSeqByte("264daa3f303d7259501c93d997d84fe6")
|
|
MultipleRemoteUri = HttpHostUri(parseUri("https://127.0.0.1/eth/web3signer"))
|
|
|
|
MultiplePrivateKeys = [
|
|
"3b89cdf5c62b423dab64dd69476c6c74bdbccc684abc89f3b392ac1f679e06c3",
|
|
"5140621611300ed419f901d8c56baf32d89d876272bbb3ab16e1c9f0884487d4"
|
|
]
|
|
|
|
var
|
|
MultipleKeystoreNames: seq[string]
|
|
MultipleSigningKeys: seq[ValidatorPrivKey]
|
|
MultipleLocalKeystores: seq[Keystore]
|
|
MultipleLocalKeystoreJsons: seq[string]
|
|
MultipleRemoteKeystores: seq[RemoteKeystore]
|
|
MultipleRemoteKeystoreJsons: seq[string]
|
|
|
|
for key in MultiplePrivateKeys:
|
|
let
|
|
nsecret = ValidatorPrivKey.fromRaw(hexToSeqByte(key)).get()
|
|
npubkey = nsecret.toPubKey().toPubKey()
|
|
keystoreName = "0x" & npubkey.toHex()
|
|
|
|
localKeystore = createKeystore(
|
|
kdfPbkdf2, rng[], nsecret,
|
|
KeystorePass.init MultiplePassword,
|
|
salt = MultipleSalt, iv = MultipleIv,
|
|
description = "This is a test keystore.",
|
|
path = validateKeyPath("m/12381/60/0/0").expect("Valid Keypath"))
|
|
localKeystoreJson = Json.encode(localKeystore)
|
|
|
|
remoteKeystore = createRemoteKeystore(npubkey, MultipleRemoteUri)
|
|
remoteKeystoreJson = Json.encode(remoteKeystore)
|
|
|
|
MultipleSigningKeys.add(nsecret)
|
|
MultipleKeystoreNames.add(keystoreName)
|
|
MultipleLocalKeystores.add(localKeystore)
|
|
MultipleLocalKeystoreJsons.add(localKeystoreJson)
|
|
MultipleRemoteKeystores.add(remoteKeystore)
|
|
MultipleRemoteKeystoreJsons.add(remoteKeystoreJson)
|
|
|
|
suite "removeValidatorFiles()":
|
|
test "Remove validator files":
|
|
let
|
|
validatorsCountBefore = directoryItemsCount(testValidatorsDir)
|
|
secretsCountBefore = directoryItemsCount(testSecretsDir)
|
|
firstValidator = validatorPubKeys[0]
|
|
removeValidatorFilesRes = removeValidatorFiles(
|
|
testValidatorsDir, testSecretsDir, firstValidator, KeystoreKind.Local)
|
|
validatorsCountAfter = directoryItemsCount(testValidatorsDir)
|
|
secretsCountAfter = directoryItemsCount(testSecretsDir)
|
|
|
|
check:
|
|
removeValidatorFilesRes.isOk
|
|
removeValidatorFilesRes.value == RemoveValidatorStatus.deleted
|
|
validatorsCountBefore - 1 == validatorsCountAfter
|
|
not fileExists(testValidatorsDir / firstValidator / KeystoreFileName)
|
|
not fileExists(testValidatorsDir / firstValidator)
|
|
secretsCountBefore - 1 == secretsCountAfter
|
|
not fileExists(testSecretsDir / firstValidator)
|
|
|
|
test "Remove nonexistent validator":
|
|
let
|
|
nonexistentValidator =
|
|
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
|
res = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
nonexistentValidator, KeystoreKind.Local)
|
|
|
|
check(res.isOk and res.value == RemoveValidatorStatus.notFound)
|
|
|
|
test "Remove validator files twice":
|
|
let
|
|
secondValidator = validatorPubKeys[1]
|
|
res1 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
secondValidator, KeystoreKind.Local)
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
secondValidator, KeystoreKind.Local)
|
|
|
|
check:
|
|
not fileExists(testValidatorsDir / secondValidator)
|
|
not fileExists(testSecretsDir / secondValidator)
|
|
res1.isOk and res1.value() == RemoveValidatorStatus.deleted
|
|
res2.isOk and res2.value() == RemoveValidatorStatus.notFound
|
|
|
|
os.removeDir testValidatorsDir
|
|
os.removeDir testSecretsDir
|
|
|
|
suite "removeValidatorFiles() multiple keystore types":
|
|
setup:
|
|
let
|
|
curKeystoreDir0 {.used.} = testValidatorsDir / MultipleKeystoreNames[0]
|
|
curSecretsFile0 {.used.} = testSecretsDir / MultipleKeystoreNames[0]
|
|
remoteKeystoreFile0 {.used.} = curKeystoreDir0 / RemoteKeystoreFileName
|
|
localKeystoreFile0 {.used.} = curKeystoreDir0 / KeystoreFileName
|
|
curSigningKey0 {.used.} = MultipleSigningKeys[0]
|
|
curCookedKey0 {.used.} = curSigningKey0.toPubKey()
|
|
curPublicKey0 {.used.} = curCookedKey0.toPubKey()
|
|
|
|
curKeystoreDir1 {.used.} = testValidatorsDir / MultipleKeystoreNames[1]
|
|
curSecretsFile1 {.used.} = testSecretsDir / MultipleKeystoreNames[1]
|
|
remoteKeystoreFile1 {.used.} = curKeystoreDir1 / RemoteKeystoreFileName
|
|
localKeystoreFile1 {.used.} = curKeystoreDir1 / KeystoreFileName
|
|
curSigningKey1 {.used.} = MultipleSigningKeys[1]
|
|
curCookedKey1 {.used.} = curSigningKey1.toPubKey()
|
|
curPublicKey1 {.used.} = curCookedKey1.toPubKey()
|
|
|
|
curSigningPath {.used.} =
|
|
validateKeyPath("m/12381/60/0/0").expect("Valid Keypath")
|
|
|
|
teardown:
|
|
os.removeDir testValidatorsDir
|
|
os.removeDir testSecretsDir
|
|
|
|
test "Remove [LOCAL] when [LOCAL] is present":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
validatorsCount1 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount1 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys1 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
MultipleKeystoreNames[0], KeystoreKind.Local)
|
|
|
|
validatorsCount2 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount2 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys2 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
res2.value == RemoveValidatorStatus.deleted
|
|
|
|
validatorsCount1 == 1
|
|
secretsCount1 == 1
|
|
validatorsCount2 == 0
|
|
secretsCount2 == 0
|
|
|
|
not(dirExists(curKeystoreDir0))
|
|
not(fileExists(remoteKeystoreFile0))
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
namesEqual(validatorPubKeys1, [MultipleKeystoreNames[0]])
|
|
namesEqual(validatorPubKeys2, [])
|
|
|
|
test "Remove [LOCAL] when [LOCAL] is missing":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
validatorsCount1 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount1 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys1 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
MultipleKeystoreNames[1], KeystoreKind.Local)
|
|
|
|
validatorsCount2 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount2 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys2 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
res2.value == RemoveValidatorStatus.notFound
|
|
|
|
validatorsCount1 == 1
|
|
secretsCount1 == 1
|
|
validatorsCount2 == 1
|
|
secretsCount2 == 1
|
|
|
|
dirExists(curKeystoreDir0)
|
|
not(fileExists(remoteKeystoreFile0))
|
|
fileExists(localKeystoreFile0)
|
|
fileExists(curSecretsFile0)
|
|
|
|
namesEqual(validatorPubKeys1, [MultipleKeystoreNames[0]])
|
|
namesEqual(validatorPubKeys2, [MultipleKeystoreNames[0]])
|
|
|
|
test "Remove [REMOTE] when [REMOTE] is present":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
|
|
validatorsCount1 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount1 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys1 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
MultipleKeystoreNames[0], KeystoreKind.Remote)
|
|
|
|
validatorsCount2 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount2 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys2 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
res2.value == RemoveValidatorStatus.deleted
|
|
|
|
validatorsCount1 == 1
|
|
secretsCount1 == 0
|
|
validatorsCount2 == 0
|
|
secretsCount2 == 0
|
|
|
|
not(dirExists(curKeystoreDir0))
|
|
not(fileExists(remoteKeystoreFile0))
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
namesEqual(validatorPubKeys1, [MultipleKeystoreNames[0]])
|
|
namesEqual(validatorPubKeys2, [])
|
|
|
|
test "Remove [REMOTE] when [REMOTE] is missing":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
|
|
validatorsCount1 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount1 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys1 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
MultipleKeystoreNames[1], KeystoreKind.Remote)
|
|
|
|
validatorsCount2 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount2 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys2 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
res2.value == RemoveValidatorStatus.notFound
|
|
|
|
validatorsCount1 == 1
|
|
secretsCount1 == 0
|
|
validatorsCount2 == 1
|
|
secretsCount2 == 0
|
|
|
|
dirExists(curKeystoreDir0)
|
|
fileExists(remoteKeystoreFile0)
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
namesEqual(validatorPubKeys1, [MultipleKeystoreNames[0]])
|
|
namesEqual(validatorPubKeys2, [MultipleKeystoreNames[0]])
|
|
|
|
test "Remove [LOCAL] when [REMOTE] is present":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
|
|
validatorsCount1 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount1 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys1 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
MultipleKeystoreNames[0], KeystoreKind.Local)
|
|
|
|
validatorsCount2 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount2 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys2 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
res2.value == RemoveValidatorStatus.notFound
|
|
|
|
validatorsCount1 == 1
|
|
secretsCount1 == 0
|
|
validatorsCount2 == 1
|
|
secretsCount2 == 0
|
|
|
|
dirExists(curKeystoreDir0)
|
|
fileExists(remoteKeystoreFile0)
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
namesEqual(validatorPubKeys1, [MultipleKeystoreNames[0]])
|
|
namesEqual(validatorPubKeys2, [MultipleKeystoreNames[0]])
|
|
|
|
test "Remove [REMOTE] when [LOCAL] is present":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
validatorsCount1 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount1 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys1 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
res2 = removeValidatorFiles(testValidatorsDir, testSecretsDir,
|
|
MultipleKeystoreNames[0], KeystoreKind.Remote)
|
|
|
|
validatorsCount2 = directoryItemsCount(testValidatorsDir)
|
|
secretsCount2 = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys2 = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
res2.value == RemoveValidatorStatus.notFound
|
|
|
|
validatorsCount1 == 1
|
|
secretsCount1 == 1
|
|
validatorsCount2 == 1
|
|
secretsCount2 == 1
|
|
|
|
dirExists(curKeystoreDir0)
|
|
not(fileExists(remoteKeystoreFile0))
|
|
fileExists(localKeystoreFile0)
|
|
fileExists(curSecretsFile0)
|
|
|
|
namesEqual(validatorPubKeys1, [MultipleKeystoreNames[0]])
|
|
namesEqual(validatorPubKeys2, [MultipleKeystoreNames[0]])
|
|
|
|
os.removeDir testValidatorsDir
|
|
os.removeDir testSecretsDir
|
|
|
|
suite "createValidatorFiles()":
|
|
setup:
|
|
const
|
|
password = string.fromBytes hexToSeqByte("7465737470617373776f7264f09f9491")
|
|
secretBytes = hexToSeqByte "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
|
salt = hexToSeqByte "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
|
|
iv = hexToSeqByte "264daa3f303d7259501c93d997d84fe6"
|
|
|
|
let
|
|
secret = ValidatorPrivKey.fromRaw(secretBytes).get
|
|
|
|
keystore = createKeystore(
|
|
kdfPbkdf2, rng[], secret,
|
|
KeystorePass.init password,
|
|
salt=salt, iv=iv,
|
|
description = "This is a test keystore that uses PBKDF2 to secure the secret.",
|
|
path = validateKeyPath("m/12381/60/0/0").expect("Valid Keypath"))
|
|
keystoreJsonContents {.used.} = Json.encode(keystore)
|
|
|
|
hexEncodedPubkey = "0x" & keystore.pubkey.toHex()
|
|
keystoreDir {.used.} = testValidatorsDir / hexEncodedPubkey
|
|
secretFile {.used.} = testSecretsDir / hexEncodedPubkey
|
|
keystoreFile {.used.} = testValidatorsDir / hexEncodedPubkey /
|
|
KeystoreFileName
|
|
|
|
teardown:
|
|
os.removeDir testValidatorsDir
|
|
os.removeDir testSecretsDir
|
|
|
|
test "Add keystore files [LOCAL]":
|
|
let
|
|
res = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res.isOk
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 1
|
|
|
|
dirExists(testValidatorsDir / hexEncodedPubkey)
|
|
fileExists(testSecretsDir / hexEncodedPubkey)
|
|
|
|
secretFile.contentEquals password
|
|
keystoreFile.contentEquals keystoreJsonContents
|
|
|
|
namesEqual(validatorPubKeys, [hexEncodedPubkey])
|
|
|
|
test "Add keystore files twice [LOCAL]":
|
|
let
|
|
res1 = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
|
|
res2 = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk # The second call should just overwrite the results of the first
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 1
|
|
|
|
dirExists(testValidatorsDir / hexEncodedPubkey)
|
|
fileExists(testSecretsDir / hexEncodedPubkey)
|
|
secretFile.contentEquals password
|
|
keystoreFile.contentEquals keystoreJsonContents
|
|
|
|
namesEqual(validatorPubKeys, [hexEncodedPubkey])
|
|
|
|
test "Add keystore files [REMOTE]":
|
|
let
|
|
curKeystoreDir = testValidatorsDir / MultipleKeystoreNames[0]
|
|
curSecretsFile = testSecretsDir / MultipleKeystoreNames[0]
|
|
remoteKeystoreFile = curKeystoreDir / RemoteKeystoreFileName
|
|
localKeystoreFile = curKeystoreDir / KeystoreFileName
|
|
|
|
res = createRemoteValidatorFiles(testValidatorsDir, curKeystoreDir,
|
|
remoteKeystoreFile,
|
|
MultipleRemoteKeystoreJsons[0])
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res.isOk
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 0
|
|
|
|
dirExists(curKeystoreDir)
|
|
fileExists(remoteKeystoreFile)
|
|
not(fileExists(localKeystoreFile))
|
|
not(fileExists(curSecretsFile))
|
|
|
|
remoteKeystoreFile.contentEquals MultipleRemoteKeystoreJsons[0]
|
|
|
|
|
|
namesEqual(validatorPubKeys, [MultipleKeystoreNames[0]])
|
|
|
|
test "Add keystore files twice [REMOTE]":
|
|
let
|
|
curKeystoreDir = testValidatorsDir / MultipleKeystoreNames[0]
|
|
curSecretsFile = testSecretsDir / MultipleKeystoreNames[0]
|
|
remoteKeystoreFile = curKeystoreDir / RemoteKeystoreFileName
|
|
localKeystoreFile = curKeystoreDir / KeystoreFileName
|
|
|
|
res1 = createRemoteValidatorFiles(testValidatorsDir, curKeystoreDir,
|
|
remoteKeystoreFile,
|
|
MultipleRemoteKeystoreJsons[0])
|
|
|
|
res2 = createRemoteValidatorFiles(testValidatorsDir, curKeystoreDir,
|
|
remoteKeystoreFile,
|
|
MultipleRemoteKeystoreJsons[0])
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk # The second call should just overwrite the results of the first
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 0
|
|
|
|
dirExists(curKeystoreDir)
|
|
fileExists(remoteKeystoreFile)
|
|
not(fileExists(localKeystoreFile))
|
|
not(fileExists(curSecretsFile))
|
|
|
|
remoteKeystoreFile.contentEquals MultipleRemoteKeystoreJsons[0]
|
|
|
|
namesEqual(validatorPubKeys, [MultipleKeystoreNames[0]])
|
|
|
|
# TODO The following tests are disabled on Windows because the io2 module
|
|
# doesn't implement the permission/mode parameter at the moment:
|
|
when not defined(windows):
|
|
test "`createLocalValidatorFiles` with `secretsDir` without permissions":
|
|
# Creating `secrets` dir with `UserRead` permissions before
|
|
# calling `createValidatorFiles` which should result in problem
|
|
# with creating a secret file inside the dir:
|
|
discard createPath(testSecretsDir, 0o400)
|
|
|
|
let
|
|
res = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
check:
|
|
res.isErr and res.error.kind == FailedToCreateSecretFile
|
|
|
|
# The secrets dir was pre-existing, so it should be preserved and
|
|
# it should remain empty:
|
|
dirExists(testSecretsDir)
|
|
testSecretsDir.isEmptyDir
|
|
|
|
# The creation of the validators dir should be rolled-back
|
|
not dirExists(testValidatorsDir)
|
|
|
|
test "`createLocalValidatorFiles` with `validatorsDir` without permissions":
|
|
# Creating `validators` dir with `UserRead` permissions before
|
|
# calling `createValidatorFiles` which should result in problems
|
|
# creating `keystoreDir` inside the dir.
|
|
discard createPath(testValidatorsDir, 0o400)
|
|
|
|
let
|
|
res = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
check:
|
|
res.isErr and res.error.kind == FailedToCreateKeystoreDir
|
|
|
|
# The creation of the secrets dir should be rolled-back
|
|
not dirExists(testSecretsDir)
|
|
|
|
# The validators dir was pre-existing, so it should be preserved and
|
|
# it should remain empty:
|
|
dirExists(testValidatorsDir)
|
|
testValidatorsDir.isEmptyDir
|
|
|
|
test "`createLocalValidatorFiles` with `keystoreDir` without permissions":
|
|
# Creating `keystore` dir with `UserRead` permissions before
|
|
# calling `createValidatorFiles` which should result in problems
|
|
# creating keystore file inside this dir:
|
|
discard createPath(testValidatorsDir, 0o700)
|
|
discard createPath(keystoreDir, 0o400)
|
|
|
|
let
|
|
res = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
check:
|
|
res.isErr and res.error.kind == FailedToCreateKeystoreFile
|
|
|
|
not dirExists(testSecretsDir)
|
|
|
|
dirExists(testValidatorsDir)
|
|
not fileExists(testValidatorsDir / hexEncodedPubkey)
|
|
testValidatorsDir.isEmptyDir
|
|
|
|
test "`createValidatorFiles` with already existing dirs and any error":
|
|
# Generate deposits so we have files and dirs already existing
|
|
# before testing `createValidatorFiles` failure
|
|
discard generateDeposits(
|
|
cfg,
|
|
rng[],
|
|
seed,
|
|
0, simulationDepositsCount,
|
|
testValidatorsDir,
|
|
testSecretsDir)
|
|
|
|
let
|
|
validatorsCountBefore = directoryItemsCount(testValidatorsDir)
|
|
secretsCountBefore = directoryItemsCount(testSecretsDir)
|
|
|
|
# Creating `keystore` dir with `UserRead` permissions before calling
|
|
# `createValidatorFiles` which will result in error
|
|
discard createPath(keystoreDir, 0o400)
|
|
|
|
let
|
|
res = createLocalValidatorFiles(testSecretsDir, testValidatorsDir,
|
|
keystoreDir,
|
|
secretFile, password,
|
|
keystoreFile, keystoreJsonContents)
|
|
|
|
validatorsCountAfter = directoryItemsCount(testValidatorsDir)
|
|
secretsCountAfter = directoryItemsCount(testSecretsDir)
|
|
|
|
check:
|
|
res.isErr
|
|
|
|
# `secrets` & `validators` should be removed during the roll-back:
|
|
dirExists(testSecretsDir)
|
|
dirExists(testValidatorsDir)
|
|
|
|
# The number of directies should not have changed after the failure:
|
|
validatorsCountBefore == validatorsCountAfter
|
|
secretsCountBefore == secretsCountAfter
|
|
|
|
os.removeDir testDataDir
|
|
|
|
suite "saveKeystore()":
|
|
setup:
|
|
let
|
|
curKeystoreDir0 = testValidatorsDir / MultipleKeystoreNames[0]
|
|
curSecretsFile0 = testSecretsDir / MultipleKeystoreNames[0]
|
|
remoteKeystoreFile0 = curKeystoreDir0 / RemoteKeystoreFileName
|
|
localKeystoreFile0 = curKeystoreDir0 / KeystoreFileName
|
|
curSigningKey0 = MultipleSigningKeys[0]
|
|
curCookedKey0 = curSigningKey0.toPubKey()
|
|
curPublicKey0 {.used.} = curCookedKey0.toPubKey()
|
|
|
|
curKeystoreDir1 = testValidatorsDir / MultipleKeystoreNames[1]
|
|
curSecretsFile1 {.used.} = testSecretsDir / MultipleKeystoreNames[1]
|
|
remoteKeystoreFile1 {.used.} = curKeystoreDir1 / RemoteKeystoreFileName
|
|
localKeystoreFile1 {.used.} = curKeystoreDir1 / KeystoreFileName
|
|
curSigningKey1 = MultipleSigningKeys[1]
|
|
curCookedKey1 = curSigningKey1.toPubKey()
|
|
curPublicKey1 {.used.} = curCookedKey1.toPubKey()
|
|
|
|
curSigningPath {.used.} =
|
|
validateKeyPath("m/12381/60/0/0").expect("Valid Keypath")
|
|
|
|
teardown:
|
|
os.removeDir testValidatorsDir
|
|
os.removeDir testSecretsDir
|
|
|
|
test "Save [LOCAL] keystore after [LOCAL] keystore with same id":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
res2 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isErr
|
|
res2.error().kind == DuplicateKeystoreDir
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 1
|
|
|
|
dirExists(curKeystoreDir0)
|
|
not(fileExists(remoteKeystoreFile0))
|
|
fileExists(localKeystoreFile0)
|
|
fileExists(curSecretsFile0)
|
|
|
|
namesEqual(validatorPubKeys, [MultipleKeystoreNames[0]])
|
|
|
|
test "Save [REMOTE] keystore after [REMOTE] keystore with same id":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
res2 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isErr
|
|
res2.error().kind == DuplicateKeystoreDir
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 0
|
|
|
|
dirExists(curKeystoreDir0)
|
|
fileExists(remoteKeystoreFile0)
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
namesEqual(validatorPubKeys, [MultipleKeystoreNames[0]])
|
|
|
|
test "Save [REMOTE] keystore after [LOCAL] keystore with same id":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
res2 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isErr
|
|
res2.error().kind == DuplicateKeystoreDir
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 1
|
|
|
|
dirExists(curKeystoreDir0)
|
|
not(fileExists(remoteKeystoreFile0))
|
|
fileExists(localKeystoreFile0)
|
|
fileExists(curSecretsFile0)
|
|
|
|
namesEqual(validatorPubKeys, [MultipleKeystoreNames[0]])
|
|
|
|
test "Save [LOCAL] keystore after [REMOTE] keystore with same id":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
res2 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isErr
|
|
res2.error().kind == DuplicateKeystoreDir
|
|
|
|
validatorsCount == 1
|
|
secretsCount == 0
|
|
|
|
dirExists(curKeystoreDir0)
|
|
fileExists(remoteKeystoreFile0)
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
namesEqual(validatorPubKeys, [MultipleKeystoreNames[0]])
|
|
|
|
test "Save [LOCAL] keystore after [LOCAL] keystore with different id":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
res2 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey1, curCookedKey1, curSigningPath,
|
|
"", mode = Fast)
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
|
|
validatorsCount == 2
|
|
secretsCount == 2
|
|
|
|
dirExists(curKeystoreDir0)
|
|
not(fileExists(remoteKeystoreFile0))
|
|
fileExists(localKeystoreFile0)
|
|
fileExists(curSecretsFile0)
|
|
|
|
dirExists(curKeystoreDir1)
|
|
not(fileExists(remoteKeystoreFile1))
|
|
fileExists(localKeystoreFile1)
|
|
fileExists(curSecretsFile1)
|
|
|
|
namesEqual(validatorPubKeys,
|
|
[MultipleKeystoreNames[0], MultipleKeystoreNames[1]])
|
|
|
|
test "Save [REMOTE] keystore after [REMOTE] keystore with different id":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
res2 = saveKeystore(testValidatorsDir, curPublicKey1, MultipleRemoteUri)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
|
|
validatorsCount == 2
|
|
secretsCount == 0
|
|
|
|
dirExists(curKeystoreDir0)
|
|
fileExists(remoteKeystoreFile0)
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
dirExists(curKeystoreDir1)
|
|
fileExists(remoteKeystoreFile1)
|
|
not(fileExists(localKeystoreFile1))
|
|
not(fileExists(curSecretsFile1))
|
|
|
|
namesEqual(validatorPubKeys,
|
|
[MultipleKeystoreNames[0], MultipleKeystoreNames[1]])
|
|
|
|
test "Save [LOCAL] keystore after [REMOTE] keystore with different id":
|
|
let
|
|
res1 = saveKeystore(testValidatorsDir, curPublicKey0, MultipleRemoteUri)
|
|
res2 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey1, curCookedKey1, curSigningPath,
|
|
"", mode = Fast)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
|
|
validatorsCount == 2
|
|
secretsCount == 1
|
|
|
|
dirExists(curKeystoreDir0)
|
|
fileExists(remoteKeystoreFile0)
|
|
not(fileExists(localKeystoreFile0))
|
|
not(fileExists(curSecretsFile0))
|
|
|
|
dirExists(curKeystoreDir1)
|
|
not(fileExists(remoteKeystoreFile1))
|
|
fileExists(localKeystoreFile1)
|
|
fileExists(curSecretsFile1)
|
|
|
|
namesEqual(validatorPubKeys,
|
|
[MultipleKeystoreNames[0], MultipleKeystoreNames[1]])
|
|
|
|
test "Save [REMOTE] keystore after [LOCAL] keystore with different id":
|
|
let
|
|
res1 = saveKeystore(rng[], testValidatorsDir, testSecretsDir,
|
|
curSigningKey0, curCookedKey0, curSigningPath,
|
|
"", mode = Fast)
|
|
res2 = saveKeystore(testValidatorsDir, curPublicKey1, MultipleRemoteUri)
|
|
|
|
validatorsCount = directoryItemsCount(testValidatorsDir)
|
|
secretsCount = directoryItemsCount(testSecretsDir)
|
|
|
|
validatorPubKeys = validatorPubKeysInDir(testValidatorsDir)
|
|
|
|
check:
|
|
res1.isOk
|
|
res2.isOk
|
|
|
|
validatorsCount == 2
|
|
secretsCount == 1
|
|
|
|
dirExists(curKeystoreDir0)
|
|
not(fileExists(remoteKeystoreFile0))
|
|
fileExists(localKeystoreFile0)
|
|
fileExists(curSecretsFile0)
|
|
|
|
dirExists(curKeystoreDir1)
|
|
fileExists(remoteKeystoreFile1)
|
|
not(fileExists(localKeystoreFile1))
|
|
not(fileExists(curSecretsFile1))
|
|
|
|
namesEqual(validatorPubKeys,
|
|
[MultipleKeystoreNames[0], MultipleKeystoreNames[1]])
|