Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Altair 1.1.0-alpha.5 - Beacon Chain #2554

Merged
merged 25 commits into from
May 28, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9c18ef2
Remove SYNC_PUBKEYS_PER_AGGREGATE
twoeths May 21, 2021
e73acc8
Adjust sync committee size and duration
twoeths May 21, 2021
9672ee1
Use stable sync committee indices when processing block rewards
twoeths May 21, 2021
30e0900
Restrict sync committee period calculation boundaries
twoeths May 21, 2021
5ee16f0
Participation flag and incentive review
twoeths May 21, 2021
e9e0673
Update inactivity penalty deltas processing
twoeths May 21, 2021
f0fff5a
Ensure indices are ordered [source, target, head] everywhere
twoeths May 21, 2021
712c8bd
Map attestation participation to flag deltas in fork transition
twoeths May 21, 2021
fe4cd2c
Fix all current altair spec tests
twoeths May 23, 2021
b324594
Fix lint in beacon-state-transition
twoeths May 24, 2021
8c38e51
Finality phase0 spec tests are removed in altair-1.1.0-alpha.5
twoeths May 24, 2021
81f01ae
Remove duplicate call of getNextSyncCommitteeIndices()
twoeths May 25, 2021
3f40221
Altair-1.1.0-alpha.5 for network and validator
twoeths May 25, 2021
b8f3339
Altair-1.1.0-alpha.5 for Sync Protocol
twoeths May 25, 2021
5604160
Fix processSyncCommittee and add respective spec tests
twoeths May 26, 2021
bc5b470
Add operations minimal spec tests
twoeths May 26, 2021
18a8c96
Fix EpochProcess, add finality minimal spec test
twoeths May 27, 2021
4a92026
Improve the way to access aggregationBits
twoeths May 27, 2021
30f5512
Add fork and fork_choice spec tests
twoeths May 27, 2021
cc659de
Add genesis minimal spec test
twoeths May 27, 2021
7a32963
Add fork transition spec test
twoeths May 28, 2021
16ea02f
SSZ spec test for altair - SyncCommittee
twoeths May 28, 2021
d056d4a
Add expectEqualBeaconState() for altair spec tests
twoeths May 28, 2021
ca63a52
chore: fix yarn check-types
twoeths May 28, 2021
a894416
chore: remove debugged comment
twoeths May 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {allForks} from "@chainsafe/lodestar-types";
import {toHexString} from "@chainsafe/ssz";
import {CachedBeaconState} from "../util";

export function processBlockHeader(state: CachedBeaconState<allForks.BeaconState>, block: allForks.BeaconBlock): void {
Expand Down Expand Up @@ -31,7 +32,9 @@ export function processBlockHeader(state: CachedBeaconState<allForks.BeaconState
state.config.types.phase0.BeaconBlockHeader.hashTreeRoot(state.latestBlockHeader)
)
) {
throw new Error("Block parent root does not match state latest block");
throw new Error(
`Block parent root ${toHexString(block.parentRoot)} does not match state latest block, block slot=${slot}`
);
}
// cache current block as the new latest block
state.latestBlockHeader = {
Expand Down
34 changes: 20 additions & 14 deletions packages/beacon-state-transition/src/allForks/util/epochContext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ByteVector, hash, toHexString, BitList, List, readonlyValues} from "@chainsafe/ssz";
import {ByteVector, hash, toHexString, BitList, List, isTreeBacked, TreeBacked} from "@chainsafe/ssz";
import bls, {CoordType, PublicKey} from "@chainsafe/bls";
import {
BLSSignature,
Expand All @@ -19,10 +19,10 @@ import {
computeEpochAtSlot,
computeProposerIndex,
computeStartSlotAtEpoch,
getAttestingIndicesFromCommittee,
getSeed,
getTotalActiveBalance,
isAggregatorFromCommitteeLength,
zipIndexesInBitList,
} from "../../util";
import {getNextSyncCommitteeIndices} from "../../altair/state_accessor/sync_committee";
import {computeEpochShuffling, IEpochShuffling} from "./epochShuffling";
Expand Down Expand Up @@ -373,16 +373,15 @@ export class EpochContext {
* Return the indexed attestation corresponding to ``attestation``.
*/
getIndexedAttestation(attestation: phase0.Attestation): phase0.IndexedAttestation {
const data = attestation.data;
const bits = Array.from(readonlyValues(attestation.aggregationBits));
const committee = this.getBeaconCommittee(data.slot, data.index);
// No need for a Set, the indices in the committee are already unique.
const attestingIndices: ValidatorIndex[] = [];
for (const [i, index] of committee.entries()) {
if (bits[i]) {
attestingIndices.push(index);
}
}
const {aggregationBits, data} = attestation;
const committeeIndices = this.getBeaconCommittee(data.slot, data.index);
const attestingIndices = isTreeBacked(attestation)
? zipIndexesInBitList(
committeeIndices,
(attestation.aggregationBits as unknown) as TreeBacked<BitList>,
this.config.types.phase0.CommitteeBits
)
: committeeIndices.filter((_, index) => !!aggregationBits[index]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a hot path in the state transition function we should keep using a for loop for speed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use zipIndexesInBitList to improve performance

fn: () => zipIndexesInBitList(config, indexes, bitlistTree),

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right! I was refering to the alternative path when it's not a tree

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If aggregationBits should always be a tree then the filter is fine

// sort in-place
attestingIndices.sort((a, b) => a - b);
return {
Expand All @@ -393,8 +392,15 @@ export class EpochContext {
}

getAttestingIndices(data: phase0.AttestationData, bits: BitList): ValidatorIndex[] {
const committee = this.getBeaconCommittee(data.slot, data.index);
return getAttestingIndicesFromCommittee(committee, Array.from(readonlyValues(bits)) as List<boolean>);
const committeeIndices = this.getBeaconCommittee(data.slot, data.index);
const validatorIndices = isTreeBacked(bits)
? zipIndexesInBitList(
committeeIndices,
(bits as unknown) as TreeBacked<BitList>,
this.config.types.phase0.CommitteeBits
)
: committeeIndices.filter((_, index) => !!bits[index]);
return validatorIndices;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
zipIndexesInBitList,
} from "../../util";
import {CachedBeaconState} from "../../allForks/util";
import {BitList, TreeBacked} from "@chainsafe/ssz";
import {BitList, isTreeBacked, TreeBacked} from "@chainsafe/ssz";

export function processSyncCommittee(
state: CachedBeaconState<altair.BeaconState>,
Expand All @@ -22,11 +22,14 @@ export function processSyncCommittee(
const {syncParticipantReward, syncProposerReward} = epochCtx;
const previousSlot = Math.max(state.slot, 1) - 1;
const committeeIndices = state.currSyncCommitteeIndexes;
const participantIndices = zipIndexesInBitList(
committeeIndices,
aggregate.syncCommitteeBits as TreeBacked<BitList>,
config.types.altair.SyncCommitteeBits
);
// the only time aggregate is not a TreeBacked is when producing a new block
const participantIndices = isTreeBacked(aggregate)
? zipIndexesInBitList(
committeeIndices,
aggregate.syncCommitteeBits as TreeBacked<BitList>,
config.types.altair.SyncCommitteeBits
)
: committeeIndices.filter((index) => !!aggregate.syncCommitteeBits[index]);
const participantPubkeys = participantIndices.map((validatorIndex) => state.validators[validatorIndex].pubkey);
const domain = getDomain(
config,
Expand Down
21 changes: 18 additions & 3 deletions packages/beacon-state-transition/src/util/genesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {processDeposit as altairProcessDeposit} from "../naive/altair";
import {computeEpochAtSlot} from "./epoch";
import {getActiveValidatorIndices} from "./validator";
import {getTemporaryBlockHeader} from "./blockRoot";
import {getNextSyncCommittee} from "../altair/state_accessor";

// TODO: Refactor to work with non-phase0 genesis state

Expand Down Expand Up @@ -48,8 +49,15 @@ export function getGenesisBeaconState(
// MISC
state.slot = GENESIS_SLOT;
const version = config.getForkVersion(GENESIS_SLOT);
const forkName = config.getForkName(GENESIS_SLOT);
const allForkNames = Object.keys(config.forks) as ForkName[];
const forkIndex = allForkNames.findIndex((item) => item === forkName);
const previousForkIndex = Math.max(0, forkIndex - 1);
const previousForkName = allForkNames[previousForkIndex];
const previousFork = config.forks[previousForkName];
// the altair genesis spec test requires previous version to be phase0 although ALTAIR_FORK_EPOCH=0
state.fork = {
previousVersion: version,
previousVersion: previousFork.version,
currentVersion: version,
epoch: computeEpochAtSlot(config, GENESIS_SLOT),
} as phase0.Fork;
Expand All @@ -62,7 +70,6 @@ export function getGenesisBeaconState(
// Ethereum 1.0 chain data
state.eth1Data = genesisEth1Data;
state.randaoMixes = randaoMixes;

return state as TreeBacked<allForks.BeaconState>;
}

Expand Down Expand Up @@ -187,5 +194,13 @@ export function initializeBeaconStateFromEth1(
// Process deposits
applyDeposits(config, state, deposits);

return state;
if (config.getForkName(GENESIS_SLOT) === ForkName.altair) {
const syncCommittees = getNextSyncCommittee(config, state);
const altairState = state as TreeBacked<altair.BeaconState>;
altairState.currentSyncCommittee = syncCommittees;
altairState.nextSyncCommittee = syncCommittees;
return altairState as TreeBacked<allForks.BeaconState>;
} else {
return state;
}
}
7 changes: 7 additions & 0 deletions packages/spec-test-runner/test/spec/altair/fork/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {altair, phase0} from "@chainsafe/lodestar-types";
import {IBaseSpecTest} from "../../type";

export interface IUpgradeStateCase extends IBaseSpecTest {
pre: phase0.BeaconState;
post: altair.BeaconState;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {join} from "path";
import {expect} from "chai";

import {TreeBacked} from "@chainsafe/ssz";
import {config} from "@chainsafe/lodestar-config/minimal";
import {allForks, altair, phase0} from "@chainsafe/lodestar-beacon-state-transition";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
import {IUpgradeStateCase} from "./type";
import {upgradeState} from "@chainsafe/lodestar-beacon-state-transition/lib/altair";
import {SPEC_TEST_LOCATION} from "../../../utils/specTestCases";

describeDirectorySpecTest<IUpgradeStateCase, altair.BeaconState>(
"upgrade state to altair",
join(SPEC_TEST_LOCATION, "/tests/minimal/altair/fork/fork/pyspec_tests"),
(testcase) => {
const phase0State = allForks.createCachedBeaconState<phase0.BeaconState>(
config,
testcase.pre as TreeBacked<phase0.BeaconState>
);
return upgradeState(phase0State);
},
{
inputTypes: {
pre: {
type: InputType.SSZ_SNAPPY,
treeBacked: true,
},
post: {
type: InputType.SSZ_SNAPPY,
treeBacked: true,
},
meta: InputType.YAML,
},
sszTypes: {
pre: config.types.phase0.BeaconState,
post: config.types.altair.BeaconState,
},

timeout: 100000000,
dapplion marked this conversation as resolved.
Show resolved Hide resolved
shouldError: (testCase) => !testCase.post,
getExpected: (testCase) => testCase.post,
expectFunc: (testCase, expected, actual) => {
expect(config.types.altair.BeaconState.equals(actual, expected)).to.be.true;
},
}
);
Loading