Skip to content

Commit

Permalink
Merge branch 'master' into dapplion/synccommitte-sigset
Browse files Browse the repository at this point in the history
  • Loading branch information
dapplion committed Jun 2, 2021
2 parents a36ee92 + 575e845 commit c40e91a
Show file tree
Hide file tree
Showing 30 changed files with 153 additions and 96 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {allForks} from "@chainsafe/lodestar-types";
import {computeSigningRoot, getDomain} from "../../util";
import {computeEpochAtSlot, computeSigningRoot, getDomain} from "../../util";
import {ISignatureSet, SignatureSetType, verifySignatureSet} from "../../util/signatureSets";
import {CachedBeaconState} from "../util";

Expand All @@ -16,7 +16,8 @@ export function getProposerSignatureSet(
signedBlock: allForks.SignedBeaconBlock
): ISignatureSet {
const {config, epochCtx} = state;
const domain = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER);
const epochSig = computeEpochAtSlot(config, signedBlock.message.slot);
const domain = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER, epochSig);

return {
type: SignatureSetType.single,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export function getProposerSlashingSignatureSets(

return [proposerSlashing.signedHeader1, proposerSlashing.signedHeader2].map(
(signedHeader): ISignatureSet => {
const epoch = computeEpochAtSlot(config, signedHeader.message.slot);
const domain = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER, epoch);
const epochSig = computeEpochAtSlot(config, signedHeader.message.slot);
const domain = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER, epochSig);
const beaconBlockHeaderType = config.types.phase0.BeaconBlockHeader;

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function getRandaoRevealSignatureSet(
const {config, epochCtx} = state;
// should not get epoch from epochCtx
const epoch = computeEpochAtSlot(config, block.slot);
const domain = getDomain(config, state, config.params.DOMAIN_RANDAO);
const domain = getDomain(config, state, config.params.DOMAIN_RANDAO, epoch);

return {
type: SignatureSetType.single,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export function processSyncCommittee(
verifySignatures = true
): void {
const {syncParticipantReward, syncProposerReward} = state.epochCtx;
// the only time aggregate is not a TreeBacked is when producing a new block
const participantIndices = getParticipantIndices(state, syncAggregate);

// different from the spec but not sure how to get through signature verification for default/empty SyncAggregate in the spec test
Expand Down Expand Up @@ -49,7 +48,6 @@ export function getSyncCommitteeSignatureSet(
const previousSlot = Math.max(state.slot, 1) - 1;
const rootSigned = getBlockRootAtSlot(config, state, previousSlot);

// the only time aggregate is not a TreeBacked is when producing a new block
if (!participantIndices) {
participantIndices = getParticipantIndices(state, syncAggregate);
}
Expand Down Expand Up @@ -77,6 +75,7 @@ function getParticipantIndices(
): number[] {
const committeeIndices = state.currSyncCommitteeIndexes;

// the only time aggregate is not a TreeBacked is when producing a new block
return isTreeBacked(syncAggregate)
? zipIndexesInBitList(
committeeIndices,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ export function processRandao(
body: phase0.BeaconBlockBody,
verifySignature = true
): void {
const currentEpoch = getCurrentEpoch(config, state);
const stateEpoch = getCurrentEpoch(config, state);
const proposer = state.validators[getBeaconProposerIndex(config, state)];
const domain = getDomain(config, state, config.params.DOMAIN_RANDAO);
const signingRoot = computeSigningRoot(config, config.types.Epoch, currentEpoch, domain);
const domain = getDomain(config, state, config.params.DOMAIN_RANDAO, stateEpoch);
const signingRoot = computeSigningRoot(config, config.types.Epoch, stateEpoch, domain);
// Verify RANDAO reveal
assert.true(
!verifySignature ||
bls.verify(proposer.pubkey.valueOf() as Uint8Array, signingRoot, body.randaoReveal.valueOf() as Uint8Array),
"Invalid RANDAO reveal"
);
// Mix it in
state.randaoMixes[currentEpoch % config.params.EPOCHS_PER_HISTORICAL_VECTOR] = xor(
Buffer.from(getRandaoMix(config, state, currentEpoch) as Uint8Array),
state.randaoMixes[stateEpoch % config.params.EPOCHS_PER_HISTORICAL_VECTOR] = xor(
Buffer.from(getRandaoMix(config, state, stateEpoch) as Uint8Array),
Buffer.from(hash(body.randaoReveal.valueOf() as Uint8Array))
);
}
4 changes: 3 additions & 1 deletion packages/beacon-state-transition/src/util/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import bls from "@chainsafe/bls";
import {IBeaconConfig} from "@chainsafe/lodestar-config";
import {allForks} from "@chainsafe/lodestar-types";
import {getDomain} from "./domain";
import {computeEpochAtSlot} from "./epoch";
import {computeSigningRoot} from "./signingRoot";

export function verifyBlockSignature(
config: IBeaconConfig,
state: allForks.BeaconState,
signedBlock: allForks.SignedBeaconBlock
): boolean {
const domain = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER);
const epochSig = computeEpochAtSlot(config, signedBlock.message.slot);
const domain = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER, epochSig);
const blockType = config.getForkTypes(signedBlock.message.slot).BeaconBlock;
const signingRoot = computeSigningRoot(config, blockType, signedBlock.message, domain);
const proposer = state.validators[signedBlock.message.proposerIndex];
Expand Down
6 changes: 2 additions & 4 deletions packages/beacon-state-transition/src/util/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {IBeaconConfig} from "@chainsafe/lodestar-config";

import {ZERO_HASH} from "../constants";

import {getCurrentEpoch} from "./epoch";
import {computeForkDataRoot} from "./fork";

/**
Expand Down Expand Up @@ -39,9 +38,8 @@ export function getDomain(
config: IBeaconConfig,
state: allForks.BeaconState,
domainType: DomainType,
messageEpoch: Epoch | null = null
messageEpoch: Epoch
): Buffer {
const epoch = messageEpoch ?? getCurrentEpoch(config, state);
const forkVersion = getForkVersion(state.fork, epoch);
const forkVersion = getForkVersion(state.fork, messageEpoch);
return computeDomain(config, domainType, forkVersion, state.genesisValidatorsRoot);
}
20 changes: 7 additions & 13 deletions packages/beacon-state-transition/src/util/validatorStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,14 @@ export function isValidProposerSlashing(
if (!verifySignatures) {
return true;
}
const domain = getDomain(
config,
state,
config.params.DOMAIN_BEACON_PROPOSER,
computeEpochAtSlot(config, header1.slot)
);

const epochSig1 = computeEpochAtSlot(config, header1.slot);
const domain1 = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER, epochSig1);
const signingRoot = computeSigningRoot(
config,
config.types.phase0.BeaconBlockHeader,
proposerSlashing.signedHeader1.message,
domain
domain1
);
const proposalData1Verified = bls.verify(
proposer.pubkey.valueOf() as Uint8Array,
Expand All @@ -150,12 +147,9 @@ export function isValidProposerSlashing(
if (!proposalData1Verified) {
return false;
}
const domain2 = getDomain(
config,
state,
config.params.DOMAIN_BEACON_PROPOSER,
computeEpochAtSlot(config, header2.slot)
);

const epochSig2 = computeEpochAtSlot(config, header2.slot);
const domain2 = getDomain(config, state, config.params.DOMAIN_BEACON_PROPOSER, epochSig2);
const signingRoot2 = computeSigningRoot(
config,
config.types.phase0.BeaconBlockHeader,
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/networks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {IBeaconParamsUnparsed} from "../config/types";
import * as mainnet from "./mainnet";
import * as pyrmont from "./pyrmont";
import * as prater from "./prater";
import * as coorparoo from "./coorparoo";
import * as oonoonba from "./oonoonba";

export type NetworkName = "mainnet" | "pyrmont" | "prater" | "dev" | "coorparoo";
export const networkNames: NetworkName[] = ["mainnet", "pyrmont", "prater", "coorparoo"];
export type NetworkName = "mainnet" | "pyrmont" | "prater" | "dev" | "oonoonba";
export const networkNames: NetworkName[] = ["mainnet", "pyrmont", "prater", "oonoonba"];

function getNetworkData(
network: NetworkName
Expand All @@ -26,8 +26,8 @@ function getNetworkData(
return pyrmont;
case "prater":
return prater;
case "coorparoo":
return coorparoo;
case "oonoonba":
return oonoonba;
default:
throw Error(`Network not supported: ${network}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export const beaconParams: IBeaconParamsUnparsed = {
MAX_EFFECTIVE_BALANCE: 32000000000,
EJECTION_BALANCE: 16000000000,
EFFECTIVE_BALANCE_INCREMENT: 1000000000,
GENESIS_FORK_VERSION: "0x00004151",
GENESIS_FORK_VERSION: "0x00004811",
BLS_WITHDRAWAL_PREFIX: "0x00",
GENESIS_DELAY: 1020129,
GENESIS_DELAY: 1100642,
SECONDS_PER_SLOT: 12,
MIN_ATTESTATION_INCLUSION_DELAY: 1,
SLOTS_PER_EPOCH: 32,
Expand Down Expand Up @@ -78,20 +78,20 @@ export const beaconParams: IBeaconParamsUnparsed = {
DOMAIN_SYNC_COMMITTEE: "0x07000000",
DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF: "0x08000000",
DOMAIN_CONTRIBUTION_AND_PROOF: "0x09000000",
ALTAIR_FORK_VERSION: "0x01004151",
ALTAIR_FORK_VERSION: "0x01004811",
ALTAIR_FORK_EPOCH: 10,
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: 4,
};

export const depositContractDeployBlock = 4823811;
export const genesisFileUrl =
"https://raw.githubusercontent.com/ajsutton/eth2-networks/4a58c1852e3add6551b5cae3f260087efd6078e4/teku/coorparoo/genesis.ssz";
"https://raw.githubusercontent.com/eth2-clients/eth2-networks/master/teku/oonoonba/genesis.ssz";
export const bootnodesFileUrl =
"https://raw.githubusercontent.com/ajsutton/eth2-networks/4a58c1852e3add6551b5cae3f260087efd6078e4/teku/coorparoo/boot_enr.yaml";
"https://raw.githubusercontent.com/eth2-clients/eth2-networks/master/teku/oonoonba/boot_enr.yaml";

export const bootEnrs = [
// /ip4/18.216.199.235/tcp/9000/p2p/16Uiu2HAm9e3CaYN8XxvjFEyHFd1aiE3FUTfMpL6Z2vMfnBQieXVs
"enr:-KG4QGtLfpaTMJKBD8_VTE0ZBf24KoVrnT-Toc5K6IuQwUm2WQShEmmjEwZc1B3J3muXaDoIYt3Qty9xEFCdvKeOq1sDhGV0aDKQFmWbwwAAQVH__________4JpZIJ2NIJpcIQS2MfriXNlY3AyNTZrMaEC0y6UqTmdr_Jw_4L_bi1Tlp9i-WT5T8MKHs0r77RUonqDdGNwgiMog3VkcIIjKA",
// /ip4/18.222.144.13/tcp/9000/p2p/16Uiu2HAmAt2JM9UjsFMUHkqmN51dE7bHTsmoqbTKcM6QeJceuVm
"enr:-KG4QOWkRj93eXbzMLc6Jvps6lXzlIq6CFmYQJV93QtkglAUf6C2myzSU8Zzay1iYxvQp0w3FD5XLQnitMtIIEwhJwgDhGV0aDKQFmWbwwAAQVH__________4JpZIJ2NIJpcIQS3pANiXNlY3AyNTZrMaEC5Z9hdyMHa64JhYZFVf40uI9BnzKWd2Y_NNG9sUcs0gWDdGNwgiMog3VkcIIjKA",
// /ip4/18.216.199.235/tcp/9000/p2p/16Uiu2HAm5nt57D6THGW2tRTLjCjAizk83DuLNMv6NTabdzEAGj7C
"enr:-KG4QLXhcaTSEqPF-g5T_t-7NJJ6DQTHy8yCV-vvjJHU7jwOUpGMdIcvlKB4roS9qG1mi-P38Pvq1GkHYblRpOvfi6UDhGV0aDKQk_tI4gEASBEKAAAAAAAAAIJpZIJ2NIJpcIQS2MfriXNlY3AyNTZrMaECmgO9ATicNnBAl0Z1wKtbfvVlxv70aiJ7Obx_bFyhGpeDdGNwgiMog3VkcIIjKA",
// /ip4/18.222.144.13/tcp/9000/p2p/16Uiu2HAmVVTsqNyKU9kuf71ZCRq3zFkFUpDaukdRaiGwSDGLq5MF
"enr:-KG4QKHoILkdRrVT253n_S_cWB9K27hKGfQBUjT7Vw_dpTj2Y7BtIcEshnlj4fERg9IDer8CzwLjpCM809ZJ0Qym7dMDhGV0aDKQk_tI4gEASBEKAAAAAAAAAIJpZIJ2NIJpcIQS3pANiXNlY3AyNTZrMaED-iX-fx0c0RglNfwWG7N-K3oI-3JXM2O0Nyd67D5U1raDdGNwgiMog3VkcIIjKA",
];
12 changes: 12 additions & 0 deletions packages/cli/src/options/beaconNodeOptions/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import {ICliCommandOptions} from "../../util";

export interface IChainArgs {
"chain.useSingleThreadVerifier": boolean;
"chain.disableBlsBatchVerify": boolean;
}

export function parseArgs(args: IChainArgs): IBeaconNodeOptions["chain"] {
return {
useSingleThreadVerifier: args["chain.useSingleThreadVerifier"],
disableBlsBatchVerify: args["chain.disableBlsBatchVerify"],
};
}

Expand All @@ -19,4 +21,14 @@ export const options: ICliCommandOptions<IChainArgs> = {
defaultDescription: String(defaultOptions.chain.useSingleThreadVerifier),
group: "chain",
},

"chain.disableBlsBatchVerify": {
hidden: true,
type: "boolean",
description:
"Do not use BLS batch verify to validate all block signatures at once. \
Will double processing times. Use only for debugging purposes.",
defaultDescription: String(defaultOptions.chain.disableBlsBatchVerify),
group: "chain",
},
};
11 changes: 11 additions & 0 deletions packages/cli/src/options/beaconNodeOptions/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import {ICliCommandOptions} from "../../util";

export interface ISyncArgs {
"sync.isSingleNode": boolean;
"sync.disableProcessAsChainSegment": boolean;
}

export function parseArgs(args: ISyncArgs): IBeaconNodeOptions["sync"] {
return {
isSingleNode: args["sync.isSingleNode"],
disableProcessAsChainSegment: args["sync.disableProcessAsChainSegment"],
};
}

Expand All @@ -21,4 +23,13 @@ Use only for local networks with a single node, can be dangerous in regular netw
defaultDescription: String(defaultOptions.sync.isSingleNode),
group: "sync",
},

"sync.disableProcessAsChainSegment": {
hidden: true,
type: "boolean",
description:
"For RangeSync disable processing batches of blocks at once. Should only be used for debugging or testing.",
defaultDescription: String(defaultOptions.sync.disableProcessAsChainSegment),
group: "sync",
},
};
4 changes: 4 additions & 0 deletions packages/cli/test/unit/options/beaconNodeOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe("options / beaconNodeOptions", () => {
"api.rest.port": 7654,

"chain.useSingleThreadVerifier": true,
"chain.disableBlsBatchVerify": true,

"eth1.enabled": true,
"eth1.providerUrl": "http://my.node:8545",
Expand All @@ -37,6 +38,7 @@ describe("options / beaconNodeOptions", () => {
"network.localMultiaddrs": [],

"sync.isSingleNode": true,
"sync.disableProcessAsChainSegment": true,
} as IBeaconNodeArgs;

const expectedOptions: RecursivePartial<IBeaconNodeOptions> = {
Expand All @@ -51,6 +53,7 @@ describe("options / beaconNodeOptions", () => {
},
chain: {
useSingleThreadVerifier: true,
disableBlsBatchVerify: true,
},
eth1: {
enabled: true,
Expand Down Expand Up @@ -82,6 +85,7 @@ describe("options / beaconNodeOptions", () => {
},
sync: {
isSingleNode: true,
disableProcessAsChainSegment: true,
},
};

Expand Down
27 changes: 18 additions & 9 deletions packages/lodestar/src/chain/blocks/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@ import {allForks, ISignatureSet, CachedBeaconState} from "@chainsafe/lodestar-be
import {CheckpointStateCache} from "../stateCache";
import {IMetrics} from "../../metrics";

type BlockProcessorModules = {
export type BlockProcessOpts = {
/**
* Do not use BLS batch verify to validate all block signatures at once.
* Will double processing times. Use only for debugging purposes.
*/
disableBlsBatchVerify?: boolean;
};

export type BlockProcessModules = {
bls: IBlsVerifier;
checkpointStateCache: CheckpointStateCache;
config: IBeaconConfig;
forkChoice: IForkChoice;
regen: IStateRegenerator;
emitter: ChainEventEmitter;
checkpointStateCache: CheckpointStateCache;
bls: IBlsVerifier;
forkChoice: IForkChoice;
metrics: IMetrics | null;
regen: IStateRegenerator;
opts?: BlockProcessOpts;
};

export async function processBlock(
{forkChoice, regen, emitter, checkpointStateCache, bls, metrics}: BlockProcessorModules,
{forkChoice, regen, emitter, checkpointStateCache, bls, metrics, opts}: BlockProcessModules,
job: IBlockJob
): Promise<void> {
if (!forkChoice.hasBlock(job.signedBlock.message.parentRoot)) {
Expand All @@ -37,7 +46,7 @@ export async function processBlock(
try {
const preState = await regen.getPreState(job.signedBlock.message);

if (!job.validSignatures) {
if (!job.validSignatures && !opts?.disableBlsBatchVerify) {
const signatureSets = job.validProposerSignature
? allForks.getAllBlockSignatureSetsExceptProposer(
preState as CachedBeaconState<allForks.BeaconState>,
Expand Down Expand Up @@ -78,7 +87,7 @@ export async function processBlock(
}

export async function processChainSegment(
{config, forkChoice, regen, emitter, checkpointStateCache, bls, metrics}: BlockProcessorModules,
{config, forkChoice, regen, emitter, checkpointStateCache, bls, metrics, opts}: BlockProcessModules,
job: IChainSegmentJob
): Promise<void> {
let importedBlocks = 0;
Expand Down Expand Up @@ -113,7 +122,7 @@ export async function processChainSegment(
let preState = await regen.getPreState(firstBlock.message);

// Verify the signature of the blocks, returning early if the signature is invalid.
if (!job.validSignatures) {
if (!job.validSignatures && !opts?.disableBlsBatchVerify) {
const signatureSets: ISignatureSet[] = [];
for (const block of blocksInEpoch) {
signatureSets.push(
Expand Down

0 comments on commit c40e91a

Please sign in to comment.