Skip to content

Commit 29b29e1

Browse files
authored
Use the new strict Json flavors mechanism for RestJson (#5674)
This requires all object types to be explicitly white-listed for default serialization. The PR makes the minimal changes, although a number of similar mechanisms in eth2_rest_serialization can now be removed.
1 parent f125a5c commit 29b29e1

File tree

7 files changed

+245
-34
lines changed

7 files changed

+245
-34
lines changed

beacon_chain/el/el_manager.nim

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ type
9696
Eth1BlockNumber* = uint64
9797
Eth1BlockTimestamp* = uint64
9898

99-
Eth1Block* = ref object
99+
Eth1BlockObj* = object
100100
hash*: Eth2Digest
101101
number*: Eth1BlockNumber
102102
timestamp*: Eth1BlockTimestamp
@@ -111,6 +111,8 @@ type
111111
## Global deposits count and hash tree root of the entire sequence
112112
## These are computed when the block is added to the chain (see `addBlock`)
113113

114+
Eth1Block* = ref Eth1BlockObj
115+
114116
Eth1Chain* = object
115117
db: BeaconChainDB
116118
cfg: RuntimeConfig

beacon_chain/rpc/rest_nimbus_api.nim

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ type
104104
peerId*: PeerId
105105
connected*: bool
106106

107+
RestJson.useDefaultSerializationFor(
108+
BlockProposalEth1Data,
109+
Eth1BlockObj,
110+
RestChronosMetricsInfo,
111+
RestConnectionInfo,
112+
RestFutureInfo,
113+
RestPeerInfo,
114+
RestPeerInfoTuple,
115+
RestPeerStats,
116+
RestPeerStatus,
117+
RestPubSubPeer,
118+
RestSimplePeer,
119+
)
120+
107121
proc toInfo(node: BeaconNode, peerId: PeerId): RestPeerInfo =
108122
RestPeerInfo(
109123
peerId: $peerId,

beacon_chain/rpc/rest_node_api.nim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ type
2828
connected*: uint64
2929
disconnecting*: uint64
3030

31+
RestJson.useDefaultSerializationFor(
32+
RestNodePeerCount,
33+
)
34+
3135
proc validateState(states: seq[PeerStateKind]): Result[ConnectionStateSet,
3236
cstring] =
3337
var res: set[ConnectionState]

beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim

Lines changed: 217 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
import std/[typetraits, strutils]
1111
import stew/[assign2, results, base10, byteutils, endians2], presto/common,
1212
libp2p/peerid, serialization, json_serialization,
13-
json_serialization/std/[net, sets], stint,
14-
chronicles
13+
json_serialization/std/[net, sets],
14+
json_serialization/stew/results as jsonSerializationResults,
15+
stint, chronicles
1516
import ".."/[eth2_ssz_serialization, forks, keystore],
1617
".."/../consensus_object_pools/block_pools_types,
1718
".."/datatypes/[phase0, altair, bellatrix],
@@ -25,7 +26,8 @@ from ".."/datatypes/deneb import BeaconState
2526

2627
export
2728
eth2_ssz_serialization, results, peerid, common, serialization, chronicles,
28-
json_serialization, net, sets, rest_types, slashing_protection_common
29+
json_serialization, net, sets, rest_types, slashing_protection_common,
30+
jsonSerializationResults
2931

3032
from web3/primitives import BlockHash
3133
export primitives.BlockHash
@@ -36,7 +38,218 @@ func decodeMediaType*(
3638
return err("Missing or incorrect Content-Type")
3739
ok contentType.get.mediaType
3840

39-
Json.createFlavor RestJson
41+
type
42+
EmptyBody* = object
43+
44+
createJsonFlavor RestJson
45+
46+
RestJson.useDefaultSerializationFor(
47+
AggregateAndProof,
48+
Attestation,
49+
AttestationData,
50+
AttesterSlashing,
51+
BLSToExecutionChange,
52+
BeaconBlockHeader,
53+
BlobSidecar,
54+
BlobsBundle,
55+
Checkpoint,
56+
ContributionAndProof,
57+
DataEnclosedObject,
58+
DataMetaEnclosedObject,
59+
DataOptimisticAndFinalizedObject,
60+
DataOptimisticObject,
61+
DataRootEnclosedObject,
62+
DataVersionEnclosedObject,
63+
DeleteKeystoresBody,
64+
DeleteKeystoresResponse,
65+
DeleteRemoteKeystoresResponse,
66+
DenebSignedBlockContents,
67+
Deposit,
68+
DepositData,
69+
DistributedKeystoreInfo,
70+
EmptyBody,
71+
Eth1Data,
72+
EventBeaconBlockObject,
73+
ExecutionPayloadAndBlobsBundle,
74+
Fork,
75+
GetBlockAttestationsResponse,
76+
GetBlockHeaderResponse,
77+
GetBlockHeadersResponse,
78+
GetDepositContractResponse,
79+
GetDepositSnapshotResponse,
80+
GetDistributedKeystoresResponse,
81+
GetEpochCommitteesResponse,
82+
GetEpochSyncCommitteesResponse,
83+
GetForkChoiceResponse,
84+
GetForkScheduleResponse,
85+
GetGenesisResponse,
86+
GetHeaderResponseCapella,
87+
GetHeaderResponseDeneb,
88+
GetKeystoresResponse,
89+
GetNextWithdrawalsResponse,
90+
GetPoolAttesterSlashingsResponse,
91+
GetPoolProposerSlashingsResponse,
92+
GetPoolVoluntaryExitsResponse,
93+
GetRemoteKeystoresResponse,
94+
GetSpecVCResponse,
95+
GetStateFinalityCheckpointsResponse,
96+
GetStateForkResponse,
97+
GetStateRandaoResponse,
98+
GetStateRootResponse,
99+
GetStateValidatorBalancesResponse,
100+
GetStateValidatorResponse,
101+
GetStateValidatorsResponse,
102+
GetValidatorGasLimitResponse,
103+
HistoricalSummary,
104+
ImportDistributedKeystoresBody,
105+
ImportRemoteKeystoresBody,
106+
IndexedAttestation,
107+
KeymanagerGenericError,
108+
KeystoreInfo,
109+
ListFeeRecipientResponse,
110+
ListGasLimitResponse,
111+
PendingAttestation,
112+
PostKeystoresResponse,
113+
PrepareBeaconProposer,
114+
ProposerSlashing,
115+
RemoteKeystoreInfo,
116+
RemoteSignerInfo,
117+
RequestItemStatus,
118+
RestAttesterDuty,
119+
RestBeaconCommitteeSelection,
120+
RestBeaconStatesCommittees,
121+
RestBeaconStatesFinalityCheckpoints,
122+
RestBlockHeader,
123+
RestBlockHeaderInfo,
124+
RestCommitteeSubscription,
125+
RestContributionAndProof,
126+
RestDepositContract,
127+
RestDepositSnapshot,
128+
RestEpochRandao,
129+
RestEpochSyncCommittee,
130+
RestExecutionPayload,
131+
RestExtraData,
132+
RestGenesis,
133+
RestIndexedErrorMessage,
134+
RestIndexedErrorMessageItem,
135+
RestMetadata,
136+
RestNetworkIdentity,
137+
RestNimbusTimestamp1,
138+
RestNimbusTimestamp2,
139+
RestNode,
140+
RestNodeExtraData,
141+
RestNodePeer,
142+
RestNodeVersion,
143+
RestPeerCount,
144+
RestProposerDuty,
145+
RestRoot,
146+
RestSignedBlockHeader,
147+
RestSignedContributionAndProof,
148+
RestSyncCommitteeContribution,
149+
RestSyncCommitteeDuty,
150+
RestSyncCommitteeMessage,
151+
RestSyncCommitteeSelection,
152+
RestSyncCommitteeSubscription,
153+
RestSyncInfo,
154+
RestValidator,
155+
RestValidatorBalance,
156+
SPDIR,
157+
SPDIR_Meta,
158+
SPDIR_SignedAttestation,
159+
SPDIR_SignedBlock,
160+
SPDIR_Validator,
161+
SetFeeRecipientRequest,
162+
SetGasLimitRequest,
163+
SignedAggregateAndProof,
164+
SignedBLSToExecutionChange,
165+
SignedBeaconBlockHeader,
166+
SignedContributionAndProof,
167+
SignedValidatorRegistrationV1,
168+
SignedVoluntaryExit,
169+
SubmitBlindedBlockResponseCapella,
170+
SubmitBlindedBlockResponseDeneb,
171+
SyncAggregate,
172+
SyncAggregatorSelectionData,
173+
SyncCommittee,
174+
SyncCommitteeContribution,
175+
SyncCommitteeMessage,
176+
TrustedAttestation,
177+
Validator,
178+
ValidatorRegistrationV1,
179+
VoluntaryExit,
180+
Web3SignerAggregationSlotData,
181+
Web3SignerDepositData,
182+
Web3SignerErrorResponse,
183+
Web3SignerForkInfo,
184+
Web3SignerMerkleProof,
185+
Web3SignerRandaoRevealData,
186+
Web3SignerSignatureResponse,
187+
Web3SignerStatusResponse,
188+
Web3SignerSyncCommitteeMessageData,
189+
Web3SignerValidatorRegistration,
190+
Withdrawal,
191+
altair.BeaconBlock,
192+
altair.BeaconBlockBody,
193+
altair.BeaconState,
194+
altair.LightClientBootstrap,
195+
altair.LightClientFinalityUpdate,
196+
altair.LightClientHeader,
197+
altair.LightClientOptimisticUpdate,
198+
altair.LightClientUpdate,
199+
altair.SignedBeaconBlock,
200+
bellatrix.BeaconBlock,
201+
bellatrix.BeaconBlockBody,
202+
bellatrix.BeaconState,
203+
bellatrix.ExecutionPayload,
204+
bellatrix.ExecutionPayloadHeader,
205+
bellatrix.SignedBeaconBlock,
206+
bellatrix_mev.BlindedBeaconBlock,
207+
bellatrix_mev.SignedBlindedBeaconBlock,
208+
capella.BeaconBlock,
209+
capella.BeaconBlockBody,
210+
capella.BeaconState,
211+
capella.ExecutionPayload,
212+
capella.ExecutionPayloadHeader,
213+
capella.LightClientBootstrap,
214+
capella.LightClientFinalityUpdate,
215+
capella.LightClientHeader,
216+
capella.LightClientOptimisticUpdate,
217+
capella.LightClientUpdate,
218+
capella.SignedBeaconBlock,
219+
capella_mev.BlindedBeaconBlock,
220+
capella_mev.BlindedBeaconBlockBody,
221+
capella_mev.BuilderBid,
222+
capella_mev.SignedBlindedBeaconBlock,
223+
capella_mev.SignedBuilderBid,
224+
deneb.BeaconBlock,
225+
deneb.BeaconBlockBody,
226+
deneb.BeaconState,
227+
deneb.BlockContents,
228+
deneb.ExecutionPayload,
229+
deneb.ExecutionPayloadHeader,
230+
deneb.LightClientBootstrap,
231+
deneb.LightClientFinalityUpdate,
232+
deneb.LightClientHeader,
233+
deneb.LightClientOptimisticUpdate,
234+
deneb.LightClientUpdate,
235+
deneb.SignedBeaconBlock,
236+
deneb_mev.BlindedBeaconBlock,
237+
deneb_mev.BlindedBeaconBlockBody,
238+
deneb_mev.BuilderBid,
239+
deneb_mev.SignedBlindedBeaconBlock,
240+
deneb_mev.SignedBuilderBid,
241+
phase0.BeaconBlock,
242+
phase0.BeaconBlockBody,
243+
phase0.BeaconState,
244+
phase0.SignedBeaconBlock,
245+
)
246+
247+
# TODO
248+
# Tuples are widely used in the responses of the REST server
249+
# If we switch to concrete types there, it would be possible
250+
# to remove this overly generic definition.
251+
template writeValue*(w: JsonWriter[RestJson], value: tuple) =
252+
writeRecordValue(w, value)
40253

41254
## The RestJson format implements JSON serialization in the way specified
42255
## by the Beacon API:
@@ -84,8 +297,6 @@ const
84297
UnexpectedDecodeError = "Unexpected decoding error"
85298

86299
type
87-
EmptyBody* = object
88-
89300
EncodeTypes* =
90301
AttesterSlashing |
91302
DeleteKeystoresBody |
@@ -3087,37 +3298,12 @@ proc writeValue*(
30873298
writer.writeField("execution_optimistic", value.optimistic.get())
30883299
writer.endRecord()
30893300

3090-
## EventBeaconBlockObject
3091-
proc writeValue*(
3092-
writer: var JsonWriter[RestJson], value: EventBeaconBlockObject
3093-
) {.raises: [IOError].} =
3094-
writer.beginRecord()
3095-
writer.writeField("slot", value.slot)
3096-
writer.writeField("block", value.block_root)
3097-
if value.optimistic.isSome():
3098-
writer.writeField("execution_optimistic", value.optimistic.get())
3099-
writer.endRecord()
3100-
31013301
## RestNodeValidity
31023302
proc writeValue*(
31033303
writer: var JsonWriter[RestJson], value: RestNodeValidity
31043304
) {.raises: [IOError].} =
31053305
writer.writeValue($value)
31063306

3107-
## RestSyncInfo
3108-
proc writeValue*(
3109-
writer: var JsonWriter[RestJson], value: RestSyncInfo
3110-
) {.raises: [IOError].} =
3111-
writer.beginRecord()
3112-
writer.writeField("head_slot", value.head_slot)
3113-
writer.writeField("sync_distance", value.sync_distance)
3114-
writer.writeField("is_syncing", value.is_syncing)
3115-
if value.is_optimistic.isSome():
3116-
writer.writeField("is_optimistic", value.is_optimistic.get())
3117-
if value.el_offline.isSome():
3118-
writer.writeField("el_offline", value.el_offline.get())
3119-
writer.endRecord()
3120-
31213307
## RestErrorMessage
31223308
proc readValue*(reader: var JsonReader[RestJson],
31233309
value: var RestErrorMessage) {.

tests/test_validator_client.nim

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ type
316316
SyncCommitteeBitsObject = object
317317
data: SyncCommitteeAggregationBits
318318

319+
RestJson.useDefaultSerializationFor(
320+
AttestationBitsObject,
321+
SyncCommitteeBitsObject
322+
)
323+
319324
const
320325
AttestationDataVectors = [
321326
# Attestation score with block monitoring enabled (perfect).

0 commit comments

Comments
 (0)