implement capellaImplementationMissing points; don't track not-active validator duties (#4340)

* implement several capellaImplementationMissing points

* don't register validator activity for not-active validators

* don't check validator indices already coming out of committees which exist; must be active validators, or else other deeper bugs
This commit is contained in:
tersec 2022-11-22 11:56:05 +00:00 committed by GitHub
parent 166746907f
commit ec443601eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 47 additions and 29 deletions

View File

@ -921,7 +921,7 @@ proc getBlockSSZ*(
of BeaconBlockFork.Bellatrix: of BeaconBlockFork.Bellatrix:
getBlockSSZ(db, key, data, bellatrix.TrustedSignedBeaconBlock) getBlockSSZ(db, key, data, bellatrix.TrustedSignedBeaconBlock)
of BeaconBlockFork.Capella: of BeaconBlockFork.Capella:
raiseAssert $capellaImplementationMissing getBlockSSZ(db, key, data, capella.TrustedSignedBeaconBlock)
proc getBlockSZ*( proc getBlockSZ*(
db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], db: BeaconChainDB, key: Eth2Digest, data: var seq[byte],

View File

@ -107,9 +107,8 @@ proc addResolvedHeadBlock(
var unrealized: FinalityCheckpoints var unrealized: FinalityCheckpoints
if enableTestFeatures in dag.updateFlags: if enableTestFeatures in dag.updateFlags:
unrealized = withState(state): unrealized = withState(state):
when stateFork >= BeaconStateFork.Capella: static: doAssert high(BeaconStateFork) == BeaconStateFork.Capella
raiseAssert $capellaImplementationMissing when stateFork >= BeaconStateFork.Altair:
elif stateFork >= BeaconStateFork.Altair:
forkyState.data.compute_unrealized_finality() forkyState.data.compute_unrealized_finality()
else: else:
forkyState.data.compute_unrealized_finality(cache) forkyState.data.compute_unrealized_finality(cache)

View File

@ -122,9 +122,7 @@ proc syncCommitteeRootForPeriod(
bsi = ? dag.getExistingBlockIdAtSlot(syncCommitteeSlot) bsi = ? dag.getExistingBlockIdAtSlot(syncCommitteeSlot)
dag.withUpdatedExistingState(tmpState, bsi) do: dag.withUpdatedExistingState(tmpState, bsi) do:
withState(state): withState(state):
when stateFork >= BeaconStateFork.Capella: when stateFork >= BeaconStateFork.Altair:
raiseAssert $capellaImplementationMissing
elif stateFork >= BeaconStateFork.Altair:
ok forkyState.syncCommitteeRoot ok forkyState.syncCommitteeRoot
else: raiseAssert "Unreachable" else: raiseAssert "Unreachable"
do: err() do: err()
@ -359,9 +357,7 @@ proc initLightClientUpdateForPeriod(
dag.handleUnexpectedLightClientError(bid.slot) dag.handleUnexpectedLightClientError(bid.slot)
return err() return err()
withStateAndBlck(state, bdata): withStateAndBlck(state, bdata):
when stateFork >= BeaconStateFork.Capella: when stateFork >= BeaconStateFork.Altair:
raiseAssert $capellaImplementationMissing
elif stateFork >= BeaconStateFork.Altair:
update.attested_header = blck.toBeaconBlockHeader() update.attested_header = blck.toBeaconBlockHeader()
update.next_sync_committee = forkyState.data.next_sync_committee update.next_sync_committee = forkyState.data.next_sync_committee
update.next_sync_committee_branch = update.next_sync_committee_branch =
@ -387,7 +383,6 @@ proc initLightClientUpdateForPeriod(
dag.handleUnexpectedLightClientError(signatureBid.slot) dag.handleUnexpectedLightClientError(signatureBid.slot)
return err() return err()
withBlck(bdata): withBlck(bdata):
static: doAssert high(BeaconStateFork) == BeaconStateFork.Capella
when stateFork >= BeaconStateFork.Altair: when stateFork >= BeaconStateFork.Altair:
update.sync_aggregate = blck.asSigned().message.body.sync_aggregate update.sync_aggregate = blck.asSigned().message.body.sync_aggregate
else: raiseAssert "Unreachable" else: raiseAssert "Unreachable"
@ -623,9 +618,7 @@ proc initLightClientDataCache*(dag: ChainDAGRef) =
if dag.head.slot < dag.lcDataStore.cache.tailSlot: if dag.head.slot < dag.lcDataStore.cache.tailSlot:
return return
withState(dag.headState): withState(dag.headState):
when stateFork >= BeaconStateFork.Capella: when stateFork >= BeaconStateFork.Altair:
raiseAssert $capellaImplementationMissing
elif stateFork >= BeaconStateFork.Altair:
dag.cacheLightClientData(forkyState, dag.head.bid) dag.cacheLightClientData(forkyState, dag.head.bid)
else: raiseAssert "Unreachable" # `tailSlot` cannot be before Altair else: raiseAssert "Unreachable" # `tailSlot` cannot be before Altair
if dag.lcDataStore.importMode == LightClientDataImportMode.OnlyNew: if dag.lcDataStore.importMode == LightClientDataImportMode.OnlyNew:
@ -676,9 +669,7 @@ proc initLightClientDataCache*(dag: ChainDAGRef) =
res.err() res.err()
continue continue
withStateAndBlck(dag.headState, bdata): withStateAndBlck(dag.headState, bdata):
when stateFork >= BeaconStateFork.Capella: when stateFork >= BeaconStateFork.Altair:
raiseAssert $capellaImplementationMissing
elif stateFork >= BeaconStateFork.Altair:
# Cache light client data (non-finalized blocks may refer to this) # Cache light client data (non-finalized blocks may refer to this)
if i != blocks.low: if i != blocks.low:
dag.cacheLightClientData(forkyState, bid) # `dag.head` already cached dag.cacheLightClientData(forkyState, bid) # `dag.head` already cached
@ -764,9 +755,7 @@ proc processHeadChangeForLightClient*(dag: ChainDAGRef) =
dag.lcDataStore.db.putBestUpdate( dag.lcDataStore.db.putBestUpdate(
period, dag.lcDataStore.cache.pendingBest.getOrDefault(key)) period, dag.lcDataStore.cache.pendingBest.getOrDefault(key))
withState(dag.headState): # Common case separate to avoid `tmpState` copy withState(dag.headState): # Common case separate to avoid `tmpState` copy
when stateFork >= BeaconStateFork.Capella: when stateFork >= BeaconStateFork.Altair:
raiseAssert $capellaImplementationMissing
elif stateFork >= BeaconStateFork.Altair:
let key = (headPeriod, forkyState.syncCommitteeRoot) let key = (headPeriod, forkyState.syncCommitteeRoot)
dag.lcDataStore.db.putBestUpdate( dag.lcDataStore.db.putBestUpdate(
headPeriod, dag.lcDataStore.cache.pendingBest.getOrDefault(key)) headPeriod, dag.lcDataStore.cache.pendingBest.getOrDefault(key))

View File

@ -235,3 +235,5 @@ const
"https://github.com/ethereum/beacon-APIs/pull/220" "https://github.com/ethereum/beacon-APIs/pull/220"
BlockIncorrectFork* = BlockIncorrectFork* =
"Block has incorrect fork" "Block has incorrect fork"
ValidatorNotActive* =
"Validator inactive"

View File

@ -266,7 +266,7 @@ proc getStateOptimistic*(node: BeaconNode,
case state.kind case state.kind
of BeaconStateFork.Phase0, BeaconStateFork.Altair: of BeaconStateFork.Phase0, BeaconStateFork.Altair:
some[bool](false) some[bool](false)
of BeaconStateFork.Bellatrix: of BeaconStateFork.Bellatrix, BeaconStateFork.Capella:
# A state is optimistic iff the block which created it is # A state is optimistic iff the block which created it is
withState(state): withState(state):
# The block root which created the state at slot `n` is at slot `n-1` # The block root which created the state at slot `n` is at slot `n-1`
@ -276,9 +276,6 @@ proc getStateOptimistic*(node: BeaconNode,
doAssert forkyState.data.slot > 0 doAssert forkyState.data.slot > 0
some[bool](node.dag.is_optimistic( some[bool](node.dag.is_optimistic(
get_block_root_at_slot(forkyState.data, forkyState.data.slot - 1))) get_block_root_at_slot(forkyState.data, forkyState.data.slot - 1)))
of BeaconStateFork.Capella:
if true: raiseAssert $capellaImplementationMissing
none[bool]()
else: else:
none[bool]() none[bool]()

View File

@ -637,6 +637,12 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
get_committee_count_per_slot(shufflingRef), request.slot, get_committee_count_per_slot(shufflingRef), request.slot,
request.committee_index) request.committee_index)
if not is_active_validator(
getStateField(
node.dag.headState, validators).item(request.validator_index),
request.slot.epoch):
return RestApiResponse.jsonError(Http400, ValidatorNotActive)
node.consensusManager[].actionTracker.registerDuty( node.consensusManager[].actionTracker.registerDuty(
request.slot, subnet_id, request.validator_index, request.slot, subnet_id, request.validator_index,
request.is_aggregator) request.is_aggregator)

View File

@ -18,6 +18,8 @@ import ".."/[eth2_ssz_serialization, forks, keystore],
"."/[rest_types, rest_keymanager_types] "."/[rest_types, rest_keymanager_types]
import nimcrypto/utils as ncrutils import nimcrypto/utils as ncrutils
from ".."/datatypes/capella import SignedBeaconBlock
export export
eth2_ssz_serialization, results, peerid, common, serialization, chronicles, eth2_ssz_serialization, results, peerid, common, serialization, chronicles,
json_serialization, options, net, sets, rest_types, slashing_protection_common json_serialization, options, net, sets, rest_types, slashing_protection_common
@ -90,6 +92,7 @@ type
EncodeOctetTypes* = EncodeOctetTypes* =
altair.SignedBeaconBlock | altair.SignedBeaconBlock |
bellatrix.SignedBeaconBlock | bellatrix.SignedBeaconBlock |
capella.SignedBeaconBlock |
phase0.SignedBeaconBlock phase0.SignedBeaconBlock
EncodeArrays* = EncodeArrays* =
@ -898,6 +901,8 @@ template prepareForkedBlockReading(
version = some(BeaconBlockFork.Altair) version = some(BeaconBlockFork.Altair)
of "BELLATRIX", "bellatrix": of "BELLATRIX", "bellatrix":
version = some(BeaconBlockFork.Bellatrix) version = some(BeaconBlockFork.Bellatrix)
of "CAPELLA", "capella":
version = some(BeaconBlockFork.Bellatrix)
else: else:
reader.raiseUnexpectedValue("Incorrect version field value") reader.raiseUnexpectedValue("Incorrect version field value")
of "block", "block_header", "data": of "block", "block_header", "data":
@ -1040,7 +1045,8 @@ proc writeValue*[
writer.writeField("version", forkIdentifier "bellatrix") writer.writeField("version", forkIdentifier "bellatrix")
writer.writeField("data", value.bellatrixData) writer.writeField("data", value.bellatrixData)
of BeaconBlockFork.Capella: of BeaconBlockFork.Capella:
raiseAssert $capellaImplementationMissing writer.writeField("version", forkIdentifier "capella")
writer.writeField("data", value.capellaData)
writer.endRecord() writer.endRecord()
## RestPublishedBeaconBlockBody ## RestPublishedBeaconBlockBody
@ -1337,7 +1343,12 @@ proc readValue*(reader: var JsonReader[RestJson],
) )
) )
of BeaconBlockFork.Capella: of BeaconBlockFork.Capella:
reader.raiseUnexpectedValue($capellaImplementationMissing) ForkedSignedBeaconBlock.init(
capella.SignedBeaconBlock(
message: blck.capellaData,
signature: signature.get()
)
)
) )
## ForkedSignedBeaconBlock ## ForkedSignedBeaconBlock
@ -1362,6 +1373,8 @@ proc readValue*(reader: var JsonReader[RestJson],
version = some(BeaconBlockFork.Altair) version = some(BeaconBlockFork.Altair)
of "bellatrix": of "bellatrix":
version = some(BeaconBlockFork.Bellatrix) version = some(BeaconBlockFork.Bellatrix)
of "capella":
version = some(BeaconBlockFork.Capella)
else: else:
reader.raiseUnexpectedValue("Incorrect version field value") reader.raiseUnexpectedValue("Incorrect version field value")
of "data": of "data":
@ -1434,7 +1447,8 @@ proc writeValue*(writer: var JsonWriter[RestJson],
writer.writeField("version", "bellatrix") writer.writeField("version", "bellatrix")
writer.writeField("data", value.bellatrixData) writer.writeField("data", value.bellatrixData)
of BeaconBlockFork.Capella: of BeaconBlockFork.Capella:
raiseAssert $capellaImplementationMissing writer.writeField("version", "capella")
writer.writeField("data", value.capellaData)
writer.endRecord() writer.endRecord()
# ForkedHashedBeaconState is used where a `ForkedBeaconState` normally would # ForkedHashedBeaconState is used where a `ForkedBeaconState` normally would
@ -1457,6 +1471,7 @@ proc readValue*(reader: var JsonReader[RestJson],
of "phase0": some(BeaconStateFork.Phase0) of "phase0": some(BeaconStateFork.Phase0)
of "altair": some(BeaconStateFork.Altair) of "altair": some(BeaconStateFork.Altair)
of "bellatrix": some(BeaconStateFork.Bellatrix) of "bellatrix": some(BeaconStateFork.Bellatrix)
of "capella": some(BeaconStateFork.Capella)
else: reader.raiseUnexpectedValue("Incorrect version field value") else: reader.raiseUnexpectedValue("Incorrect version field value")
of "data": of "data":
if data.isSome(): if data.isSome():
@ -1533,7 +1548,8 @@ proc writeValue*(writer: var JsonWriter[RestJson], value: ForkedHashedBeaconStat
writer.writeField("version", "bellatrix") writer.writeField("version", "bellatrix")
writer.writeField("data", value.bellatrixData.data) writer.writeField("data", value.bellatrixData.data)
of BeaconStateFork.Capella: of BeaconStateFork.Capella:
raiseAssert $capellaImplementationMissing writer.writeField("version", "capella")
writer.writeField("data", value.capellaData.data)
writer.endRecord() writer.endRecord()
## Web3SignerRequest ## Web3SignerRequest
@ -2915,6 +2931,7 @@ proc decodeString*(t: typedesc[BeaconBlockFork],
of "phase0": ok(BeaconBlockFork.Phase0) of "phase0": ok(BeaconBlockFork.Phase0)
of "altair": ok(BeaconBlockFork.Altair) of "altair": ok(BeaconBlockFork.Altair)
of "bellatrix": ok(BeaconBlockFork.Bellatrix) of "bellatrix": ok(BeaconBlockFork.Bellatrix)
of "capella": ok(BeaconBlockFork.Capella)
else: err("Unsupported or invalid beacon block fork version") else: err("Unsupported or invalid beacon block fork version")
proc decodeString*(t: typedesc[BeaconStateFork], proc decodeString*(t: typedesc[BeaconStateFork],
@ -2923,4 +2940,5 @@ proc decodeString*(t: typedesc[BeaconStateFork],
of "phase0": ok(BeaconStateFork.Phase0) of "phase0": ok(BeaconStateFork.Phase0)
of "altair": ok(BeaconStateFork.Altair) of "altair": ok(BeaconStateFork.Altair)
of "bellatrix": ok(BeaconStateFork.Bellatrix) of "bellatrix": ok(BeaconStateFork.Bellatrix)
of "capella": ok(BeaconStateFork.Capella)
else: err("Unsupported or invalid beacon state fork version") else: err("Unsupported or invalid beacon state fork version")

View File

@ -16,6 +16,8 @@ import
".."/[helpers, forks, keystore, eth2_ssz_serialization], ".."/[helpers, forks, keystore, eth2_ssz_serialization],
"."/[rest_types, rest_common, eth2_rest_serialization] "."/[rest_types, rest_common, eth2_rest_serialization]
from ".."/datatypes/capella import SignedBeaconBlock
export chronos, client, rest_types, eth2_rest_serialization export chronos, client, rest_types, eth2_rest_serialization
proc getGenesis*(): RestResponse[GetGenesisResponse] {. proc getGenesis*(): RestResponse[GetGenesisResponse] {.
@ -116,6 +118,11 @@ proc publishBlock*(body: bellatrix.SignedBeaconBlock): RestPlainResponse {.
meth: MethodPost.} meth: MethodPost.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock ## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
proc publishBlock*(body: capella.SignedBeaconBlock): RestPlainResponse {.
rest, endpoint: "/eth/v1/beacon/blocks",
meth: MethodPost.}
## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock
proc publishSszBlock*( proc publishSszBlock*(
client: RestClientRef, client: RestClientRef,
blck: ForkySignedBeaconBlock blck: ForkySignedBeaconBlock

View File

@ -1686,7 +1686,7 @@ proc publishBlock*(
of BeaconBlockFork.Bellatrix: of BeaconBlockFork.Bellatrix:
publishBlock(it, data.bellatrixData) publishBlock(it, data.bellatrixData)
of BeaconBlockFork.Capella: of BeaconBlockFork.Capella:
raiseAssert $capellaImplementationMissing publishBlock(it, data.capellaData)
do: do:
if apiResponse.isErr(): if apiResponse.isErr():
debug ErrorMessage, endpoint = node, error = apiResponse.error() debug ErrorMessage, endpoint = node, error = apiResponse.error()