@lodestar/beacon-node 1.48.0-dev.fd70e5fc15 → 1.48.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +4 -4
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
  5. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  6. package/lib/chain/archiveStore/archiveStore.js +1 -0
  7. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  8. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  9. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  10. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  11. package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
  12. package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
  13. package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
  14. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  15. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  16. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  17. package/lib/chain/archiveStore/historicalState/worker.js +4 -1
  18. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  19. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  20. package/lib/chain/archiveStore/utils/archiveBlocks.js +31 -34
  21. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  22. package/lib/chain/blocks/index.d.ts.map +1 -1
  23. package/lib/chain/blocks/index.js +3 -2
  24. package/lib/chain/blocks/index.js.map +1 -1
  25. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  26. package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
  27. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  28. package/lib/chain/chain.d.ts +4 -3
  29. package/lib/chain/chain.d.ts.map +1 -1
  30. package/lib/chain/chain.js +60 -35
  31. package/lib/chain/chain.js.map +1 -1
  32. package/lib/chain/errors/blockError.d.ts +16 -2
  33. package/lib/chain/errors/blockError.d.ts.map +1 -1
  34. package/lib/chain/errors/blockError.js.map +1 -1
  35. package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
  36. package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
  37. package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
  38. package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -0
  39. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  40. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  41. package/lib/chain/interface.d.ts +2 -2
  42. package/lib/chain/interface.d.ts.map +1 -1
  43. package/lib/chain/prepareNextSlot.js +13 -13
  44. package/lib/chain/prepareNextSlot.js.map +1 -1
  45. package/lib/chain/validation/block.d.ts.map +1 -1
  46. package/lib/chain/validation/block.js +26 -4
  47. package/lib/chain/validation/block.js.map +1 -1
  48. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  49. package/lib/chain/validation/dataColumnSidecar.js +38 -13
  50. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  51. package/lib/chain/validation/executionPayloadEnvelope.js +10 -0
  52. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  53. package/lib/db/beacon.d.ts +14 -5
  54. package/lib/db/beacon.d.ts.map +1 -1
  55. package/lib/db/beacon.js +17 -3
  56. package/lib/db/beacon.js.map +1 -1
  57. package/lib/db/dataColumnStore.d.ts +39 -0
  58. package/lib/db/dataColumnStore.d.ts.map +1 -0
  59. package/lib/db/dataColumnStore.js +81 -0
  60. package/lib/db/dataColumnStore.js.map +1 -0
  61. package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
  62. package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
  63. package/lib/db/flatFileStore/atomicWrite.js +61 -0
  64. package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
  65. package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
  66. package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
  67. package/lib/db/flatFileStore/dcolFormat.js +286 -0
  68. package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
  69. package/lib/db/flatFileStore/errors.d.ts +82 -0
  70. package/lib/db/flatFileStore/errors.d.ts.map +1 -0
  71. package/lib/db/flatFileStore/errors.js +32 -0
  72. package/lib/db/flatFileStore/errors.js.map +1 -0
  73. package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
  74. package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
  75. package/lib/db/flatFileStore/flatFileStore.js +251 -0
  76. package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
  77. package/lib/db/flatFileStore/index.d.ts +4 -0
  78. package/lib/db/flatFileStore/index.d.ts.map +1 -0
  79. package/lib/db/flatFileStore/index.js +2 -0
  80. package/lib/db/flatFileStore/index.js.map +1 -0
  81. package/lib/db/flatFileStore/interface.d.ts +25 -0
  82. package/lib/db/flatFileStore/interface.d.ts.map +1 -0
  83. package/lib/db/flatFileStore/interface.js +2 -0
  84. package/lib/db/flatFileStore/interface.js.map +1 -0
  85. package/lib/db/flatFileStore/metrics.d.ts +24 -0
  86. package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
  87. package/lib/db/flatFileStore/metrics.js +25 -0
  88. package/lib/db/flatFileStore/metrics.js.map +1 -0
  89. package/lib/db/flatFileStore/path.d.ts +9 -0
  90. package/lib/db/flatFileStore/path.d.ts.map +1 -0
  91. package/lib/db/flatFileStore/path.js +21 -0
  92. package/lib/db/flatFileStore/path.js.map +1 -0
  93. package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
  94. package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
  95. package/lib/db/flatFileStore/slotIndex.js +46 -0
  96. package/lib/db/flatFileStore/slotIndex.js.map +1 -0
  97. package/lib/db/flatFileStore/snappy.d.ts +3 -0
  98. package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
  99. package/lib/db/flatFileStore/snappy.js +12 -0
  100. package/lib/db/flatFileStore/snappy.js.map +1 -0
  101. package/lib/db/index.d.ts +1 -0
  102. package/lib/db/index.d.ts.map +1 -1
  103. package/lib/db/interface.d.ts +8 -1
  104. package/lib/db/interface.d.ts.map +1 -1
  105. package/lib/db/repositories/blockArchive.d.ts +8 -1
  106. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  107. package/lib/db/repositories/blockArchive.js +65 -28
  108. package/lib/db/repositories/blockArchive.js.map +1 -1
  109. package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
  110. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  111. package/lib/db/repositories/blockArchiveIndex.js +3 -7
  112. package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
  113. package/lib/metrics/metrics/lodestar.d.ts +18 -0
  114. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  115. package/lib/metrics/metrics/lodestar.js +55 -1
  116. package/lib/metrics/metrics/lodestar.js.map +1 -1
  117. package/lib/monitoring/clientStats.js +1 -1
  118. package/lib/monitoring/clientStats.js.map +1 -1
  119. package/lib/network/gossip/encoding.d.ts.map +1 -1
  120. package/lib/network/gossip/encoding.js +0 -7
  121. package/lib/network/gossip/encoding.js.map +1 -1
  122. package/lib/network/gossip/topic.d.ts +2 -1
  123. package/lib/network/gossip/topic.d.ts.map +1 -1
  124. package/lib/network/gossip/topic.js +4 -20
  125. package/lib/network/gossip/topic.js.map +1 -1
  126. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  127. package/lib/network/processor/gossipHandlers.js +6 -7
  128. package/lib/network/processor/gossipHandlers.js.map +1 -1
  129. package/lib/network/processor/index.d.ts +49 -3
  130. package/lib/network/processor/index.d.ts.map +1 -1
  131. package/lib/network/processor/index.js +232 -98
  132. package/lib/network/processor/index.js.map +1 -1
  133. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  134. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
  135. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  136. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
  137. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
  138. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  139. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  140. package/lib/network/reqresp/protocols.js +6 -22
  141. package/lib/network/reqresp/protocols.js.map +1 -1
  142. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
  143. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  144. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
  145. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  146. package/lib/node/nodejs.d.ts +2 -1
  147. package/lib/node/nodejs.d.ts.map +1 -1
  148. package/lib/node/nodejs.js +4 -2
  149. package/lib/node/nodejs.js.map +1 -1
  150. package/lib/util/sszBytes.d.ts +6 -0
  151. package/lib/util/sszBytes.d.ts.map +1 -1
  152. package/lib/util/sszBytes.js +1 -1
  153. package/lib/util/sszBytes.js.map +1 -1
  154. package/package.json +17 -18
  155. package/src/api/impl/beacon/blocks/index.ts +8 -4
  156. package/src/chain/archiveStore/archiveStore.ts +6 -1
  157. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
  158. package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
  159. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  160. package/src/chain/archiveStore/historicalState/worker.ts +4 -1
  161. package/src/chain/archiveStore/utils/archiveBlocks.ts +34 -39
  162. package/src/chain/blocks/index.ts +13 -2
  163. package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
  164. package/src/chain/chain.ts +75 -34
  165. package/src/chain/errors/blockError.ts +20 -8
  166. package/src/chain/errors/dataColumnSidecarError.ts +24 -8
  167. package/src/chain/errors/executionPayloadEnvelope.ts +14 -2
  168. package/src/chain/interface.ts +2 -2
  169. package/src/chain/prepareNextSlot.ts +16 -16
  170. package/src/chain/validation/block.ts +26 -4
  171. package/src/chain/validation/dataColumnSidecar.ts +47 -14
  172. package/src/chain/validation/executionPayloadEnvelope.ts +10 -0
  173. package/src/db/beacon.ts +33 -6
  174. package/src/db/dataColumnStore.ts +113 -0
  175. package/src/db/flatFileStore/atomicWrite.ts +65 -0
  176. package/src/db/flatFileStore/dcolFormat.ts +389 -0
  177. package/src/db/flatFileStore/errors.ts +53 -0
  178. package/src/db/flatFileStore/flatFileStore.ts +310 -0
  179. package/src/db/flatFileStore/index.ts +3 -0
  180. package/src/db/flatFileStore/interface.ts +21 -0
  181. package/src/db/flatFileStore/metrics.ts +48 -0
  182. package/src/db/flatFileStore/path.ts +32 -0
  183. package/src/db/flatFileStore/slotIndex.ts +56 -0
  184. package/src/db/flatFileStore/snappy.ts +14 -0
  185. package/src/db/index.ts +1 -0
  186. package/src/db/interface.ts +9 -1
  187. package/src/db/repositories/blockArchive.ts +89 -30
  188. package/src/db/repositories/blockArchiveIndex.ts +4 -9
  189. package/src/metrics/metrics/lodestar.ts +57 -1
  190. package/src/monitoring/clientStats.ts +1 -1
  191. package/src/network/gossip/encoding.ts +0 -7
  192. package/src/network/gossip/topic.ts +3 -25
  193. package/src/network/processor/gossipHandlers.ts +11 -11
  194. package/src/network/processor/index.ts +263 -148
  195. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
  196. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
  197. package/src/network/reqresp/protocols.ts +7 -24
  198. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
  199. package/src/node/nodejs.ts +6 -1
  200. package/src/util/sszBytes.ts +1 -1
@@ -209,8 +209,19 @@ export async function processBlocks(
209
209
  const blockSlot = signedBlock.message.slot;
210
210
  const {state} = err.type;
211
211
  const forkTypes = this.config.getForkTypes(blockSlot);
212
- this.persistInvalidSszValue(forkTypes.SignedBeaconBlock, signedBlock, `${blockSlot}_invalid_signature`);
213
- this.persistInvalidSszBytes("BeaconState", state.serialize(), `${state.slot}_invalid_signature`);
212
+ const blockRootHex = toRootHex(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message));
213
+ this.persistInvalidSszValue(
214
+ forkTypes.SignedBeaconBlock,
215
+ signedBlock,
216
+ `${blockSlot}_invalid_signature`,
217
+ blockRootHex
218
+ );
219
+ this.persistInvalidSszBytes(
220
+ "BeaconState",
221
+ state.serialize(),
222
+ toRootHex(state.hashTreeRoot()),
223
+ `${state.slot}_invalid_signature`
224
+ );
214
225
  } else if (err.type.code === BlockErrorCode.INVALID_STATE_ROOT) {
215
226
  const {signedBlock} = err;
216
227
  const blockSlot = signedBlock.message.slot;
@@ -1,6 +1,6 @@
1
- import {ForkPostDeneb, isForkPostDeneb} from "@lodestar/params";
1
+ import {ForkPostDeneb, ForkPostFulu, isForkPostDeneb} from "@lodestar/params";
2
2
  import {SignedBeaconBlock} from "@lodestar/types";
3
- import {fromHex, toRootHex} from "@lodestar/utils";
3
+ import {toRootHex} from "@lodestar/utils";
4
4
  import {getBlobKzgCommitments} from "../../util/dataColumns.js";
5
5
  import {BeaconChain} from "../chain.js";
6
6
  import {IBlockInput, IDataColumnsInput, isBlockInputBlobs, isBlockInputColumns} from "./blockInput/index.js";
@@ -76,7 +76,6 @@ async function writeBlockAndBlobsToDb(this: BeaconChain, blockInput: IBlockInput
76
76
  */
77
77
  export async function writeDataColumnsToDb(this: BeaconChain, blockInput: IDataColumnsInput): Promise<void> {
78
78
  const {slot, blockRootHex} = blockInput;
79
- const blockRoot = fromHex(blockRootHex);
80
79
 
81
80
  if (!blockInput.hasComputedAllData()) {
82
81
  // Supernodes may only have a subset of the data columns by the time the block begins to be imported
@@ -89,25 +88,19 @@ export async function writeDataColumnsToDb(this: BeaconChain, blockInput: IDataC
89
88
 
90
89
  const {custodyColumns} = this.custodyConfig;
91
90
  const dataColumnSidecars = blockInput.getCustodyColumns();
91
+ const dataColumnSidecarType = this.config.getForkTypes<ForkPostFulu>(slot).DataColumnSidecar;
92
92
 
93
- const binaryPuts: {key: number; value: Uint8Array}[] = [];
94
- const nonbinaryPuts = [];
93
+ const binaryColumns: {index: number; data: Uint8Array}[] = [];
95
94
  for (const dataColumnSidecar of dataColumnSidecars) {
96
- // skip reserializing column if we already have it
97
95
  const serialized = this.serializedCache.get(dataColumnSidecar);
98
- if (serialized) {
99
- binaryPuts.push({key: dataColumnSidecar.index, value: serialized});
100
- } else {
101
- nonbinaryPuts.push(dataColumnSidecar);
102
- }
96
+ binaryColumns.push({
97
+ index: dataColumnSidecar.index,
98
+ data: serialized ?? dataColumnSidecarType.serialize(dataColumnSidecar),
99
+ });
103
100
  }
101
+ await this.db.dataColumns.putManyBinary({slot, blockRoot: blockRootHex}, binaryColumns);
104
102
 
105
- await Promise.all([
106
- this.db.dataColumnSidecar.putManyBinary(blockRoot, binaryPuts),
107
- this.db.dataColumnSidecar.putMany(blockRoot, nonbinaryPuts),
108
- ]);
109
-
110
- this.logger.debug("Persisted dataColumnSidecars to hot DB", {
103
+ this.logger.debug("Persisted dataColumnSidecars", {
111
104
  slot,
112
105
  root: blockRootHex,
113
106
  dataColumnSidecars: dataColumnSidecars.length,
@@ -268,6 +268,7 @@ export class BeaconChain implements IBeaconChain {
268
268
  db,
269
269
  dbName,
270
270
  dataDir,
271
+ dataColumnDir,
271
272
  logger,
272
273
  processShutdownCallback,
273
274
  clock,
@@ -285,6 +286,7 @@ export class BeaconChain implements IBeaconChain {
285
286
  db: IBeaconDb;
286
287
  dbName: string;
287
288
  dataDir: string;
289
+ dataColumnDir?: string;
288
290
  logger: Logger;
289
291
  processShutdownCallback: ProcessShutdownCallback;
290
292
  /** Used for testing to supply fake clock */
@@ -505,7 +507,12 @@ export class BeaconChain implements IBeaconChain {
505
507
 
506
508
  this.archiveStore = new ArchiveStore(
507
509
  {db, chain: this, logger: logger as LoggerNode, metrics},
508
- {...opts, dbName, anchorState: {finalizedCheckpoint: anchorState.finalizedCheckpoint}},
510
+ {
511
+ ...opts,
512
+ dbName,
513
+ dataColumnDir: dataColumnDir ?? path.join(dataDir, "data_columns"),
514
+ anchorState: {finalizedCheckpoint: anchorState.finalizedCheckpoint},
515
+ },
509
516
  signal
510
517
  );
511
518
 
@@ -969,12 +976,15 @@ export class BeaconChain implements IBeaconChain {
969
976
 
970
977
  async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]> {
971
978
  const fork = this.config.getForkName(blockSlot);
979
+ const sidecarsByIndex = new Map<number, DataColumnSidecar>();
972
980
 
973
981
  if (isForkPostGloas(fork)) {
974
982
  // After gloas, columns are tracked in PayloadEnvelopeInput
975
983
  const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
976
984
  if (payloadInput) {
977
- return payloadInput.getAllColumns();
985
+ for (const sidecar of payloadInput.getAllColumns()) {
986
+ sidecarsByIndex.set(sidecar.index, sidecar);
987
+ }
978
988
  }
979
989
  } else {
980
990
  // Before gloas, columns are tracked in BlockInput
@@ -983,16 +993,17 @@ export class BeaconChain implements IBeaconChain {
983
993
  if (!isBlockInputColumns(blockInput)) {
984
994
  throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
985
995
  }
986
- return blockInput.getAllColumns();
996
+ for (const sidecar of blockInput.getAllColumns()) {
997
+ sidecarsByIndex.set(sidecar.index, sidecar);
998
+ }
987
999
  }
988
1000
  }
989
1001
 
990
- const sidecarsUnfinalized = await this.db.dataColumnSidecar.values(fromHex(blockRootHex));
991
- if (sidecarsUnfinalized.length > 0) {
992
- return sidecarsUnfinalized;
1002
+ for (const sidecar of await this.db.dataColumns.getAll({slot: blockSlot, blockRoot: blockRootHex})) {
1003
+ if (!sidecarsByIndex.has(sidecar.index)) sidecarsByIndex.set(sidecar.index, sidecar);
993
1004
  }
994
- const sidecarsFinalized = await this.db.dataColumnSidecarArchive.values(blockSlot);
995
- return sidecarsFinalized;
1005
+
1006
+ return [...sidecarsByIndex.values()].sort((a, b) => a.index - b.index);
996
1007
  }
997
1008
 
998
1009
  async getSerializedDataColumnSidecars(
@@ -1001,22 +1012,25 @@ export class BeaconChain implements IBeaconChain {
1001
1012
  indices: number[]
1002
1013
  ): Promise<(Uint8Array | undefined)[]> {
1003
1014
  const fork = this.config.getForkName(blockSlot);
1015
+ const dataColumnSidecars: (Uint8Array | undefined)[] = indices.map(() => undefined);
1004
1016
 
1005
1017
  if (isForkPostGloas(fork)) {
1006
1018
  // After gloas, columns are tracked in PayloadEnvelopeInput
1007
1019
  const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
1008
1020
  if (payloadInput) {
1009
- return indices.map((index) => {
1021
+ for (let i = 0; i < indices.length; i++) {
1022
+ const index = indices[i];
1010
1023
  const sidecar = payloadInput.getColumn(index);
1011
1024
  if (!sidecar) {
1012
- return undefined;
1025
+ continue;
1013
1026
  }
1014
1027
  const serialized = this.serializedCache.get(sidecar);
1015
1028
  if (serialized) {
1016
- return serialized;
1029
+ dataColumnSidecars[i] = serialized;
1030
+ } else {
1031
+ dataColumnSidecars[i] = sszTypesFor(fork as ForkPostGloas).DataColumnSidecar.serialize(sidecar);
1017
1032
  }
1018
- return sszTypesFor(fork as ForkPostGloas).DataColumnSidecar.serialize(sidecar);
1019
- });
1033
+ }
1020
1034
  }
1021
1035
  } else {
1022
1036
  // Before gloas, columns are tracked in BlockInput
@@ -1025,26 +1039,42 @@ export class BeaconChain implements IBeaconChain {
1025
1039
  if (!isBlockInputColumns(blockInput)) {
1026
1040
  throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
1027
1041
  }
1028
- return indices.map((index) => {
1042
+ for (let i = 0; i < indices.length; i++) {
1043
+ const index = indices[i];
1029
1044
  const sidecar = blockInput.getColumn(index);
1030
1045
  if (!sidecar) {
1031
- return undefined;
1046
+ continue;
1032
1047
  }
1033
1048
  const serialized = this.serializedCache.get(sidecar);
1034
1049
  if (serialized) {
1035
- return serialized;
1050
+ dataColumnSidecars[i] = serialized;
1051
+ } else {
1052
+ dataColumnSidecars[i] = sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(
1053
+ sidecar
1054
+ );
1036
1055
  }
1037
- return sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(sidecar);
1038
- });
1056
+ }
1039
1057
  }
1040
1058
  }
1041
1059
 
1042
- const sidecarsUnfinalized = await this.db.dataColumnSidecar.getManyBinary(fromHex(blockRootHex), indices);
1043
- if (sidecarsUnfinalized.some((sidecar) => sidecar != null)) {
1044
- return sidecarsUnfinalized;
1060
+ const missingPositions = dataColumnSidecars
1061
+ .map((sidecar, position) => (sidecar === undefined ? position : -1))
1062
+ .filter((position) => position !== -1);
1063
+
1064
+ if (missingPositions.length > 0) {
1065
+ const persistedSidecars = await this.db.dataColumns.getManyBinary(
1066
+ {slot: blockSlot, blockRoot: blockRootHex},
1067
+ missingPositions.map((position) => indices[position])
1068
+ );
1069
+ for (let i = 0; i < missingPositions.length; i++) {
1070
+ const sidecar = persistedSidecars[i];
1071
+ if (sidecar !== undefined) {
1072
+ dataColumnSidecars[missingPositions[i]] = sidecar;
1073
+ }
1074
+ }
1045
1075
  }
1046
- const sidecarsFinalized = await this.db.dataColumnSidecarArchive.getManyBinary(blockSlot, indices);
1047
- return sidecarsFinalized;
1076
+
1077
+ return dataColumnSidecars;
1048
1078
  }
1049
1079
 
1050
1080
  async produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody> {
@@ -1387,10 +1417,15 @@ export class BeaconChain implements IBeaconChain {
1387
1417
  const slot = data.slot;
1388
1418
  if (isBlindedBeaconBlock(data)) {
1389
1419
  const sszType = this.config.getPostBellatrixForkTypes(slot).BlindedBeaconBlock;
1390
- void this.persistSszObject("BlindedBeaconBlock", sszType.serialize(data), sszType.hashTreeRoot(data), suffix);
1420
+ void this.persistSszObject(
1421
+ "BlindedBeaconBlock",
1422
+ sszType.serialize(data),
1423
+ toRootHex(sszType.hashTreeRoot(data)),
1424
+ suffix
1425
+ );
1391
1426
  } else {
1392
1427
  const sszType = this.config.getForkTypes(slot).BeaconBlock;
1393
- void this.persistSszObject("BeaconBlock", sszType.serialize(data), sszType.hashTreeRoot(data), suffix);
1428
+ void this.persistSszObject("BeaconBlock", sszType.serialize(data), toRootHex(sszType.hashTreeRoot(data)), suffix);
1394
1429
  }
1395
1430
  }
1396
1431
 
@@ -1411,33 +1446,39 @@ export class BeaconChain implements IBeaconChain {
1411
1446
  this.persistSszObject(
1412
1447
  `SignedBeaconBlock_slot_${blockSlot}`,
1413
1448
  blockType.serialize(block),
1414
- blockType.hashTreeRoot(block),
1449
+ toRootHex(this.config.getForkTypes(blockSlot).BeaconBlock.hashTreeRoot(block.message)),
1415
1450
  `${logStr}_block`
1416
1451
  ),
1417
1452
  this.persistSszObject(
1418
1453
  `preState_slot_${preState.slot}_BeaconState`,
1419
1454
  preState.serialize(),
1420
- preState.hashTreeRoot(),
1455
+ toRootHex(preState.hashTreeRoot()),
1421
1456
  `${logStr}_pre_state`
1422
1457
  ),
1423
1458
  this.persistSszObject(
1424
1459
  `postState_slot_${postState.slot}_BeaconState`,
1425
1460
  postState.serialize(),
1426
- postState.hashTreeRoot(),
1461
+ toRootHex(postStateRoot),
1427
1462
  `${logStr}_post_state`
1428
1463
  ),
1429
1464
  ]);
1430
1465
  }
1431
1466
 
1432
- persistInvalidSszValue<T>(type: Type<T>, sszObject: T, suffix?: string): void {
1467
+ persistInvalidSszValue<T>(type: Type<T>, sszObject: T, suffix?: string, rootHex?: RootHex): void {
1433
1468
  if (this.opts.persistInvalidSszObjects) {
1434
- void this.persistSszObject(type.typeName, type.serialize(sszObject), type.hashTreeRoot(sszObject), suffix);
1469
+ void this.persistSszObject(
1470
+ type.typeName,
1471
+ type.serialize(sszObject),
1472
+ // in SignedBeaconBlock case, we want to use BeaconBlock root instead
1473
+ rootHex ?? toRootHex(type.hashTreeRoot(sszObject)),
1474
+ suffix
1475
+ );
1435
1476
  }
1436
1477
  }
1437
1478
 
1438
- persistInvalidSszBytes(typeName: string, sszBytes: Uint8Array, suffix?: string): void {
1479
+ persistInvalidSszBytes(typeName: string, sszBytes: Uint8Array, rootHex: RootHex, suffix?: string): void {
1439
1480
  if (this.opts.persistInvalidSszObjects) {
1440
- void this.persistSszObject(typeName, sszBytes, sszBytes, suffix);
1481
+ void this.persistSszObject(typeName, sszBytes, rootHex, suffix);
1441
1482
  }
1442
1483
  }
1443
1484
 
@@ -1568,14 +1609,14 @@ export class BeaconChain implements IBeaconChain {
1568
1609
  return {state: blockState, stateId: "block_state_any_epoch", shouldWarn: true};
1569
1610
  }
1570
1611
 
1571
- private async persistSszObject(prefix: string, bytes: Uint8Array, root: Uint8Array, logStr?: string): Promise<void> {
1612
+ private async persistSszObject(prefix: string, bytes: Uint8Array, rootHex: RootHex, logStr?: string): Promise<void> {
1572
1613
  const now = new Date();
1573
1614
  // yyyy-MM-dd
1574
1615
  const dateStr = now.toISOString().split("T")[0];
1575
1616
 
1576
1617
  // by default store to lodestar_archive of current dir
1577
1618
  const dirpath = path.join(this.opts.persistInvalidSszObjectsDir ?? "invalid_ssz_objects", dateStr);
1578
- const filepath = path.join(dirpath, `${prefix}_${toRootHex(root)}.ssz`);
1619
+ const filepath = path.join(dirpath, `${prefix}_${rootHex}.ssz`);
1579
1620
 
1580
1621
  await ensureDir(dirpath);
1581
1622
 
@@ -120,9 +120,9 @@ export type BlockErrorType =
120
120
  | {code: BlockErrorCode.ALREADY_KNOWN; root: RootHex}
121
121
  | {code: BlockErrorCode.REPEAT_PROPOSAL; proposerIndex: ValidatorIndex; root: RootHex}
122
122
  | {code: BlockErrorCode.BLOCK_SLOT_LIMIT_REACHED}
123
- | {code: BlockErrorCode.INCORRECT_PROPOSER; proposerIndex: ValidatorIndex}
124
- | {code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID; blockSlot: Slot}
125
- | {code: BlockErrorCode.UNKNOWN_PROPOSER; proposerIndex: ValidatorIndex}
123
+ | {code: BlockErrorCode.INCORRECT_PROPOSER; slot: Slot; root: RootHex; proposerIndex: ValidatorIndex}
124
+ | {code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID; slot: Slot; root: RootHex}
125
+ | {code: BlockErrorCode.UNKNOWN_PROPOSER; slot: Slot; root: RootHex; proposerIndex: ValidatorIndex}
126
126
  | {code: BlockErrorCode.INVALID_SIGNATURE; state: IBeaconStateView}
127
127
  | {
128
128
  code: BlockErrorCode.INVALID_STATE_ROOT;
@@ -132,7 +132,7 @@ export type BlockErrorType =
132
132
  postState: IBeaconStateView;
133
133
  }
134
134
  | {code: BlockErrorCode.NOT_FINALIZED_DESCENDANT; parentRoot: RootHex}
135
- | {code: BlockErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
135
+ | {code: BlockErrorCode.NOT_LATER_THAN_PARENT; slot: Slot; root: RootHex; parentSlot: Slot}
136
136
  | {code: BlockErrorCode.NON_LINEAR_PARENT_ROOTS}
137
137
  | {code: BlockErrorCode.NON_LINEAR_SLOTS}
138
138
  | {code: BlockErrorCode.ENVELOPE_BLOCK_ROOT_MISMATCH; envelopeBlockRoot: RootHex; blockRoot: RootHex}
@@ -140,7 +140,7 @@ export type BlockErrorType =
140
140
  | {code: BlockErrorCode.BEACON_CHAIN_ERROR; error: Error}
141
141
  | {code: BlockErrorCode.KNOWN_BAD_BLOCK}
142
142
  | {code: BlockErrorCode.BLACKLISTED_BLOCK}
143
- | {code: BlockErrorCode.INCORRECT_TIMESTAMP; timestamp: number; expectedTimestamp: number}
143
+ | {code: BlockErrorCode.INCORRECT_TIMESTAMP; slot: Slot; root: RootHex; timestamp: number; expectedTimestamp: number}
144
144
  | {code: BlockErrorCode.TOO_MUCH_GAS_USED; gasUsed: number; gasLimit: number}
145
145
  | {code: BlockErrorCode.SAME_PARENT_HASH; blockHash: RootHex}
146
146
  | {code: BlockErrorCode.TRANSACTIONS_TOO_BIG; size: number; max: number}
@@ -151,9 +151,21 @@ export type BlockErrorType =
151
151
  errorMessage: string;
152
152
  }
153
153
  | {code: BlockErrorCode.DATA_UNAVAILABLE}
154
- | {code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS; blobKzgCommitmentsLen: number; commitmentLimit: number}
155
- | {code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH; bidParentRoot: RootHex; blockParentRoot: RootHex}
156
- | {code: BlockErrorCode.NON_ZERO_DEPOSITS; count: number}
154
+ | {
155
+ code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS;
156
+ slot: Slot;
157
+ root: RootHex;
158
+ blobKzgCommitmentsLen: number;
159
+ commitmentLimit: number;
160
+ }
161
+ | {
162
+ code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH;
163
+ slot: Slot;
164
+ root: RootHex;
165
+ bidParentRoot: RootHex;
166
+ blockParentRoot: RootHex;
167
+ }
168
+ | {code: BlockErrorCode.NON_ZERO_DEPOSITS; slot: Slot; root: RootHex; count: number}
157
169
  | {code: BlockErrorCode.PARENT_EXECUTION_INVALID; parentRoot: RootHex}
158
170
  | {code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN; parentRoot: RootHex; parentBlockHash: RootHex}
159
171
  | {code: BlockErrorCode.NON_LINEAR_PAYLOAD_ROOTS; parentBlockHash: RootHex; expectedBlockHash: RootHex};
@@ -47,10 +47,12 @@ export enum DataColumnSidecarErrorCode {
47
47
  }
48
48
 
49
49
  export type DataColumnSidecarErrorType =
50
- | {code: DataColumnSidecarErrorCode.INVALID_INDEX; slot: Slot; columnIndex: number}
51
- | {code: DataColumnSidecarErrorCode.NO_COMMITMENTS; slot: Slot; columnIndex: number}
50
+ | {code: DataColumnSidecarErrorCode.INVALID_INDEX; slot: Slot; root: RootHex; columnIndex: number}
51
+ | {code: DataColumnSidecarErrorCode.NO_COMMITMENTS; slot: Slot; root: RootHex; columnIndex: number}
52
52
  | {
53
53
  code: DataColumnSidecarErrorCode.MISMATCHED_LENGTHS;
54
+ slot: Slot;
55
+ root: RootHex;
54
56
  columnLength: number;
55
57
  commitmentsLength: number;
56
58
  proofsLength: number;
@@ -61,10 +63,17 @@ export type DataColumnSidecarErrorType =
61
63
  columnIndex: number;
62
64
  fork: ForkName;
63
65
  }
64
- | {code: DataColumnSidecarErrorCode.INVALID_SUBNET; columnIndex: number; gossipSubnet: SubnetID}
66
+ | {
67
+ code: DataColumnSidecarErrorCode.INVALID_SUBNET;
68
+ slot: Slot;
69
+ root: RootHex;
70
+ columnIndex: number;
71
+ gossipSubnet: SubnetID;
72
+ }
65
73
  | {
66
74
  code: DataColumnSidecarErrorCode.TOO_MANY_KZG_COMMITMENTS;
67
75
  slot: number;
76
+ root: RootHex;
68
77
  columnIndex: number;
69
78
  count: number;
70
79
  limit: number;
@@ -85,12 +94,12 @@ export type DataColumnSidecarErrorType =
85
94
  | {
86
95
  code: DataColumnSidecarErrorCode.PROPOSAL_SIGNATURE_INVALID;
87
96
  slot: Slot;
88
- blockRoot: RootHex;
97
+ root: RootHex;
89
98
  index: number;
90
99
  }
91
- | {code: DataColumnSidecarErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
92
- | {code: DataColumnSidecarErrorCode.INCLUSION_PROOF_INVALID; slot: Slot; columnIndex: number}
93
- | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF; slot: Slot; columnIndex: number}
100
+ | {code: DataColumnSidecarErrorCode.NOT_LATER_THAN_PARENT; slot: Slot; root: RootHex; parentSlot: Slot}
101
+ | {code: DataColumnSidecarErrorCode.INCLUSION_PROOF_INVALID; slot: Slot; root: RootHex; columnIndex: number}
102
+ | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF; slot: Slot; root: RootHex; columnIndex: number}
94
103
  | {code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_COUNT; slot: number; expected: number; actual: number}
95
104
  | {
96
105
  code: DataColumnSidecarErrorCode.INCORRECT_BLOCK;
@@ -106,6 +115,7 @@ export type DataColumnSidecarErrorType =
106
115
  }
107
116
  | {
108
117
  code: DataColumnSidecarErrorCode.INCORRECT_SIDECAR_SLOT;
118
+ root: RootHex;
109
119
  columnIndex: number;
110
120
  expected: Slot;
111
121
  actual: Slot;
@@ -127,7 +137,13 @@ export type DataColumnSidecarErrorType =
127
137
  actual: number;
128
138
  }
129
139
  | {code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF_BATCH; slot: number; reason: string}
130
- | {code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER; actualProposerIndex: number; expectedProposerIndex: number}
140
+ | {
141
+ code: DataColumnSidecarErrorCode.INCORRECT_PROPOSER;
142
+ slot: Slot;
143
+ root: RootHex;
144
+ actualProposerIndex: number;
145
+ expectedProposerIndex: number;
146
+ }
131
147
  | {code: DataColumnSidecarErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; slot: Slot; blockRoot: RootHex};
132
148
 
133
149
  export class DataColumnSidecarGossipError extends GossipActionError<DataColumnSidecarErrorType> {}
@@ -26,23 +26,35 @@ export type ExecutionPayloadEnvelopeErrorType =
26
26
  slot: Slot;
27
27
  }
28
28
  | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_BLOCK; blockRoot: RootHex}
29
- | {code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH; envelopeSlot: Slot; blockSlot: Slot}
29
+ | {
30
+ code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH;
31
+ slot: Slot;
32
+ root: RootHex;
33
+ envelopeSlot: Slot;
34
+ blockSlot: Slot;
35
+ }
30
36
  | {
31
37
  code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH;
38
+ slot: Slot;
39
+ root: RootHex;
32
40
  envelopeBuilderIndex: BuilderIndex;
33
41
  bidBuilderIndex: BuilderIndex | null;
34
42
  }
35
43
  | {
36
44
  code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH;
45
+ slot: Slot;
46
+ root: RootHex;
37
47
  envelopeBlockHash: RootHex;
38
48
  bidBlockHash: RootHex | null;
39
49
  }
40
50
  | {
41
51
  code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH;
52
+ slot: Slot;
53
+ root: RootHex;
42
54
  envelopeRequestsRoot: RootHex;
43
55
  bidRequestsRoot: RootHex;
44
56
  }
45
- | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
57
+ | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE; slot: Slot; root: RootHex}
46
58
  | {code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; blockRoot: RootHex};
47
59
 
48
60
  export class ExecutionPayloadEnvelopeError extends GossipActionError<ExecutionPayloadEnvelopeErrorType> {}
@@ -290,8 +290,8 @@ export interface IBeaconChain {
290
290
  postState: IBeaconStateView,
291
291
  block: SignedBeaconBlock
292
292
  ): Promise<void>;
293
- persistInvalidSszValue<T>(type: Type<T>, sszObject: T | Uint8Array, suffix?: string): void;
294
- persistInvalidSszBytes(type: string, sszBytes: Uint8Array, suffix?: string): void;
293
+ persistInvalidSszValue<T>(type: Type<T>, sszObject: T, suffix?: string, rootHex?: RootHex): void;
294
+ persistInvalidSszBytes(type: string, sszBytes: Uint8Array, rootHex: RootHex, suffix?: string): void;
295
295
  regenStateForAttestationVerification(
296
296
  attEpoch: Epoch,
297
297
  shufflingDependentRoot: RootHex,
@@ -243,6 +243,22 @@ export class PrepareNextSlotScheduler {
243
243
  parentBlockHash = preparedState.latestExecutionPayloadHeader.blockHash;
244
244
  }
245
245
 
246
+ // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
247
+ // every slot. Without the flag, only emit the event if we are proposing in the next slot.
248
+ if (
249
+ (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
250
+ this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
251
+ ) {
252
+ const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
253
+ prepareState: stateAfterParentPayload,
254
+ prepareSlot,
255
+ parentBlockRoot: fromHex(updatedHead.blockRoot),
256
+ parentBlockHash,
257
+ feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
258
+ });
259
+ this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
260
+ }
261
+
246
262
  if (feeRecipient) {
247
263
  const preparationTime =
248
264
  computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
@@ -273,22 +289,6 @@ export class PrepareNextSlotScheduler {
273
289
  }
274
290
 
275
291
  this.computeStateHashTreeRoot(preparedState, isEpochTransition);
276
-
277
- // If emitPayloadAttributes is true emit a SSE payloadAttributes event for
278
- // every slot. Without the flag, only emit the event if we are proposing in the next slot.
279
- if (
280
- (feeRecipient || this.chain.opts.emitPayloadAttributes === true) &&
281
- this.chain.emitter.listenerCount(routes.events.EventType.payloadAttributes)
282
- ) {
283
- const data = getPayloadAttributesForSSE(fork as ForkPostBellatrix, this.chain, {
284
- prepareState: stateAfterParentPayload,
285
- prepareSlot,
286
- parentBlockRoot: fromHex(updatedHead.blockRoot),
287
- parentBlockHash,
288
- feeRecipient: feeRecipient ?? "0x0000000000000000000000000000000000000000",
289
- });
290
- this.chain.emitter.emit(routes.events.EventType.payloadAttributes, {data, version: fork});
291
- }
292
292
  } else {
293
293
  // Pre-bellatrix only reaches here at an epoch transition to precompute the next epoch state
294
294
  const preparedState = await this.chain.regen.getBlockSlotState(
@@ -134,8 +134,9 @@ export async function validateGossipBlock(
134
134
  if (parentBlock.slot >= blockSlot) {
135
135
  throw new BlockGossipError(GossipAction.REJECT, {
136
136
  code: BlockErrorCode.NOT_LATER_THAN_PARENT,
137
- parentSlot: parentBlock.slot,
138
137
  slot: blockSlot,
138
+ root: blockRoot,
139
+ parentSlot: parentBlock.slot,
139
140
  });
140
141
  }
141
142
 
@@ -150,6 +151,8 @@ export async function validateGossipBlock(
150
151
  if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
151
152
  throw new BlockGossipError(GossipAction.REJECT, {
152
153
  code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS,
154
+ slot: blockSlot,
155
+ root: blockRoot,
153
156
  blobKzgCommitmentsLen,
154
157
  commitmentLimit: maxBlobsPerBlock,
155
158
  });
@@ -167,6 +170,8 @@ export async function validateGossipBlock(
167
170
  if (blobKzgCommitmentsLen > maxBlobsPerBlock) {
168
171
  throw new BlockGossipError(GossipAction.REJECT, {
169
172
  code: BlockErrorCode.TOO_MANY_KZG_COMMITMENTS,
173
+ slot: blockSlot,
174
+ root: blockRoot,
170
175
  blobKzgCommitmentsLen,
171
176
  commitmentLimit: maxBlobsPerBlock,
172
177
  });
@@ -176,6 +181,8 @@ export async function validateGossipBlock(
176
181
  if (!byteArrayEquals(bid.parentBlockRoot, block.parentRoot)) {
177
182
  throw new BlockGossipError(GossipAction.REJECT, {
178
183
  code: BlockErrorCode.BID_PARENT_ROOT_MISMATCH,
184
+ slot: blockSlot,
185
+ root: blockRoot,
179
186
  bidParentRoot: toRootHex(bid.parentBlockRoot),
180
187
  blockParentRoot: parentRoot,
181
188
  });
@@ -185,6 +192,8 @@ export async function validateGossipBlock(
185
192
  if (body.deposits.length !== 0) {
186
193
  throw new BlockGossipError(GossipAction.REJECT, {
187
194
  code: BlockErrorCode.NON_ZERO_DEPOSITS,
195
+ slot: blockSlot,
196
+ root: blockRoot,
188
197
  count: body.deposits.length,
189
198
  });
190
199
  }
@@ -249,6 +258,8 @@ export async function validateGossipBlock(
249
258
  if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
250
259
  throw new BlockGossipError(GossipAction.REJECT, {
251
260
  code: BlockErrorCode.INCORRECT_TIMESTAMP,
261
+ slot: blockSlot,
262
+ root: blockRoot,
252
263
  timestamp: executionPayload.timestamp,
253
264
  expectedTimestamp,
254
265
  });
@@ -258,7 +269,12 @@ export async function validateGossipBlock(
258
269
 
259
270
  // [REJECT] The proposer index is a valid validator index
260
271
  if (proposerIndex >= state.validatorCount) {
261
- throw new BlockGossipError(GossipAction.REJECT, {code: BlockErrorCode.UNKNOWN_PROPOSER, proposerIndex});
272
+ throw new BlockGossipError(GossipAction.REJECT, {
273
+ code: BlockErrorCode.UNKNOWN_PROPOSER,
274
+ slot: blockSlot,
275
+ root: blockRoot,
276
+ proposerIndex,
277
+ });
262
278
  }
263
279
 
264
280
  // [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
@@ -270,7 +286,12 @@ export async function validateGossipBlock(
270
286
  // shuffling, the block MAY be queued for later processing while proposers for the block's branch are calculated --
271
287
  // in such a case do not REJECT, instead IGNORE this message.
272
288
  if (state.getBeaconProposer(blockSlot) !== proposerIndex) {
273
- throw new BlockGossipError(GossipAction.REJECT, {code: BlockErrorCode.INCORRECT_PROPOSER, proposerIndex});
289
+ throw new BlockGossipError(GossipAction.REJECT, {
290
+ code: BlockErrorCode.INCORRECT_PROPOSER,
291
+ slot: blockSlot,
292
+ root: blockRoot,
293
+ proposerIndex,
294
+ });
274
295
  }
275
296
 
276
297
  // Simple implementation of a pending block queue. Keeping the block here recycles the queue logic, and keeps the
@@ -315,7 +336,8 @@ export async function verifyBlockProposerSignature(
315
336
  if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: opts.verifyOnMainThread ?? true}))) {
316
337
  throw new BlockGossipError(GossipAction.REJECT, {
317
338
  code: BlockErrorCode.PROPOSAL_SIGNATURE_INVALID,
318
- blockSlot,
339
+ slot: blockSlot,
340
+ root: blockRoot,
319
341
  });
320
342
  }
321
343