ncli verifyDeposit: a simple helper for inspecting deposit events
This commit is contained in:
parent
571577c662
commit
dcaa8c7014
|
@ -25,13 +25,14 @@ import
|
||||||
./spec/datatypes/base,
|
./spec/datatypes/base,
|
||||||
./networking/network_metadata,
|
./networking/network_metadata,
|
||||||
./validators/slashing_protection_common,
|
./validators/slashing_protection_common,
|
||||||
|
./conf/eth2_types_confutils_defs,
|
||||||
./filepath
|
./filepath
|
||||||
|
|
||||||
from consensus_object_pools/block_pools_types_light_client
|
from consensus_object_pools/block_pools_types_light_client
|
||||||
import LightClientDataImportMode
|
import LightClientDataImportMode
|
||||||
|
|
||||||
export
|
export
|
||||||
uri, nat, enr,
|
uri, nat, enr, eth2_types_confutils_defs,
|
||||||
defaultEth2TcpPort, enabledLogLevel, ValidIpAddress,
|
defaultEth2TcpPort, enabledLogLevel, ValidIpAddress,
|
||||||
defs, parseCmdArg, completeCmdArg, network_metadata,
|
defs, parseCmdArg, completeCmdArg, network_metadata,
|
||||||
network, BlockHashOrNumber,
|
network, BlockHashOrNumber,
|
||||||
|
@ -918,13 +919,6 @@ proc createDumpDirs*(config: BeaconNodeConf) =
|
||||||
warn "Could not create dump directory",
|
warn "Could not create dump directory",
|
||||||
path = config.dumpDirOutgoing, err = ioErrorMsg(res.error)
|
path = config.dumpDirOutgoing, err = ioErrorMsg(res.error)
|
||||||
|
|
||||||
func parseCmdArg*(T: type Eth2Digest, input: string): T
|
|
||||||
{.raises: [ValueError, Defect].} =
|
|
||||||
Eth2Digest.fromHex(input)
|
|
||||||
|
|
||||||
func completeCmdArg*(T: type Eth2Digest, input: string): seq[string] =
|
|
||||||
return @[]
|
|
||||||
|
|
||||||
func parseCmdArg*(T: type GraffitiBytes, input: string): T
|
func parseCmdArg*(T: type GraffitiBytes, input: string): T
|
||||||
{.raises: [ValueError, Defect].} =
|
{.raises: [ValueError, Defect].} =
|
||||||
GraffitiBytes.init(input)
|
GraffitiBytes.init(input)
|
||||||
|
@ -950,12 +944,6 @@ func parseCmdArg*(T: type PubKey0x, input: string): T
|
||||||
{.raises: [ValueError, Defect].} =
|
{.raises: [ValueError, Defect].} =
|
||||||
PubKey0x(hexToPaddedByteArray[RawPubKeySize](input))
|
PubKey0x(hexToPaddedByteArray[RawPubKeySize](input))
|
||||||
|
|
||||||
func parseCmdArg*(T: type ValidatorPubKey, input: string): T
|
|
||||||
{.raises: [ValueError, Defect].} =
|
|
||||||
let res = ValidatorPubKey.fromHex(input)
|
|
||||||
if res.isErr(): raise (ref ValueError)(msg: $res.error())
|
|
||||||
res.get()
|
|
||||||
|
|
||||||
func completeCmdArg*(T: type PubKey0x, input: string): seq[string] =
|
func completeCmdArg*(T: type PubKey0x, input: string): seq[string] =
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import
|
||||||
|
../spec/[crypto, digest]
|
||||||
|
|
||||||
|
func parseCmdArg*(T: type Eth2Digest, input: string): T
|
||||||
|
{.raises: [ValueError, Defect].} =
|
||||||
|
Eth2Digest.fromHex(input)
|
||||||
|
|
||||||
|
func completeCmdArg*(T: type Eth2Digest, input: string): seq[string] =
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
func parseCmdArg*(T: type ValidatorPubKey, input: string): T
|
||||||
|
{.raises: [ValueError, Defect].} =
|
||||||
|
let res = ValidatorPubKey.fromHex(input)
|
||||||
|
if res.isErr(): raise (ref ValueError)(msg: $res.error())
|
||||||
|
res.get()
|
||||||
|
|
||||||
|
func completeCmdArg*(T: type ValidatorPubKey, input: string): seq[string] =
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
func parseCmdArg*(T: type ValidatorSig, input: string): T
|
||||||
|
{.raises: [ValueError, Defect].} =
|
||||||
|
let res = ValidatorSig.fromHex(input)
|
||||||
|
if res.isErr(): raise (ref ValueError)(msg: $res.error())
|
||||||
|
res.get()
|
||||||
|
|
||||||
|
func completeCmdArg*(T: type ValidatorSig, input: string): seq[string] =
|
||||||
|
return @[]
|
|
@ -0,0 +1,26 @@
|
||||||
|
import
|
||||||
|
web3, web3/ethtypes
|
||||||
|
|
||||||
|
export
|
||||||
|
web3, ethtypes
|
||||||
|
|
||||||
|
type
|
||||||
|
PubKeyBytes* = DynamicBytes[48, 48]
|
||||||
|
WithdrawalCredentialsBytes* = DynamicBytes[32, 32]
|
||||||
|
SignatureBytes* = DynamicBytes[96, 96]
|
||||||
|
Int64LeBytes* = DynamicBytes[8, 8]
|
||||||
|
|
||||||
|
contract(DepositContract):
|
||||||
|
proc deposit(pubkey: PubKeyBytes,
|
||||||
|
withdrawalCredentials: WithdrawalCredentialsBytes,
|
||||||
|
signature: SignatureBytes,
|
||||||
|
deposit_data_root: FixedBytes[32])
|
||||||
|
|
||||||
|
proc get_deposit_root(): FixedBytes[32]
|
||||||
|
proc get_deposit_count(): Int64LeBytes
|
||||||
|
|
||||||
|
proc DepositEvent(pubkey: PubKeyBytes,
|
||||||
|
withdrawalCredentials: WithdrawalCredentialsBytes,
|
||||||
|
amount: Int64LeBytes,
|
||||||
|
signature: SignatureBytes,
|
||||||
|
index: Int64LeBytes) {.event.}
|
|
@ -21,6 +21,7 @@ import
|
||||||
../networking/network_metadata,
|
../networking/network_metadata,
|
||||||
../consensus_object_pools/block_pools_types,
|
../consensus_object_pools/block_pools_types,
|
||||||
".."/[beacon_chain_db, beacon_node_status, beacon_clock],
|
".."/[beacon_chain_db, beacon_node_status, beacon_clock],
|
||||||
|
./deposit_contract_abi,
|
||||||
./merkle_minimal
|
./merkle_minimal
|
||||||
|
|
||||||
from std/times import getTime, inSeconds, initTime, `-`
|
from std/times import getTime, inSeconds, initTime, `-`
|
||||||
|
@ -32,27 +33,6 @@ export
|
||||||
logScope:
|
logScope:
|
||||||
topics = "eth1"
|
topics = "eth1"
|
||||||
|
|
||||||
type
|
|
||||||
PubKeyBytes = DynamicBytes[48, 48]
|
|
||||||
WithdrawalCredentialsBytes = DynamicBytes[32, 32]
|
|
||||||
SignatureBytes = DynamicBytes[96, 96]
|
|
||||||
Int64LeBytes = DynamicBytes[8, 8]
|
|
||||||
|
|
||||||
contract(DepositContract):
|
|
||||||
proc deposit(pubkey: PubKeyBytes,
|
|
||||||
withdrawalCredentials: WithdrawalCredentialsBytes,
|
|
||||||
signature: SignatureBytes,
|
|
||||||
deposit_data_root: FixedBytes[32])
|
|
||||||
|
|
||||||
proc get_deposit_root(): FixedBytes[32]
|
|
||||||
proc get_deposit_count(): Int64LeBytes
|
|
||||||
|
|
||||||
proc DepositEvent(pubkey: PubKeyBytes,
|
|
||||||
withdrawalCredentials: WithdrawalCredentialsBytes,
|
|
||||||
amount: Int64LeBytes,
|
|
||||||
signature: SignatureBytes,
|
|
||||||
index: Int64LeBytes) {.event.}
|
|
||||||
|
|
||||||
const
|
const
|
||||||
web3Timeouts = 60.seconds
|
web3Timeouts = 60.seconds
|
||||||
hasDepositRootChecks = defined(has_deposit_root_checks)
|
hasDepositRootChecks = defined(has_deposit_root_checks)
|
||||||
|
|
104
ncli/ncli.nim
104
ncli/ncli.nim
|
@ -7,8 +7,10 @@ import
|
||||||
../beacon_chain/spec/eth2_apis/eth2_rest_serialization,
|
../beacon_chain/spec/eth2_apis/eth2_rest_serialization,
|
||||||
../beacon_chain/spec/datatypes/[phase0, altair, bellatrix],
|
../beacon_chain/spec/datatypes/[phase0, altair, bellatrix],
|
||||||
../beacon_chain/spec/[
|
../beacon_chain/spec/[
|
||||||
eth2_ssz_serialization, forks, helpers, state_transition],
|
eth2_ssz_serialization, forks, helpers, state_transition, signatures],
|
||||||
../beacon_chain/networking/network_metadata
|
../beacon_chain/networking/network_metadata,
|
||||||
|
../beacon_chain/conf/eth2_types_confutils_defs,
|
||||||
|
../beacon_chain/eth1/deposit_contract_abi
|
||||||
|
|
||||||
type
|
type
|
||||||
Cmd* = enum
|
Cmd* = enum
|
||||||
|
@ -16,6 +18,7 @@ type
|
||||||
pretty = "Pretty-print SSZ object"
|
pretty = "Pretty-print SSZ object"
|
||||||
transition = "Run state transition function"
|
transition = "Run state transition function"
|
||||||
slots = "Apply empty slots"
|
slots = "Apply empty slots"
|
||||||
|
verifyDeposit = "Verify deposit"
|
||||||
|
|
||||||
NcliConf* = object
|
NcliConf* = object
|
||||||
eth2Network* {.
|
eth2Network* {.
|
||||||
|
@ -28,29 +31,29 @@ type
|
||||||
of hashTreeRoot:
|
of hashTreeRoot:
|
||||||
htrKind* {.
|
htrKind* {.
|
||||||
argument
|
argument
|
||||||
desc: "kind of SSZ object: attester_slashing, attestation, signed_block, block, block_body, block_header, deposit, deposit_data, eth1_data, state, proposer_slashing, or voluntary_exit"}: string
|
desc: "kind of SSZ object: attester_slashing, attestation, signed_block, block, block_body, block_header, deposit, deposit_data, eth1_data, state, proposer_slashing, or voluntary_exit" .}: string
|
||||||
|
|
||||||
htrFile* {.
|
htrFile* {.
|
||||||
argument
|
argument
|
||||||
desc: "filename of SSZ or JSON-encoded object of which to compute hash tree root"}: string
|
desc: "filename of SSZ or JSON-encoded object of which to compute hash tree root" .}: string
|
||||||
|
|
||||||
of pretty:
|
of pretty:
|
||||||
prettyKind* {.
|
prettyKind* {.
|
||||||
argument
|
argument
|
||||||
desc: "kind of SSZ object: attester_slashing, attestation, signed_block, block, block_body, block_header, deposit, deposit_data, eth1_data, state, proposer_slashing, or voluntary_exit"}: string
|
desc: "kind of SSZ object: attester_slashing, attestation, signed_block, block, block_body, block_header, deposit, deposit_data, eth1_data, state, proposer_slashing, or voluntary_exit" .}: string
|
||||||
|
|
||||||
prettyFile* {.
|
prettyFile* {.
|
||||||
argument
|
argument
|
||||||
desc: "filename of SSZ or JSON-encoded object to pretty-print"}: string
|
desc: "filename of SSZ or JSON-encoded object to pretty-print" .}: string
|
||||||
|
|
||||||
of transition:
|
of transition:
|
||||||
preState* {.
|
preState* {.
|
||||||
argument
|
argument
|
||||||
desc: "State to which to apply specified block"}: string
|
desc: "State to which to apply specified block" .}: string
|
||||||
|
|
||||||
blck* {.
|
blck* {.
|
||||||
argument
|
argument
|
||||||
desc: "Block to apply to preState"}: string
|
desc: "Block to apply to preState" .}: string
|
||||||
|
|
||||||
postState* {.
|
postState* {.
|
||||||
argument
|
argument
|
||||||
|
@ -59,20 +62,39 @@ type
|
||||||
verifyStateRoot* {.
|
verifyStateRoot* {.
|
||||||
argument
|
argument
|
||||||
desc: "Verify state root (default true)"
|
desc: "Verify state root (default true)"
|
||||||
defaultValue: true}: bool
|
defaultValue: true .}: bool
|
||||||
|
|
||||||
of slots:
|
of slots:
|
||||||
preState2* {.
|
preState2* {.
|
||||||
argument
|
argument
|
||||||
desc: "State to which to apply specified block"}: string
|
desc: "State to which to apply specified block" .}: string
|
||||||
|
|
||||||
slot* {.
|
slot* {.
|
||||||
argument
|
argument
|
||||||
desc: "Block to apply to preState"}: uint64
|
desc: "Block to apply to preState" .}: uint64
|
||||||
|
|
||||||
postState2* {.
|
postState2* {.
|
||||||
argument
|
argument
|
||||||
desc: "Filename of state resulting from applying blck to preState"}: string
|
desc: "Filename of state resulting from applying blck to preState" .}: string
|
||||||
|
|
||||||
|
of verifyDeposit:
|
||||||
|
pubkey* {.
|
||||||
|
desc: "The validator's public BLS signing key" .}: Option[ValidatorPubKey]
|
||||||
|
|
||||||
|
withdrawalCredentials* {.
|
||||||
|
desc: "The validator's withdrawal credentials (The prefixed 32 bytes form mandated by the spec)"
|
||||||
|
name: "withdrawal-credentials" .}: Option[Eth2Digest]
|
||||||
|
|
||||||
|
amount* {.
|
||||||
|
defaultValue: 32000000000
|
||||||
|
desc: "The deposit amount in gwei" .}: Gwei
|
||||||
|
|
||||||
|
signature* {.
|
||||||
|
desc: "The deposit signature" .}: Option[ValidatorSig]
|
||||||
|
|
||||||
|
depositData* {.
|
||||||
|
argument
|
||||||
|
desc: "Deposit event data from the official deposit contract in ABI form (hex-encoded)" .}: Option[string]
|
||||||
|
|
||||||
template saveSSZFile(filename: string, value: ForkedHashedBeaconState) =
|
template saveSSZFile(filename: string, value: ForkedHashedBeaconState) =
|
||||||
case value.kind:
|
case value.kind:
|
||||||
|
@ -168,7 +190,6 @@ proc doSSZ(conf: NcliConf) =
|
||||||
else:
|
else:
|
||||||
raiseAssert "doSSZ() only implements hashTreeRoot and pretty commands"
|
raiseAssert "doSSZ() only implements hashTreeRoot and pretty commands"
|
||||||
|
|
||||||
|
|
||||||
case kind
|
case kind
|
||||||
of "attester_slashing": printit(AttesterSlashing)
|
of "attester_slashing": printit(AttesterSlashing)
|
||||||
of "attestation": printit(Attestation)
|
of "attestation": printit(Attestation)
|
||||||
|
@ -191,6 +212,62 @@ proc doSSZ(conf: NcliConf) =
|
||||||
of "proposer_slashing": printit(ProposerSlashing)
|
of "proposer_slashing": printit(ProposerSlashing)
|
||||||
of "voluntary_exit": printit(VoluntaryExit)
|
of "voluntary_exit": printit(VoluntaryExit)
|
||||||
|
|
||||||
|
template init[N: static int](T: type DynamicBytes[N, N]): T =
|
||||||
|
T newSeq[byte](N)
|
||||||
|
|
||||||
|
proc doVerifyDeposit(conf: NcliConf) =
|
||||||
|
let cfg = getRuntimeConfig(conf.eth2Network)
|
||||||
|
|
||||||
|
let deposit = if conf.depositData.isSome:
|
||||||
|
let eventBytes = conf.depositData.get.substr(10)
|
||||||
|
var
|
||||||
|
pubkey = init deposit_contract_abi.PubKeyBytes
|
||||||
|
withdrawalCredentials = init WithdrawalCredentialsBytes
|
||||||
|
amount = init Int64LeBytes
|
||||||
|
signature = init SignatureBytes
|
||||||
|
index = init Int64LeBytes
|
||||||
|
|
||||||
|
echo eventBytes
|
||||||
|
|
||||||
|
try:
|
||||||
|
var offset = 0
|
||||||
|
offset += decode(eventBytes, offset, pubkey)
|
||||||
|
offset += decode(eventBytes, offset, withdrawalCredentials)
|
||||||
|
offset += decode(eventBytes, offset, amount)
|
||||||
|
offset += decode(eventBytes, offset, signature)
|
||||||
|
except CatchableError as err:
|
||||||
|
echo "Invalid deposit event: ", err.msg
|
||||||
|
quit 1
|
||||||
|
|
||||||
|
DepositData(
|
||||||
|
pubkey: ValidatorPubKey.init(pubkey.toArray),
|
||||||
|
withdrawal_credentials: Eth2Digest(data: withdrawalCredentials.toArray),
|
||||||
|
amount: bytes_to_uint64(amount.toArray),
|
||||||
|
signature: ValidatorSig.init(signature.toArray))
|
||||||
|
else:
|
||||||
|
var missingParams: seq[string]
|
||||||
|
|
||||||
|
if conf.pubkey.isNone: missingParams.add "pubkey"
|
||||||
|
if conf.withdrawalCredentials.isNone: missingParams.add "withdrawal-credentials"
|
||||||
|
if conf.signature.isNone: missingParams.add "singature"
|
||||||
|
|
||||||
|
if missingParams.len > 0:
|
||||||
|
echo "Please supply the hex-encoded deposit data as an argument or provide all of the following parameters:"
|
||||||
|
for param in missingParams:
|
||||||
|
echo " --", param
|
||||||
|
quit 1
|
||||||
|
|
||||||
|
DepositData(
|
||||||
|
pubkey: conf.pubkey.get,
|
||||||
|
withdrawal_credentials: conf.withdrawalCredentials.get,
|
||||||
|
amount: conf.amount,
|
||||||
|
signature: conf.signature.get)
|
||||||
|
|
||||||
|
let status = if verify_deposit_signature(cfg, deposit): "valid"
|
||||||
|
else: "invalid"
|
||||||
|
|
||||||
|
echo "The deposit is ", status
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
let
|
let
|
||||||
conf = NcliConf.load()
|
conf = NcliConf.load()
|
||||||
|
@ -200,3 +277,4 @@ when isMainModule:
|
||||||
of pretty: doSSZ(conf)
|
of pretty: doSSZ(conf)
|
||||||
of transition: doTransition(conf)
|
of transition: doTransition(conf)
|
||||||
of slots: doSlots(conf)
|
of slots: doSlots(conf)
|
||||||
|
of verifyDeposit: doVerifyDeposit(conf)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit acfda8192759c28ae120af1daa691551d993a54e
|
Subproject commit dfa91e350cf72e80eb44ed1bdbf6429c4de9b858
|
Loading…
Reference in New Issue