2018-12-19 14:58:53 +02:00
|
|
|
import
|
2019-11-21 09:15:10 +00:00
|
|
|
os, strutils,
|
2019-12-10 02:18:47 +02:00
|
|
|
chronicles, chronos, blscurve, nimcrypto, json_serialization, serialization,
|
2019-11-05 20:16:10 +02:00
|
|
|
web3, stint, eth/keys,
|
2020-04-15 09:59:47 +02:00
|
|
|
spec/[datatypes, digest, crypto], conf, ssz, interop, merkle_minimal
|
2018-12-19 14:58:53 +02:00
|
|
|
|
2019-07-12 17:24:11 +03:00
|
|
|
contract(DepositContract):
|
2019-09-09 18:59:02 +03:00
|
|
|
proc deposit(pubkey: Bytes48, withdrawalCredentials: Bytes32, signature: Bytes96, deposit_data_root: FixedBytes[32])
|
2019-07-12 17:24:11 +03:00
|
|
|
|
2019-03-18 05:54:08 +02:00
|
|
|
proc writeTextFile(filename: string, contents: string) =
|
|
|
|
writeFile(filename, contents)
|
2019-10-17 15:18:58 +02:00
|
|
|
# echo "Wrote ", filename
|
2019-03-18 05:54:08 +02:00
|
|
|
|
2018-12-19 14:58:53 +02:00
|
|
|
proc writeFile(filename: string, value: auto) =
|
|
|
|
Json.saveFile(filename, value, pretty = true)
|
2019-10-17 15:18:58 +02:00
|
|
|
# echo "Wrote ", filename
|
2018-12-19 14:58:53 +02:00
|
|
|
|
2019-07-12 17:24:11 +03:00
|
|
|
proc ethToWei(eth: UInt256): UInt256 =
|
|
|
|
eth * 1000000000000000000.u256
|
|
|
|
|
2019-10-29 04:43:23 +02:00
|
|
|
proc generateDeposits*(totalValidators: int,
|
|
|
|
outputDir: string,
|
|
|
|
randomKeys: bool,
|
|
|
|
firstIdx = 0): seq[Deposit] =
|
2019-09-01 17:02:49 +02:00
|
|
|
info "Generating deposits", totalValidators, outputDir, randomKeys
|
2019-03-27 14:06:06 +02:00
|
|
|
for i in 0 ..< totalValidators:
|
2019-03-07 07:59:28 -06:00
|
|
|
let
|
2019-10-29 04:43:23 +02:00
|
|
|
v = validatorFileBaseName(firstIdx + i)
|
2019-03-18 05:54:08 +02:00
|
|
|
depositFn = outputDir / v & ".deposit.json"
|
|
|
|
privKeyFn = outputDir / v & ".privkey"
|
2018-12-19 14:58:53 +02:00
|
|
|
|
2019-03-07 07:59:28 -06:00
|
|
|
if existsFile(depositFn) and existsFile(privKeyFn):
|
2019-09-01 17:02:49 +02:00
|
|
|
try:
|
|
|
|
result.add Json.loadFile(depositFn, Deposit)
|
|
|
|
continue
|
2019-09-02 15:09:55 +02:00
|
|
|
except SerializationError as err:
|
|
|
|
debug "Rewriting unreadable deposit", err = err.formatMsg(depositFn)
|
2019-09-01 17:02:49 +02:00
|
|
|
discard
|
2018-12-19 14:58:53 +02:00
|
|
|
|
2020-03-04 23:53:32 +01:00
|
|
|
var
|
|
|
|
privkey{.noInit.}: ValidatorPrivKey
|
|
|
|
pubKey{.noInit.}: ValidatorPubKey
|
|
|
|
|
|
|
|
if randomKeys:
|
2020-04-11 10:51:07 +02:00
|
|
|
(pubKey, privKey) = crypto.newKeyPair().tryGet()
|
2020-03-04 23:53:32 +01:00
|
|
|
else:
|
|
|
|
privKey = makeInteropPrivKey(i)
|
2020-04-11 10:51:07 +02:00
|
|
|
pubKey = privKey.toPubKey()
|
2018-12-19 14:58:53 +02:00
|
|
|
|
2019-09-01 17:02:49 +02:00
|
|
|
let dp = makeDeposit(pubKey, privKey)
|
2019-03-07 07:59:28 -06:00
|
|
|
|
2019-09-01 17:02:49 +02:00
|
|
|
result.add(dp)
|
2019-07-12 17:24:11 +03:00
|
|
|
|
2020-04-15 09:59:47 +02:00
|
|
|
# Does quadratic additional work, but fast enough, and otherwise more
|
|
|
|
# cleanly allows free intermixing of pre-existing and newly generated
|
|
|
|
# deposit and private key files. TODO: only generate new Merkle proof
|
|
|
|
# for the most recent deposit if this becomes bottleneck.
|
|
|
|
attachMerkleProofs(result)
|
|
|
|
|
|
|
|
writeTextFile(privKeyFn, privKey.toHex())
|
|
|
|
writeFile(depositFn, result[result.len - 1])
|
|
|
|
|
2019-09-01 17:02:49 +02:00
|
|
|
proc sendDeposits*(
|
|
|
|
deposits: seq[Deposit],
|
2019-11-05 20:16:10 +02:00
|
|
|
depositWeb3Url, depositContractAddress, privateKey: string) {.async.} =
|
2019-12-03 14:10:47 +02:00
|
|
|
|
2019-12-03 01:27:59 +02:00
|
|
|
var web3 = await newWeb3(depositWeb3Url)
|
2019-11-05 20:16:10 +02:00
|
|
|
if privateKey.len != 0:
|
2020-04-05 11:50:31 +02:00
|
|
|
web3.privateKey = PrivateKey.fromHex(privateKey).tryGet()
|
2019-12-03 14:10:47 +02:00
|
|
|
else:
|
|
|
|
let accounts = await web3.provider.eth_accounts()
|
|
|
|
if accounts.len == 0:
|
|
|
|
error "No account offered by the web3 provider", web3url = depositWeb3Url
|
|
|
|
return
|
|
|
|
web3.defaultAccount = accounts[0]
|
2019-12-03 01:27:59 +02:00
|
|
|
|
|
|
|
let contractAddress = Address.fromHex(depositContractAddress)
|
|
|
|
|
2019-09-01 17:02:49 +02:00
|
|
|
for i, dp in deposits:
|
|
|
|
let depositContract = web3.contractSender(DepositContract, contractAddress)
|
2019-11-18 13:48:41 +01:00
|
|
|
discard await depositContract.deposit(
|
2020-04-11 10:51:07 +02:00
|
|
|
Bytes48(dp.data.pubKey.toRaw()),
|
2019-09-01 17:02:49 +02:00
|
|
|
Bytes32(dp.data.withdrawal_credentials.data),
|
2020-04-11 10:51:07 +02:00
|
|
|
Bytes96(dp.data.signature.toRaw()),
|
2019-11-05 20:16:10 +02:00
|
|
|
FixedBytes[32](hash_tree_root(dp.data).data)).send(value = 32.u256.ethToWei, gasPrice = 1)
|
2019-09-01 17:02:49 +02:00
|
|
|
|
|
|
|
when isMainModule:
|
|
|
|
import confutils
|
|
|
|
|
|
|
|
cli do (totalValidators: int = 125000,
|
|
|
|
outputDir: string = "validators",
|
|
|
|
randomKeys: bool = false,
|
|
|
|
depositWeb3Url: string = "",
|
|
|
|
depositContractAddress: string = ""):
|
|
|
|
let deposits = generateDeposits(totalValidators, outputDir, randomKeys)
|
|
|
|
|
|
|
|
if depositWeb3Url.len() > 0 and depositContractAddress.len() > 0:
|
2019-09-09 18:59:02 +03:00
|
|
|
echo "Sending deposits to eth1..."
|
2019-11-05 20:16:10 +02:00
|
|
|
waitFor sendDeposits(deposits, depositWeb3Url, depositContractAddress, "")
|
2019-09-09 18:59:02 +03:00
|
|
|
echo "Done"
|