@lodestar/beacon-node 1.37.0-dev.f0ce024c1a → 1.37.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 (80) hide show
  1. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  2. package/lib/chain/blocks/importBlock.js +4 -2
  3. package/lib/chain/blocks/importBlock.js.map +1 -1
  4. package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
  5. package/lib/chain/blocks/writeBlockInputToDb.js +14 -1
  6. package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
  7. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  8. package/lib/chain/prepareNextSlot.js +2 -1
  9. package/lib/chain/prepareNextSlot.js.map +1 -1
  10. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  11. package/lib/chain/produceBlock/produceBlockBody.js +2 -1
  12. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  13. package/lib/chain/seenCache/seenGossipBlockInput.d.ts +11 -1
  14. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  15. package/lib/chain/seenCache/seenGossipBlockInput.js +30 -1
  16. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  17. package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
  18. package/lib/chain/validation/blobSidecar.js +29 -22
  19. package/lib/chain/validation/blobSidecar.js.map +1 -1
  20. package/lib/chain/validation/block.d.ts.map +1 -1
  21. package/lib/chain/validation/block.js +10 -7
  22. package/lib/chain/validation/block.js.map +1 -1
  23. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  24. package/lib/chain/validation/dataColumnSidecar.js +33 -26
  25. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  26. package/lib/network/gossip/encoding.d.ts.map +1 -1
  27. package/lib/network/gossip/encoding.js +2 -1
  28. package/lib/network/gossip/encoding.js.map +1 -1
  29. package/lib/network/interface.d.ts +3 -3
  30. package/lib/network/interface.d.ts.map +1 -1
  31. package/lib/network/network.d.ts +3 -3
  32. package/lib/network/network.d.ts.map +1 -1
  33. package/lib/network/network.js +3 -3
  34. package/lib/network/network.js.map +1 -1
  35. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  36. package/lib/network/processor/gossipHandlers.js +2 -0
  37. package/lib/network/processor/gossipHandlers.js.map +1 -1
  38. package/lib/network/reqresp/utils/collect.d.ts +3 -3
  39. package/lib/network/reqresp/utils/collect.d.ts.map +1 -1
  40. package/lib/network/reqresp/utils/collect.js +7 -3
  41. package/lib/network/reqresp/utils/collect.js.map +1 -1
  42. package/lib/network/reqresp/utils/collectSequentialBlocksInRange.d.ts +3 -2
  43. package/lib/network/reqresp/utils/collectSequentialBlocksInRange.d.ts.map +1 -1
  44. package/lib/network/reqresp/utils/collectSequentialBlocksInRange.js +5 -3
  45. package/lib/network/reqresp/utils/collectSequentialBlocksInRange.js.map +1 -1
  46. package/lib/sync/backfill/backfill.d.ts.map +1 -1
  47. package/lib/sync/backfill/backfill.js +37 -14
  48. package/lib/sync/backfill/backfill.js.map +1 -1
  49. package/lib/sync/backfill/verify.d.ts +4 -4
  50. package/lib/sync/backfill/verify.d.ts.map +1 -1
  51. package/lib/sync/backfill/verify.js +6 -6
  52. package/lib/sync/backfill/verify.js.map +1 -1
  53. package/lib/sync/utils/downloadByRange.js +1 -1
  54. package/lib/sync/utils/downloadByRange.js.map +1 -1
  55. package/lib/sync/utils/downloadByRoot.js +1 -1
  56. package/lib/sync/utils/downloadByRoot.js.map +1 -1
  57. package/package.json +14 -19
  58. package/src/chain/blocks/importBlock.ts +5 -1
  59. package/src/chain/blocks/writeBlockInputToDb.ts +13 -1
  60. package/src/chain/prepareNextSlot.ts +2 -1
  61. package/src/chain/produceBlock/produceBlockBody.ts +2 -1
  62. package/src/chain/seenCache/seenGossipBlockInput.ts +33 -2
  63. package/src/chain/validation/blobSidecar.ts +33 -24
  64. package/src/chain/validation/block.ts +11 -7
  65. package/src/chain/validation/dataColumnSidecar.ts +43 -33
  66. package/src/network/gossip/encoding.ts +2 -1
  67. package/src/network/interface.ts +2 -9
  68. package/src/network/network.ts +8 -9
  69. package/src/network/processor/gossipHandlers.ts +2 -0
  70. package/src/network/reqresp/utils/collect.ts +12 -6
  71. package/src/network/reqresp/utils/collectSequentialBlocksInRange.ts +10 -6
  72. package/src/sync/backfill/backfill.ts +40 -16
  73. package/src/sync/backfill/verify.ts +10 -10
  74. package/src/sync/utils/downloadByRange.ts +1 -1
  75. package/src/sync/utils/downloadByRoot.ts +1 -1
  76. package/lib/network/gossip/snappy_bun.d.ts +0 -3
  77. package/lib/network/gossip/snappy_bun.d.ts.map +0 -1
  78. package/lib/network/gossip/snappy_bun.js +0 -3
  79. package/lib/network/gossip/snappy_bun.js.map +0 -1
  80. package/src/network/gossip/snappy_bun.ts +0 -2
@@ -516,6 +516,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
516
516
  throw new GossipActionError(GossipAction.REJECT, {code: "PRE_DENEB_BLOCK"});
517
517
  }
518
518
  const blockInput = await validateBeaconBlob(blobSidecar, topic.subnet, peerIdStr, seenTimestampSec);
519
+ chain.serializedCache.set(blobSidecar, serializedData);
519
520
  if (!blockInput.hasBlockAndAllData()) {
520
521
  const cutoffTimeMs = getCutoffTimeMs(chain, blobSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
521
522
  chain.logger.debug("Received gossip blob, waiting for full data availability", {
@@ -562,6 +563,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
562
563
  peerIdStr,
563
564
  seenTimestampSec
564
565
  );
566
+ chain.serializedCache.set(dataColumnSidecar, serializedData);
565
567
  const blockInputMeta = blockInput.getLogMeta();
566
568
  const {receivedColumns} = blockInputMeta;
567
569
  // it's not helpful to track every single column received
@@ -1,6 +1,6 @@
1
1
  import {Type} from "@chainsafe/ssz";
2
2
  import {RequestError, RequestErrorCode, ResponseIncoming} from "@lodestar/reqresp";
3
- import {WithBytes} from "@lodestar/types";
3
+ import {SerializedCache} from "../../../util/serializedCache.ts";
4
4
  import {ResponseTypeGetter} from "../types.js";
5
5
 
6
6
  /**
@@ -32,13 +32,16 @@ export async function collectExactOneTyped<T>(
32
32
  export async function collectMaxResponseTyped<T>(
33
33
  source: AsyncIterable<ResponseIncoming>,
34
34
  maxResponses: number,
35
- typeFn: ResponseTypeGetter<T>
35
+ typeFn: ResponseTypeGetter<T>,
36
+ serializedCache?: SerializedCache
36
37
  ): Promise<T[]> {
37
38
  // else: zero or more responses
38
39
  const responses: T[] = [];
39
40
  for await (const chunk of source) {
40
41
  const type = typeFn(chunk.fork, chunk.protocolVersion);
41
42
  const response = sszDeserializeResponse(type, chunk.data);
43
+ // optionally cache the serialized response if the cache is available
44
+ serializedCache?.set(response as object, chunk.data);
42
45
  responses.push(response);
43
46
 
44
47
  if (maxResponses !== undefined && responses.length >= maxResponses) {
@@ -58,14 +61,17 @@ export async function collectMaxResponseTyped<T>(
58
61
  export async function collectMaxResponseTypedWithBytes<T>(
59
62
  source: AsyncIterable<ResponseIncoming>,
60
63
  maxResponses: number,
61
- typeFn: ResponseTypeGetter<T>
62
- ): Promise<WithBytes<T>[]> {
64
+ typeFn: ResponseTypeGetter<T>,
65
+ serializedCache?: SerializedCache
66
+ ): Promise<T[]> {
63
67
  // else: zero or more responses
64
- const responses: WithBytes<T>[] = [];
68
+ const responses: T[] = [];
65
69
  for await (const chunk of source) {
66
70
  const type = typeFn(chunk.fork, chunk.protocolVersion);
67
71
  const data = sszDeserializeResponse(type, chunk.data);
68
- responses.push({data, bytes: chunk.data});
72
+ responses.push(data);
73
+ // optionally cache the serialized response if the cache is available
74
+ serializedCache?.set(data as object, chunk.data);
69
75
 
70
76
  if (maxResponses !== undefined && responses.length >= maxResponses) {
71
77
  break;
@@ -1,6 +1,7 @@
1
1
  import {ResponseIncoming} from "@lodestar/reqresp";
2
- import {SignedBeaconBlock, WithBytes, phase0} from "@lodestar/types";
2
+ import {SignedBeaconBlock, phase0} from "@lodestar/types";
3
3
  import {LodestarError} from "@lodestar/utils";
4
+ import {SerializedCache} from "../../../util/serializedCache.ts";
4
5
  import {ReqRespMethod, responseSszTypeByMethod} from "../types.js";
5
6
  import {sszDeserializeResponse} from "./collect.js";
6
7
 
@@ -10,9 +11,10 @@ import {sszDeserializeResponse} from "./collect.js";
10
11
  */
11
12
  export async function collectSequentialBlocksInRange(
12
13
  blockStream: AsyncIterable<ResponseIncoming>,
13
- {count, startSlot}: Pick<phase0.BeaconBlocksByRangeRequest, "count" | "startSlot">
14
- ): Promise<WithBytes<SignedBeaconBlock>[]> {
15
- const blocks: WithBytes<SignedBeaconBlock>[] = [];
14
+ {count, startSlot}: Pick<phase0.BeaconBlocksByRangeRequest, "count" | "startSlot">,
15
+ serializedCache?: SerializedCache
16
+ ): Promise<SignedBeaconBlock[]> {
17
+ const blocks: SignedBeaconBlock[] = [];
16
18
 
17
19
  for await (const chunk of blockStream) {
18
20
  const blockType = responseSszTypeByMethod[ReqRespMethod.BeaconBlocksByRange](chunk.fork, chunk.protocolVersion);
@@ -30,11 +32,13 @@ export async function collectSequentialBlocksInRange(
30
32
  }
31
33
 
32
34
  const prevBlock = blocks.at(-1);
33
- if (prevBlock && prevBlock.data.message.slot >= blockSlot) {
35
+ if (prevBlock && prevBlock.message.slot >= blockSlot) {
34
36
  throw new BlocksByRangeError({code: BlocksByRangeErrorCode.BAD_SEQUENCE});
35
37
  }
36
38
 
37
- blocks.push({data: block, bytes: chunk.data});
39
+ blocks.push(block);
40
+ // optionally cache the serialized response if the cache is available
41
+ serializedCache?.set(block, chunk.data);
38
42
  if (blocks.length >= count) {
39
43
  break; // Done, collected all blocks
40
44
  }
@@ -749,27 +749,33 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
749
749
  const anchorBlock = res[0];
750
750
 
751
751
  // GENESIS_SLOT doesn't has valid signature
752
- if (anchorBlock.data.message.slot === GENESIS_SLOT) return;
752
+ if (anchorBlock.message.slot === GENESIS_SLOT) return;
753
753
  await verifyBlockProposerSignature(this.chain.bls, this.chain.getHeadState(), [anchorBlock]);
754
754
 
755
755
  // We can write to the disk if this is ahead of prevFinalizedCheckpointBlock otherwise
756
756
  // we will need to go make checks on the top of sync loop before writing as it might
757
757
  // override prevFinalizedCheckpointBlock
758
- if (this.prevFinalizedCheckpointBlock.slot < anchorBlock.data.message.slot)
759
- await this.db.blockArchive.putBinary(anchorBlock.data.message.slot, anchorBlock.bytes);
758
+ if (this.prevFinalizedCheckpointBlock.slot < anchorBlock.message.slot) {
759
+ const serialized = this.chain.serializedCache.get(anchorBlock);
760
+ if (serialized) {
761
+ await this.db.blockArchive.putBinary(anchorBlock.message.slot, serialized);
762
+ } else {
763
+ await this.db.blockArchive.put(anchorBlock.message.slot, anchorBlock);
764
+ }
765
+ }
760
766
 
761
767
  this.syncAnchor = {
762
- anchorBlock: anchorBlock.data,
768
+ anchorBlock: anchorBlock,
763
769
  anchorBlockRoot,
764
- anchorSlot: anchorBlock.data.message.slot,
765
- lastBackSyncedBlock: {root: anchorBlockRoot, slot: anchorBlock.data.message.slot, block: anchorBlock.data},
770
+ anchorSlot: anchorBlock.message.slot,
771
+ lastBackSyncedBlock: {root: anchorBlockRoot, slot: anchorBlock.message.slot, block: anchorBlock},
766
772
  };
767
773
 
768
774
  this.metrics?.backfillSync.totalBlocks.inc({method: BackfillSyncMethod.blockbyroot});
769
775
 
770
776
  this.logger.verbose("Fetched new anchorBlock", {
771
777
  root: toRootHex(anchorBlockRoot),
772
- slot: anchorBlock.data.message.slot,
778
+ slot: anchorBlock.message.slot,
773
779
  });
774
780
 
775
781
  return;
@@ -825,15 +831,33 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
825
831
  nextAnchor.slot > this.prevFinalizedCheckpointBlock.slot
826
832
  ? verifiedBlocks
827
833
  : verifiedBlocks.slice(0, verifiedBlocks.length - 1);
828
- await this.db.blockArchive.batchPutBinary(
829
- blocksToPut.map((block) => ({
830
- key: block.data.message.slot,
831
- value: block.bytes,
832
- slot: block.data.message.slot,
833
- blockRoot: this.config.getForkTypes(block.data.message.slot).BeaconBlock.hashTreeRoot(block.data.message),
834
- parentRoot: block.data.message.parentRoot,
835
- }))
836
- );
834
+
835
+ const binaryPuts = [];
836
+ const nonBinaryPuts = [];
837
+
838
+ for (const block of blocksToPut) {
839
+ const serialized = this.chain.serializedCache.get(block);
840
+ const item = {
841
+ key: block.message.slot,
842
+ slot: block.message.slot,
843
+ blockRoot: this.config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message),
844
+ parentRoot: block.message.parentRoot,
845
+ };
846
+
847
+ if (serialized) {
848
+ binaryPuts.push({...item, value: serialized});
849
+ } else {
850
+ nonBinaryPuts.push({...item, value: block});
851
+ }
852
+ }
853
+
854
+ if (binaryPuts.length > 0) {
855
+ await this.db.blockArchive.batchPutBinary(binaryPuts);
856
+ }
857
+ if (nonBinaryPuts.length > 0) {
858
+ await this.db.blockArchive.batchPut(nonBinaryPuts);
859
+ }
860
+
837
861
  this.metrics?.backfillSync.totalBlocks.inc({method: BackfillSyncMethod.rangesync}, verifiedBlocks.length);
838
862
  }
839
863
 
@@ -1,7 +1,7 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {GENESIS_SLOT} from "@lodestar/params";
3
3
  import {CachedBeaconStateAllForks, ISignatureSet, getBlockProposerSignatureSet} from "@lodestar/state-transition";
4
- import {Root, SignedBeaconBlock, Slot, WithBytes, ssz} from "@lodestar/types";
4
+ import {Root, SignedBeaconBlock, Slot, ssz} from "@lodestar/types";
5
5
  import {IBlsVerifier} from "../../chain/bls/index.js";
6
6
  import {BackfillSyncError, BackfillSyncErrorCode} from "./errors.js";
7
7
 
@@ -14,19 +14,19 @@ export type BackfillBlock = BackfillBlockHeader & {block: SignedBeaconBlock};
14
14
 
15
15
  export function verifyBlockSequence(
16
16
  config: BeaconConfig,
17
- blocks: WithBytes<SignedBeaconBlock>[],
17
+ blocks: SignedBeaconBlock[],
18
18
  anchorRoot: Root
19
19
  ): {
20
20
  nextAnchor: BackfillBlock | null;
21
- verifiedBlocks: WithBytes<SignedBeaconBlock>[];
21
+ verifiedBlocks: SignedBeaconBlock[];
22
22
  error?: BackfillSyncErrorCode.NOT_LINEAR;
23
23
  } {
24
24
  let nextRoot: Root = anchorRoot;
25
25
  let nextAnchor: BackfillBlock | null = null;
26
26
 
27
- const verifiedBlocks: WithBytes<SignedBeaconBlock>[] = [];
27
+ const verifiedBlocks: SignedBeaconBlock[] = [];
28
28
  for (const block of blocks.reverse()) {
29
- const blockRoot = config.getForkTypes(block.data.message.slot).BeaconBlock.hashTreeRoot(block.data.message);
29
+ const blockRoot = config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message);
30
30
  if (!ssz.Root.equals(blockRoot, nextRoot)) {
31
31
  if (ssz.Root.equals(nextRoot, anchorRoot)) {
32
32
  throw new BackfillSyncError({code: BackfillSyncErrorCode.NOT_ANCHORED});
@@ -34,8 +34,8 @@ export function verifyBlockSequence(
34
34
  return {nextAnchor, verifiedBlocks, error: BackfillSyncErrorCode.NOT_LINEAR};
35
35
  }
36
36
  verifiedBlocks.push(block);
37
- nextAnchor = {block: block.data, slot: block.data.message.slot, root: nextRoot};
38
- nextRoot = block.data.message.parentRoot;
37
+ nextAnchor = {block: block, slot: block.message.slot, root: nextRoot};
38
+ nextRoot = block.message.parentRoot;
39
39
  }
40
40
  return {nextAnchor, verifiedBlocks};
41
41
  }
@@ -43,12 +43,12 @@ export function verifyBlockSequence(
43
43
  export async function verifyBlockProposerSignature(
44
44
  bls: IBlsVerifier,
45
45
  state: CachedBeaconStateAllForks,
46
- blocks: WithBytes<SignedBeaconBlock>[]
46
+ blocks: SignedBeaconBlock[]
47
47
  ): Promise<void> {
48
- if (blocks.length === 1 && blocks[0].data.message.slot === GENESIS_SLOT) return;
48
+ if (blocks.length === 1 && blocks[0].message.slot === GENESIS_SLOT) return;
49
49
  const signatures = blocks.reduce((sigs: ISignatureSet[], block) => {
50
50
  // genesis block doesn't have valid signature
51
- if (block.data.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(state, block.data));
51
+ if (block.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(state, block));
52
52
  return sigs;
53
53
  }, []);
54
54
 
@@ -254,7 +254,7 @@ export async function requestByRange({
254
254
  if (blocksRequest) {
255
255
  requests.push(
256
256
  network.sendBeaconBlocksByRange(peerIdStr, blocksRequest).then((blockResponse) => {
257
- blocks = blockResponse.map(({data}) => data);
257
+ blocks = blockResponse;
258
258
  })
259
259
  );
260
260
  }
@@ -314,7 +314,7 @@ export async function fetchAndValidateBlock({
314
314
  blockRoot,
315
315
  }: Omit<FetchByRootAndValidateBlockProps, "chain">): Promise<SignedBeaconBlock> {
316
316
  const response = await network.sendBeaconBlocksByRoot(peerIdStr, [blockRoot]);
317
- const block = response.at(0)?.data;
317
+ const block = response.at(0);
318
318
  if (!block) {
319
319
  throw new DownloadByRootError({
320
320
  code: DownloadByRootErrorCode.MISSING_BLOCK_RESPONSE,
@@ -1,3 +0,0 @@
1
- import { snappy } from "@lodestar/bun";
2
- export declare const compress: typeof snappy.compress, uncompress: typeof snappy.uncompress;
3
- //# sourceMappingURL=snappy_bun.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"snappy_bun.d.ts","sourceRoot":"","sources":["../../../src/network/gossip/snappy_bun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,eAAe,CAAC;AACrC,eAAO,MAAO,QAAQ,0BAAE,UAAU,0BAAU,CAAC"}
@@ -1,3 +0,0 @@
1
- import { snappy } from "@lodestar/bun";
2
- export const { compress, uncompress } = snappy;
3
- //# sourceMappingURL=snappy_bun.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"snappy_bun.js","sourceRoot":"","sources":["../../../src/network/gossip/snappy_bun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,eAAe,CAAC;AACrC,MAAM,CAAC,MAAM,EAAC,QAAQ,EAAE,UAAU,EAAC,GAAG,MAAM,CAAC"}
@@ -1,2 +0,0 @@
1
- import {snappy} from "@lodestar/bun";
2
- export const {compress, uncompress} = snappy;