@lodestar/beacon-node 1.37.0 → 1.38.0-dev.1ddbe5d870
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/README.md +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +5 -3
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +4 -4
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +2 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +5 -1
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts +2 -0
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +18 -10
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts +3 -3
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.js +2 -2
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +3 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.d.ts +2 -2
- package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.js +1 -2
- package/lib/chain/rewards/syncCommitteeRewards.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +2 -2
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
- package/lib/chain/validation/blobSidecar.js +2 -2
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.js +1 -1
- 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 +2 -2
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.js +2 -3
- package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.js +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +3 -3
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
- package/lib/chain/validation/syncCommittee.js +1 -1
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -3
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +1 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts +4 -2
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +24 -9
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +6 -5
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/metrics.d.ts +8 -0
- package/lib/network/gossip/metrics.d.ts.map +1 -1
- package/lib/network/gossip/metrics.js +12 -0
- package/lib/network/gossip/metrics.js.map +1 -1
- package/lib/sync/backfill/backfill.d.ts.map +1 -1
- package/lib/sync/backfill/backfill.js +4 -2
- package/lib/sync/backfill/backfill.js.map +1 -1
- package/lib/sync/backfill/verify.d.ts +2 -2
- package/lib/sync/backfill/verify.d.ts.map +1 -1
- package/lib/sync/backfill/verify.js +3 -3
- package/lib/sync/backfill/verify.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/state/utils.ts +5 -3
- package/src/chain/blocks/importBlock.ts +5 -4
- package/src/chain/blocks/index.ts +2 -1
- package/src/chain/blocks/types.ts +5 -1
- package/src/chain/blocks/verifyBlock.ts +35 -11
- package/src/chain/blocks/verifyBlocksSignatures.ts +5 -3
- package/src/chain/chain.ts +2 -2
- package/src/chain/opPools/aggregatedAttestationPool.ts +5 -1
- package/src/chain/rewards/syncCommitteeRewards.ts +2 -2
- package/src/chain/validation/attesterSlashing.ts +2 -2
- package/src/chain/validation/blobSidecar.ts +10 -2
- package/src/chain/validation/block.ts +1 -1
- package/src/chain/validation/dataColumnSidecar.ts +6 -1
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/signatureSets/contributionAndProof.ts +3 -2
- package/src/chain/validation/signatureSets/syncCommittee.ts +3 -1
- package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +4 -2
- package/src/chain/validation/syncCommittee.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +4 -5
- package/src/chain/validation/voluntaryExit.ts +1 -1
- package/src/network/gossip/encoding.ts +26 -9
- package/src/network/gossip/gossipsub.ts +8 -6
- package/src/network/gossip/metrics.ts +12 -0
- package/src/sync/backfill/backfill.ts +9 -2
- package/src/sync/backfill/verify.ts +8 -2
|
@@ -2,16 +2,17 @@ import {DOMAIN_CONTRIBUTION_AND_PROOF} from "@lodestar/params";
|
|
|
2
2
|
import {
|
|
3
3
|
CachedBeaconStateAllForks,
|
|
4
4
|
ISignatureSet,
|
|
5
|
+
Index2PubkeyCache,
|
|
5
6
|
SignatureSetType,
|
|
6
7
|
computeSigningRoot,
|
|
7
8
|
} from "@lodestar/state-transition";
|
|
8
9
|
import {altair, ssz} from "@lodestar/types";
|
|
9
10
|
|
|
10
11
|
export function getContributionAndProofSignatureSet(
|
|
12
|
+
index2pubkey: Index2PubkeyCache,
|
|
11
13
|
state: CachedBeaconStateAllForks,
|
|
12
14
|
signedContributionAndProof: altair.SignedContributionAndProof
|
|
13
15
|
): ISignatureSet {
|
|
14
|
-
const {epochCtx} = state;
|
|
15
16
|
const domain = state.config.getDomain(
|
|
16
17
|
state.slot,
|
|
17
18
|
DOMAIN_CONTRIBUTION_AND_PROOF,
|
|
@@ -20,7 +21,7 @@ export function getContributionAndProofSignatureSet(
|
|
|
20
21
|
const signingData = signedContributionAndProof.message;
|
|
21
22
|
return {
|
|
22
23
|
type: SignatureSetType.single,
|
|
23
|
-
pubkey:
|
|
24
|
+
pubkey: index2pubkey[signedContributionAndProof.message.aggregatorIndex],
|
|
24
25
|
signingRoot: computeSigningRoot(ssz.altair.ContributionAndProof, signingData, domain),
|
|
25
26
|
signature: signedContributionAndProof.signature,
|
|
26
27
|
};
|
|
@@ -2,12 +2,14 @@ import {DOMAIN_SYNC_COMMITTEE} from "@lodestar/params";
|
|
|
2
2
|
import {
|
|
3
3
|
CachedBeaconStateAllForks,
|
|
4
4
|
ISignatureSet,
|
|
5
|
+
Index2PubkeyCache,
|
|
5
6
|
SignatureSetType,
|
|
6
7
|
computeSigningRoot,
|
|
7
8
|
} from "@lodestar/state-transition";
|
|
8
9
|
import {altair, ssz} from "@lodestar/types";
|
|
9
10
|
|
|
10
11
|
export function getSyncCommitteeSignatureSet(
|
|
12
|
+
index2pubkey: Index2PubkeyCache,
|
|
11
13
|
state: CachedBeaconStateAllForks,
|
|
12
14
|
syncCommittee: altair.SyncCommitteeMessage
|
|
13
15
|
): ISignatureSet {
|
|
@@ -15,7 +17,7 @@ export function getSyncCommitteeSignatureSet(
|
|
|
15
17
|
|
|
16
18
|
return {
|
|
17
19
|
type: SignatureSetType.single,
|
|
18
|
-
pubkey:
|
|
20
|
+
pubkey: index2pubkey[syncCommittee.validatorIndex],
|
|
19
21
|
signingRoot: computeSigningRoot(ssz.Root, syncCommittee.beaconBlockRoot, domain),
|
|
20
22
|
signature: syncCommittee.signature,
|
|
21
23
|
};
|
|
@@ -2,16 +2,18 @@ import {DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF} from "@lodestar/params";
|
|
|
2
2
|
import {
|
|
3
3
|
CachedBeaconStateAllForks,
|
|
4
4
|
ISignatureSet,
|
|
5
|
+
Index2PubkeyCache,
|
|
5
6
|
SignatureSetType,
|
|
6
7
|
computeSigningRoot,
|
|
7
8
|
} from "@lodestar/state-transition";
|
|
8
9
|
import {altair, ssz} from "@lodestar/types";
|
|
9
10
|
|
|
10
11
|
export function getSyncCommitteeSelectionProofSignatureSet(
|
|
12
|
+
index2pubkey: Index2PubkeyCache,
|
|
11
13
|
state: CachedBeaconStateAllForks,
|
|
12
14
|
contributionAndProof: altair.ContributionAndProof
|
|
13
15
|
): ISignatureSet {
|
|
14
|
-
const {
|
|
16
|
+
const {config} = state;
|
|
15
17
|
const slot = contributionAndProof.contribution.slot;
|
|
16
18
|
const domain = config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, slot);
|
|
17
19
|
const signingData: altair.SyncAggregatorSelectionData = {
|
|
@@ -20,7 +22,7 @@ export function getSyncCommitteeSelectionProofSignatureSet(
|
|
|
20
22
|
};
|
|
21
23
|
return {
|
|
22
24
|
type: SignatureSetType.single,
|
|
23
|
-
pubkey:
|
|
25
|
+
pubkey: index2pubkey[contributionAndProof.aggregatorIndex],
|
|
24
26
|
signingRoot: computeSigningRoot(ssz.altair.SyncAggregatorSelectionData, signingData, domain),
|
|
25
27
|
signature: contributionAndProof.selectionProof,
|
|
26
28
|
};
|
|
@@ -89,7 +89,7 @@ async function validateSyncCommitteeSigOnly(
|
|
|
89
89
|
syncCommittee: altair.SyncCommitteeMessage,
|
|
90
90
|
prioritizeBls = false
|
|
91
91
|
): Promise<void> {
|
|
92
|
-
const signatureSet = getSyncCommitteeSignatureSet(headState, syncCommittee);
|
|
92
|
+
const signatureSet = getSyncCommitteeSignatureSet(chain.index2pubkey, headState, syncCommittee);
|
|
93
93
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
94
94
|
throw new SyncCommitteeError(GossipAction.REJECT, {
|
|
95
95
|
code: SyncCommitteeErrorCode.INVALID_SIGNATURE,
|
|
@@ -21,6 +21,7 @@ export async function validateSyncCommitteeGossipContributionAndProof(
|
|
|
21
21
|
const contributionAndProof = signedContributionAndProof.message;
|
|
22
22
|
const {contribution, aggregatorIndex} = contributionAndProof;
|
|
23
23
|
const {subcommitteeIndex, slot} = contribution;
|
|
24
|
+
const {index2pubkey} = chain;
|
|
24
25
|
|
|
25
26
|
const headState = chain.getHeadState();
|
|
26
27
|
validateGossipSyncCommitteeExceptSig(chain, headState, subcommitteeIndex, {
|
|
@@ -73,16 +74,14 @@ export async function validateSyncCommitteeGossipContributionAndProof(
|
|
|
73
74
|
// i.e. state.validators[contribution_and_proof.aggregator_index].pubkey in get_sync_subcommittee_pubkeys(state, contribution.subcommittee_index).
|
|
74
75
|
// > Checked in validateGossipSyncCommitteeExceptSig()
|
|
75
76
|
|
|
76
|
-
const participantPubkeys = syncCommitteeParticipantIndices.map(
|
|
77
|
-
(validatorIndex) => headState.epochCtx.index2pubkey[validatorIndex]
|
|
78
|
-
);
|
|
77
|
+
const participantPubkeys = syncCommitteeParticipantIndices.map((validatorIndex) => index2pubkey[validatorIndex]);
|
|
79
78
|
const signatureSets = [
|
|
80
79
|
// [REJECT] The contribution_and_proof.selection_proof is a valid signature of the SyncAggregatorSelectionData
|
|
81
80
|
// derived from the contribution by the validator with index contribution_and_proof.aggregator_index.
|
|
82
|
-
getSyncCommitteeSelectionProofSignatureSet(headState, contributionAndProof),
|
|
81
|
+
getSyncCommitteeSelectionProofSignatureSet(index2pubkey, headState, contributionAndProof),
|
|
83
82
|
|
|
84
83
|
// [REJECT] The aggregator signature, signed_contribution_and_proof.signature, is valid.
|
|
85
|
-
getContributionAndProofSignatureSet(headState, signedContributionAndProof),
|
|
84
|
+
getContributionAndProofSignatureSet(index2pubkey, headState, signedContributionAndProof),
|
|
86
85
|
|
|
87
86
|
// [REJECT] The aggregate signature is valid for the message beacon_block_root and aggregate pubkey derived from
|
|
88
87
|
// the participation info in aggregation_bits for the subcommittee specified by the contribution.subcommittee_index.
|
|
@@ -59,7 +59,7 @@ async function validateVoluntaryExit(
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
const signatureSet = getVoluntaryExitSignatureSet(state, voluntaryExit);
|
|
62
|
+
const signatureSet = getVoluntaryExitSignatureSet(chain.index2pubkey, state, voluntaryExit);
|
|
63
63
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
64
64
|
throw new VoluntaryExitError(GossipAction.REJECT, {
|
|
65
65
|
code: VoluntaryExitErrorCode.INVALID_SIGNATURE,
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {Message} from "@libp2p/interface";
|
|
2
2
|
// snappyjs is better for compression for smaller payloads
|
|
3
|
-
import {compress, uncompress} from "snappyjs";
|
|
4
3
|
import xxhashFactory from "xxhash-wasm";
|
|
5
4
|
import {digest} from "@chainsafe/as-sha256";
|
|
6
5
|
import {RPC} from "@chainsafe/libp2p-gossipsub/message";
|
|
7
6
|
import {DataTransform} from "@chainsafe/libp2p-gossipsub/types";
|
|
7
|
+
import snappyWasm from "@chainsafe/snappy-wasm";
|
|
8
8
|
import {ForkName} from "@lodestar/params";
|
|
9
9
|
import {intToBytes} from "@lodestar/utils";
|
|
10
10
|
import {MESSAGE_DOMAIN_VALID_SNAPPY} from "./constants.js";
|
|
11
|
+
import {Eth2GossipsubMetrics} from "./metrics.js";
|
|
11
12
|
import {GossipTopicCache, getGossipSSZType} from "./topic.js";
|
|
12
13
|
|
|
13
14
|
// Load WASM
|
|
@@ -16,6 +17,10 @@ const xxhash = await xxhashFactory();
|
|
|
16
17
|
// Use salt to prevent msgId from being mined for collisions
|
|
17
18
|
const h64Seed = BigInt(Math.floor(Math.random() * 1e9));
|
|
18
19
|
|
|
20
|
+
// create singleton snappy encoder + decoder
|
|
21
|
+
const encoder = new snappyWasm.Encoder();
|
|
22
|
+
const decoder = new snappyWasm.Decoder();
|
|
23
|
+
|
|
19
24
|
// Shared buffer to convert msgId to string
|
|
20
25
|
const sharedMsgIdBuf = Buffer.alloc(20);
|
|
21
26
|
|
|
@@ -70,7 +75,8 @@ export function msgIdFn(gossipTopicCache: GossipTopicCache, msg: Message): Uint8
|
|
|
70
75
|
export class DataTransformSnappy implements DataTransform {
|
|
71
76
|
constructor(
|
|
72
77
|
private readonly gossipTopicCache: GossipTopicCache,
|
|
73
|
-
private readonly maxSizePerMessage: number
|
|
78
|
+
private readonly maxSizePerMessage: number,
|
|
79
|
+
private readonly metrics: Eth2GossipsubMetrics | null
|
|
74
80
|
) {}
|
|
75
81
|
|
|
76
82
|
/**
|
|
@@ -80,13 +86,15 @@ export class DataTransformSnappy implements DataTransform {
|
|
|
80
86
|
* - `outboundTransform()`: compress snappy payload
|
|
81
87
|
*/
|
|
82
88
|
inboundTransform(topicStr: string, data: Uint8Array): Uint8Array {
|
|
83
|
-
|
|
89
|
+
// check uncompressed data length before we actually decompress
|
|
90
|
+
const uncompressedDataLength = snappyWasm.decompress_len(data);
|
|
91
|
+
if (uncompressedDataLength > this.maxSizePerMessage) {
|
|
92
|
+
throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} > ${this.maxSizePerMessage}`);
|
|
93
|
+
}
|
|
84
94
|
|
|
85
|
-
// check uncompressed data length before we extract beacon block root, slot or
|
|
86
|
-
// attestation data at later steps
|
|
87
|
-
const uncompressedDataLength = uncompressedData.length;
|
|
88
95
|
const topic = this.gossipTopicCache.getTopic(topicStr);
|
|
89
96
|
const sszType = getGossipSSZType(topic);
|
|
97
|
+
this.metrics?.dataTransform.inbound.inc({type: topic.type});
|
|
90
98
|
|
|
91
99
|
if (uncompressedDataLength < sszType.minSize) {
|
|
92
100
|
throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} < ${sszType.minSize}`);
|
|
@@ -95,6 +103,10 @@ export class DataTransformSnappy implements DataTransform {
|
|
|
95
103
|
throw Error(`ssz_snappy decoded data length ${uncompressedDataLength} > ${sszType.maxSize}`);
|
|
96
104
|
}
|
|
97
105
|
|
|
106
|
+
// Only after sanity length checks, we can decompress the data
|
|
107
|
+
// Using Buffer.alloc() instead of Buffer.allocUnsafe() to mitigate high GC pressure observed in some environments
|
|
108
|
+
const uncompressedData = Buffer.alloc(uncompressedDataLength);
|
|
109
|
+
decoder.decompress_into(data, uncompressedData);
|
|
98
110
|
return uncompressedData;
|
|
99
111
|
}
|
|
100
112
|
|
|
@@ -102,11 +114,16 @@ export class DataTransformSnappy implements DataTransform {
|
|
|
102
114
|
* Takes the data to be published (a topic and associated data) transforms the data. The
|
|
103
115
|
* transformed data will then be used to create a `RawGossipsubMessage` to be sent to peers.
|
|
104
116
|
*/
|
|
105
|
-
outboundTransform(
|
|
117
|
+
outboundTransform(topicStr: string, data: Uint8Array): Uint8Array {
|
|
118
|
+
const topic = this.gossipTopicCache.getTopic(topicStr);
|
|
119
|
+
this.metrics?.dataTransform.outbound.inc({type: topic.type});
|
|
106
120
|
if (data.length > this.maxSizePerMessage) {
|
|
107
121
|
throw Error(`ssz_snappy encoded data length ${data.length} > ${this.maxSizePerMessage}`);
|
|
108
122
|
}
|
|
109
|
-
|
|
110
|
-
|
|
123
|
+
|
|
124
|
+
// Using Buffer.alloc() instead of Buffer.allocUnsafe() to mitigate high GC pressure observed in some environments
|
|
125
|
+
const compressedData = Buffer.alloc(snappyWasm.max_compress_len(data.length));
|
|
126
|
+
const compressedLen = encoder.compress_into(data, compressedData);
|
|
127
|
+
return compressedData.subarray(0, compressedLen);
|
|
111
128
|
}
|
|
112
129
|
}
|
|
@@ -89,6 +89,13 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
89
89
|
const gossipTopicCache = new GossipTopicCache(config);
|
|
90
90
|
|
|
91
91
|
const scoreParams = computeGossipPeerScoreParams({config, eth2Context: modules.eth2Context});
|
|
92
|
+
let metrics: Eth2GossipsubMetrics | null = null;
|
|
93
|
+
if (metricsRegister) {
|
|
94
|
+
metrics = createEth2GossipsubMetrics(metricsRegister);
|
|
95
|
+
metrics.gossipMesh.peersByType.addCollect(() =>
|
|
96
|
+
this.onScrapeLodestarMetrics(metrics as Eth2GossipsubMetrics, networkConfig)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
92
99
|
|
|
93
100
|
// Gossipsub parameters defined here:
|
|
94
101
|
// https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub
|
|
@@ -116,7 +123,7 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
116
123
|
fastMsgIdFn: fastMsgIdFn,
|
|
117
124
|
msgIdFn: msgIdFn.bind(msgIdFn, gossipTopicCache),
|
|
118
125
|
msgIdToStrFn: msgIdToStrFn,
|
|
119
|
-
dataTransform: new DataTransformSnappy(gossipTopicCache, config.MAX_PAYLOAD_SIZE),
|
|
126
|
+
dataTransform: new DataTransformSnappy(gossipTopicCache, config.MAX_PAYLOAD_SIZE, metrics),
|
|
120
127
|
metricsRegister: metricsRegister as MetricsRegister | null,
|
|
121
128
|
metricsTopicStrToLabel: metricsRegister
|
|
122
129
|
? getMetricsTopicStrToLabel(networkConfig, {disableLightClientServer: opts.disableLightClientServer ?? false})
|
|
@@ -141,11 +148,6 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
141
148
|
this.events = events;
|
|
142
149
|
this.gossipTopicCache = gossipTopicCache;
|
|
143
150
|
|
|
144
|
-
if (metricsRegister) {
|
|
145
|
-
const metrics = createEth2GossipsubMetrics(metricsRegister);
|
|
146
|
-
metrics.gossipMesh.peersByType.addCollect(() => this.onScrapeLodestarMetrics(metrics, networkConfig));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
151
|
this.addEventListener("gossipsub:message", this.onGossipsubMessage.bind(this));
|
|
150
152
|
this.events.on(NetworkEvent.gossipMessageValidationResult, this.onValidationResult.bind(this));
|
|
151
153
|
|
|
@@ -67,5 +67,17 @@ export function createEth2GossipsubMetrics(register: RegistryMetricCreator) {
|
|
|
67
67
|
labelNames: ["subnet", "boundary"],
|
|
68
68
|
}),
|
|
69
69
|
},
|
|
70
|
+
dataTransform: {
|
|
71
|
+
inbound: register.counter<{type: GossipType}>({
|
|
72
|
+
name: "lodestar_gossip_data_transform_inbound_total",
|
|
73
|
+
help: "Total number of inbound data transforms by gossip type",
|
|
74
|
+
labelNames: ["type"],
|
|
75
|
+
}),
|
|
76
|
+
outbound: register.counter<{type: GossipType}>({
|
|
77
|
+
name: "lodestar_gossip_data_transform_outbound_total",
|
|
78
|
+
help: "Total number of outbound data transforms by gossip type",
|
|
79
|
+
labelNames: ["type"],
|
|
80
|
+
}),
|
|
81
|
+
},
|
|
70
82
|
};
|
|
71
83
|
}
|
|
@@ -750,7 +750,9 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
|
|
|
750
750
|
|
|
751
751
|
// GENESIS_SLOT doesn't has valid signature
|
|
752
752
|
if (anchorBlock.message.slot === GENESIS_SLOT) return;
|
|
753
|
-
await verifyBlockProposerSignature(this.chain.bls, this.chain.getHeadState(), [
|
|
753
|
+
await verifyBlockProposerSignature(this.chain.index2pubkey, this.chain.bls, this.chain.getHeadState(), [
|
|
754
|
+
anchorBlock,
|
|
755
|
+
]);
|
|
754
756
|
|
|
755
757
|
// We can write to the disk if this is ahead of prevFinalizedCheckpointBlock otherwise
|
|
756
758
|
// we will need to go make checks on the top of sync loop before writing as it might
|
|
@@ -815,7 +817,12 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
|
|
|
815
817
|
|
|
816
818
|
// If any of the block's proposer signature fail, we can't trust this peer at all
|
|
817
819
|
if (verifiedBlocks.length > 0) {
|
|
818
|
-
await verifyBlockProposerSignature(
|
|
820
|
+
await verifyBlockProposerSignature(
|
|
821
|
+
this.chain.index2pubkey,
|
|
822
|
+
this.chain.bls,
|
|
823
|
+
this.chain.getHeadState(),
|
|
824
|
+
verifiedBlocks
|
|
825
|
+
);
|
|
819
826
|
|
|
820
827
|
// This is bad, like super bad. Abort the backfill
|
|
821
828
|
if (!nextAnchor)
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
2
2
|
import {GENESIS_SLOT} from "@lodestar/params";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CachedBeaconStateAllForks,
|
|
5
|
+
ISignatureSet,
|
|
6
|
+
Index2PubkeyCache,
|
|
7
|
+
getBlockProposerSignatureSet,
|
|
8
|
+
} from "@lodestar/state-transition";
|
|
4
9
|
import {Root, SignedBeaconBlock, Slot, ssz} from "@lodestar/types";
|
|
5
10
|
import {IBlsVerifier} from "../../chain/bls/index.js";
|
|
6
11
|
import {BackfillSyncError, BackfillSyncErrorCode} from "./errors.js";
|
|
@@ -41,6 +46,7 @@ export function verifyBlockSequence(
|
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
export async function verifyBlockProposerSignature(
|
|
49
|
+
index2pubkey: Index2PubkeyCache,
|
|
44
50
|
bls: IBlsVerifier,
|
|
45
51
|
state: CachedBeaconStateAllForks,
|
|
46
52
|
blocks: SignedBeaconBlock[]
|
|
@@ -48,7 +54,7 @@ export async function verifyBlockProposerSignature(
|
|
|
48
54
|
if (blocks.length === 1 && blocks[0].message.slot === GENESIS_SLOT) return;
|
|
49
55
|
const signatures = blocks.reduce((sigs: ISignatureSet[], block) => {
|
|
50
56
|
// genesis block doesn't have valid signature
|
|
51
|
-
if (block.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(state, block));
|
|
57
|
+
if (block.message.slot !== GENESIS_SLOT) sigs.push(getBlockProposerSignatureSet(index2pubkey, state, block));
|
|
52
58
|
return sigs;
|
|
53
59
|
}, []);
|
|
54
60
|
|