@lodestar/beacon-node 1.37.0-dev.f0ce024c1a → 1.37.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.
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +4 -2
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +14 -1
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +2 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +2 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +11 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +30 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
- package/lib/chain/validation/blobSidecar.js +29 -22
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +10 -7
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +33 -26
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +2 -1
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/interface.d.ts +3 -3
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +3 -3
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +3 -3
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +2 -0
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/utils/collect.d.ts +3 -3
- package/lib/network/reqresp/utils/collect.d.ts.map +1 -1
- package/lib/network/reqresp/utils/collect.js +7 -3
- package/lib/network/reqresp/utils/collect.js.map +1 -1
- package/lib/network/reqresp/utils/collectSequentialBlocksInRange.d.ts +3 -2
- package/lib/network/reqresp/utils/collectSequentialBlocksInRange.d.ts.map +1 -1
- package/lib/network/reqresp/utils/collectSequentialBlocksInRange.js +5 -3
- package/lib/network/reqresp/utils/collectSequentialBlocksInRange.js.map +1 -1
- package/lib/sync/backfill/backfill.d.ts.map +1 -1
- package/lib/sync/backfill/backfill.js +37 -14
- package/lib/sync/backfill/backfill.js.map +1 -1
- package/lib/sync/backfill/verify.d.ts +4 -4
- package/lib/sync/backfill/verify.d.ts.map +1 -1
- package/lib/sync/backfill/verify.js +6 -6
- package/lib/sync/backfill/verify.js.map +1 -1
- package/lib/sync/utils/downloadByRange.js +1 -1
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +1 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/package.json +14 -19
- package/src/chain/blocks/importBlock.ts +5 -1
- package/src/chain/blocks/writeBlockInputToDb.ts +13 -1
- package/src/chain/prepareNextSlot.ts +2 -1
- package/src/chain/produceBlock/produceBlockBody.ts +2 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +33 -2
- package/src/chain/validation/blobSidecar.ts +33 -24
- package/src/chain/validation/block.ts +11 -7
- package/src/chain/validation/dataColumnSidecar.ts +43 -33
- package/src/network/gossip/encoding.ts +2 -1
- package/src/network/interface.ts +2 -9
- package/src/network/network.ts +8 -9
- package/src/network/processor/gossipHandlers.ts +2 -0
- package/src/network/reqresp/utils/collect.ts +12 -6
- package/src/network/reqresp/utils/collectSequentialBlocksInRange.ts +10 -6
- package/src/sync/backfill/backfill.ts +40 -16
- package/src/sync/backfill/verify.ts +10 -10
- package/src/sync/utils/downloadByRange.ts +1 -1
- package/src/sync/utils/downloadByRoot.ts +1 -1
- package/lib/network/gossip/snappy_bun.d.ts +0 -3
- package/lib/network/gossip/snappy_bun.d.ts.map +0 -1
- package/lib/network/gossip/snappy_bun.js +0 -3
- package/lib/network/gossip/snappy_bun.js.map +0 -1
- 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 {
|
|
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
|
-
|
|
64
|
+
typeFn: ResponseTypeGetter<T>,
|
|
65
|
+
serializedCache?: SerializedCache
|
|
66
|
+
): Promise<T[]> {
|
|
63
67
|
// else: zero or more responses
|
|
64
|
-
const responses:
|
|
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(
|
|
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,
|
|
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
|
-
|
|
15
|
-
|
|
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.
|
|
35
|
+
if (prevBlock && prevBlock.message.slot >= blockSlot) {
|
|
34
36
|
throw new BlocksByRangeError({code: BlocksByRangeErrorCode.BAD_SEQUENCE});
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
blocks.push(
|
|
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.
|
|
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.
|
|
759
|
-
|
|
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
|
|
768
|
+
anchorBlock: anchorBlock,
|
|
763
769
|
anchorBlockRoot,
|
|
764
|
-
anchorSlot: anchorBlock.
|
|
765
|
-
lastBackSyncedBlock: {root: anchorBlockRoot, slot: anchorBlock.
|
|
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.
|
|
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
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
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,
|
|
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:
|
|
17
|
+
blocks: SignedBeaconBlock[],
|
|
18
18
|
anchorRoot: Root
|
|
19
19
|
): {
|
|
20
20
|
nextAnchor: BackfillBlock | null;
|
|
21
|
-
verifiedBlocks:
|
|
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:
|
|
27
|
+
const verifiedBlocks: SignedBeaconBlock[] = [];
|
|
28
28
|
for (const block of blocks.reverse()) {
|
|
29
|
-
const blockRoot = config.getForkTypes(block.
|
|
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
|
|
38
|
-
nextRoot = block.
|
|
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:
|
|
46
|
+
blocks: SignedBeaconBlock[]
|
|
47
47
|
): Promise<void> {
|
|
48
|
-
if (blocks.length === 1 && blocks[0].
|
|
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.
|
|
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
|
|
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)
|
|
317
|
+
const block = response.at(0);
|
|
318
318
|
if (!block) {
|
|
319
319
|
throw new DownloadByRootError({
|
|
320
320
|
code: DownloadByRootErrorCode.MISSING_BLOCK_RESPONSE,
|
|
@@ -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 +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"}
|