Skip to content

Commit

Permalink
ncli verifyDeposit: a simple helper for inspecting deposit events
Browse files Browse the repository at this point in the history
  • Loading branch information
zah committed Jul 11, 2022
1 parent 571577c commit dcaa8c7
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 49 deletions.
16 changes: 2 additions & 14 deletions beacon_chain/conf.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ import
./spec/datatypes/base,
./networking/network_metadata,
./validators/slashing_protection_common,
./conf/eth2_types_confutils_defs,
./filepath

from consensus_object_pools/block_pools_types_light_client
import LightClientDataImportMode

export
uri, nat, enr,
uri, nat, enr, eth2_types_confutils_defs,
defaultEth2TcpPort, enabledLogLevel, ValidIpAddress,
defs, parseCmdArg, completeCmdArg, network_metadata,
network, BlockHashOrNumber,
Expand Down Expand Up @@ -918,13 +919,6 @@ proc createDumpDirs*(config: BeaconNodeConf) =
warn "Could not create dump directory",
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
{.raises: [ValueError, Defect].} =
GraffitiBytes.init(input)
Expand All @@ -950,12 +944,6 @@ func parseCmdArg*(T: type PubKey0x, input: string): T
{.raises: [ValueError, Defect].} =
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] =
return @[]

Expand Down
27 changes: 27 additions & 0 deletions beacon_chain/conf/eth2_types_confutils_defs.nim
Original file line number Diff line number Diff line change
@@ -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 @[]
26 changes: 26 additions & 0 deletions beacon_chain/eth1/deposit_contract_abi.nim
Original file line number Diff line number Diff line change
@@ -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.}
22 changes: 1 addition & 21 deletions beacon_chain/eth1/eth1_monitor.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import
../networking/network_metadata,
../consensus_object_pools/block_pools_types,
".."/[beacon_chain_db, beacon_node_status, beacon_clock],
./deposit_contract_abi,
./merkle_minimal

from std/times import getTime, inSeconds, initTime, `-`
Expand All @@ -32,27 +33,6 @@ export
logScope:
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
web3Timeouts = 60.seconds
hasDepositRootChecks = defined(has_deposit_root_checks)
Expand Down
104 changes: 91 additions & 13 deletions ncli/ncli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ import
../beacon_chain/spec/eth2_apis/eth2_rest_serialization,
../beacon_chain/spec/datatypes/[phase0, altair, bellatrix],
../beacon_chain/spec/[
eth2_ssz_serialization, forks, helpers, state_transition],
../beacon_chain/networking/network_metadata
eth2_ssz_serialization, forks, helpers, state_transition, signatures],
../beacon_chain/networking/network_metadata,
../beacon_chain/conf/eth2_types_confutils_defs,
../beacon_chain/eth1/deposit_contract_abi

type
Cmd* = enum
hashTreeRoot = "Compute hash tree root of SSZ object"
pretty = "Pretty-print SSZ object"
transition = "Run state transition function"
slots = "Apply empty slots"
verifyDeposit = "Verify deposit"

NcliConf* = object
eth2Network* {.
Expand All @@ -28,29 +31,29 @@ type
of hashTreeRoot:
htrKind* {.
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* {.
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:
prettyKind* {.
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* {.
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:
preState* {.
argument
desc: "State to which to apply specified block"}: string
desc: "State to which to apply specified block" .}: string

blck* {.
argument
desc: "Block to apply to preState"}: string
desc: "Block to apply to preState" .}: string

postState* {.
argument
Expand All @@ -59,20 +62,39 @@ type
verifyStateRoot* {.
argument
desc: "Verify state root (default true)"
defaultValue: true}: bool
defaultValue: true .}: bool

of slots:
preState2* {.
argument
desc: "State to which to apply specified block"}: string
desc: "State to which to apply specified block" .}: string

slot* {.
argument
desc: "Block to apply to preState"}: uint64
desc: "Block to apply to preState" .}: uint64

postState2* {.
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) =
case value.kind:
Expand Down Expand Up @@ -168,7 +190,6 @@ proc doSSZ(conf: NcliConf) =
else:
raiseAssert "doSSZ() only implements hashTreeRoot and pretty commands"


case kind
of "attester_slashing": printit(AttesterSlashing)
of "attestation": printit(Attestation)
Expand All @@ -191,6 +212,62 @@ proc doSSZ(conf: NcliConf) =
of "proposer_slashing": printit(ProposerSlashing)
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:
let
conf = NcliConf.load()
Expand All @@ -200,3 +277,4 @@ when isMainModule:
of pretty: doSSZ(conf)
of transition: doTransition(conf)
of slots: doSlots(conf)
of verifyDeposit: doVerifyDeposit(conf)

0 comments on commit dcaa8c7

Please sign in to comment.