From 7a8e2652511d3da9e2c528cc40b8b4a0b7a8765f Mon Sep 17 00:00:00 2001 From: cheatfate Date: Sat, 3 Apr 2021 03:21:44 +0300 Subject: [PATCH] Fix ValidatorIndex issues with workaround. --- beacon_chain/rpc/beacon_rest_api.nim | 57 +++++++++++++++++++++++----- beacon_chain/rpc/rest_utils.nim | 45 ++++++++++++++-------- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/beacon_chain/rpc/beacon_rest_api.nim b/beacon_chain/rpc/beacon_rest_api.nim index 3ce05c8a0..5f638a21f 100644 --- a/beacon_chain/rpc/beacon_rest_api.nim +++ b/beacon_chain/rpc/beacon_rest_api.nim @@ -247,10 +247,23 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = "Only unique validator keys allowed") res1.incl(item.key) of ValidatorQueryKind.Index: - if item.index in res2: + let vitem = + block: + let vres = item.index.toValidatorIndex() + if vres.isErr(): + case vres.error() + of ValidatorIndexError.TooHighValue: + return RestApiResponse.jsonError(Http400, + "Incorrect validator index value") + of ValidatorIndexError.UnsupportedValue: + return RestApiResponse.jsonError(Http500, + "Unsupported validator index value") + vres.get() + + if vitem in res2: return RestApiResponse.jsonError(Http400, "Only unique validator indexes allowed") - res2.incl(item.index) + res2.incl(vitem) (res1, res2) node.withStateForBlockSlot(bslot): @@ -309,7 +322,7 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = bres.get() if validator_id.isErr(): return RestApiResponse.jsonError(Http400, "Invalid validator_id", - $validator_id.error()) + $validator_id.error()) node.withStateForBlockSlot(bslot): let current_epoch = get_current_epoch(node.chainDag.headState.data.data) let vid = validator_id.get() @@ -332,16 +345,28 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = "Could not obtain validator's status") return RestApiResponse.jsonError(Http404, "Could not find validator") of ValidatorQueryKind.Index: - let index = uint64(vid.index) - if index >= uint64(len(state().validators)): + let vindex = + block: + let vres = vid.index.toValidatorIndex() + if vres.isErr(): + case vres.error() + of ValidatorIndexError.TooHighValue: + return RestApiResponse.jsonError(Http400, + "Incorrect validator index value") + of ValidatorIndexError.UnsupportedValue: + return RestApiResponse.jsonError(Http500, + "Unsupported validator index value") + vres.get() + + if uint64(vindex) >= uint64(len(state().validators)): return RestApiResponse.jsonError(Http404, "Could not find validator") - let validator = state().validators[index] + let validator = state().validators[vindex] let sres = validator.getStatus(current_epoch) if sres.isOk(): return RestApiResponse.jsonResponse( ( - index: ValidatorIndex(index), - balance: Base10.toString(state().balances[index]), + index: vindex, + balance: Base10.toString(state().balances[vindex]), status: toString(sres.get()), validator: validator ) @@ -387,10 +412,22 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = "Only unique validator keys allowed") res1.incl(item.key) of ValidatorQueryKind.Index: - if item.index in res2: + let vitem = + block: + let vres = item.index.toValidatorIndex() + if vres.isErr(): + case vres.error() + of ValidatorIndexError.TooHighValue: + return RestApiResponse.jsonError(Http400, + "Incorrect validator index value") + of ValidatorIndexError.UnsupportedValue: + return RestApiResponse.jsonError(Http500, + "Unsupported validator index value") + vres.get() + if vitem in res2: return RestApiResponse.jsonError(Http400, "Only unique validator indexes allowed") - res2.incl(item.index) + res2.incl(vitem) (res1, res2) node.withStateForBlockSlot(bslot): let current_epoch = get_current_epoch(node.chainDag.headState.data.data) diff --git a/beacon_chain/rpc/rest_utils.nim b/beacon_chain/rpc/rest_utils.nim index e6ae6a27f..db76d1d94 100644 --- a/beacon_chain/rpc/rest_utils.nim +++ b/beacon_chain/rpc/rest_utils.nim @@ -24,23 +24,24 @@ const # Size of `ValidatorPubKey` hexadecimal value (without 0x) ValidatorSigSize = RawSigSize * 2 # Size of `ValidatorSig` hexadecimal value (without 0x) - ValidatorIndexSize = len($(1 shl 40)) - # Maximum size of `ValidatorIndex` decimal value RootHashSize = sizeof(Eth2Digest) * 2 # Size of `xxx_root` hexadecimal value (without 0x) - FarFutureEpochString* = "18446744073709551615" - MaxEpoch* = compute_epoch_at_slot(not(0'u64)) type ValidatorQueryKind* {.pure.} = enum Index, Key + RestValidatorIndex* = distinct uint64 + + ValidatorIndexError* {.pure.} = enum + UnsupportedValue, TooHighValue + ValidatorIdent* = object case kind*: ValidatorQueryKind of ValidatorQueryKind.Index: - index*: ValidatorIndex + index*: RestValidatorIndex of ValidatorQueryKind.Key: key*: ValidatorPubKey @@ -165,10 +166,7 @@ proc validate(key: string, value: string): int = else: match(value.toOpenArray(2, len(value) - 1), HexadecimalSet) else: - if len(value) > ValidatorIndexSize: - 1 - else: - match(value, DecimalSet) + match(value, DecimalSet) else: match(value, DecimalSet) else: @@ -251,9 +249,6 @@ proc decodeString*(t: typedesc[BlockIdent], proc decodeString*(t: typedesc[ValidatorIdent], value: string): Result[ValidatorIdent, cstring] = - # This should raise exception if ValidatorIndex type will be changed, - # because currently it `uint32` but in 40bits size in specification. - doAssert(sizeof(uint32) == sizeof(ValidatorIndex)) if len(value) > 2: if (value[0] == '0') and (value[1] == 'x'): if len(value) != ValidatorKeySize + 2: @@ -263,15 +258,15 @@ proc decodeString*(t: typedesc[ValidatorIdent], ok(ValidatorIdent(kind: ValidatorQueryKind.Key, key: res)) elif (value[0] in DecimalSet) and (value[1] in DecimalSet): - let res = ? Base10.decode(uint32, value) + let res = ? Base10.decode(uint64, value) ok(ValidatorIdent(kind: ValidatorQueryKind.Index, - index: ValidatorIndex(res))) + index: RestValidatorIndex(res))) else: err("Incorrect validator identifier value") else: - let res = ? Base10.decode(uint32, value) + let res = ? Base10.decode(uint64, value) ok(ValidatorIdent(kind: ValidatorQueryKind.Index, - index: ValidatorIndex(res))) + index: RestValidatorIndex(res))) proc decodeString*(t: typedesc[PeerID], value: string): Result[PeerID, cstring] = @@ -484,3 +479,21 @@ template withStateForBlockSlot*(node: BeaconNode, let rpcState = assignClone(node.chainDag.headState) node.chainDag.withState(rpcState[], blockSlot): body + +proc toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex, + ValidatorIndexError] = + when sizeof(ValidatorIndex) == 4: + if uint64(value) < VALIDATOR_REGISTRY_LIMIT: + if uint64(value) <= uint64(high(uint32)): + ok(ValidatorIndex(value)) + else: + err(ValidatorIndexError.UnsupportedValue) + else: + err(ValidatorIndexError.TooHighValue) + elif sizeof(ValidatorIndex) == 8: + if uint64(value) < VALIDATOR_REGISTRY_LIMIT: + ok(ValidatorIndex(value)) + else: + err(ValidatorIndexError.TooHighValue) + else: + doAssert(false, "ValidatorIndex type size is incorrect")