Skip to content

Commit

Permalink
Track balances as Number64UintType (#2973)
Browse files Browse the repository at this point in the history
* Track balances as Number64UintType

* Use Number64ListType ssz type, refactor BalanceList

* Use applyDeltaInBatch

* Fix spec & unit tests

* Fix perf test to go with numbered balance

* New ssz, persistent-merkle-tree and fix tests

* Chore: clean up commented code

* Fix test/perf/phase0/epoch/processEffectiveBalanceUpdates.test.ts

Co-authored-by: Lion - dapplion <[email protected]>
  • Loading branch information
twoeths and dapplion authored Aug 31, 2021
1 parent 131c6cc commit 1629df1
Show file tree
Hide file tree
Showing 52 changed files with 303 additions and 297 deletions.
4 changes: 2 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
"@chainsafe/lodestar-params": "^0.29.1",
"@chainsafe/lodestar-types": "^0.29.1",
"@chainsafe/lodestar-utils": "^0.29.1",
"@chainsafe/persistent-merkle-tree": "^0.3.5",
"@chainsafe/ssz": "^0.8.15",
"@chainsafe/persistent-merkle-tree": "^0.3.7",
"@chainsafe/ssz": "^0.8.17",
"cross-fetch": "^3.1.4",
"eventsource": "^1.1.0",
"qs": "^6.10.1"
Expand Down
10 changes: 5 additions & 5 deletions packages/api/src/routes/beacon/state.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ContainerType} from "@chainsafe/ssz";
import {phase0, CommitteeIndex, Slot, ValidatorIndex, Epoch, Root, Gwei, ssz} from "@chainsafe/lodestar-types";
import {phase0, CommitteeIndex, Slot, ValidatorIndex, Epoch, Root, ssz} from "@chainsafe/lodestar-types";
import {
RoutesData,
ReturnTypes,
Expand Down Expand Up @@ -46,14 +46,14 @@ export type FinalityCheckpoints = {

export type ValidatorResponse = {
index: ValidatorIndex;
balance: Gwei;
balance: number;
status: ValidatorStatus;
validator: phase0.Validator;
};

export type ValidatorBalance = {
index: ValidatorIndex;
balance: Gwei;
balance: number;
};

export type EpochCommitteeResponse = {
Expand Down Expand Up @@ -237,7 +237,7 @@ export function getReturnTypes(): ReturnTypes<Api> {
const ValidatorResponse = new ContainerType<ValidatorResponse>({
fields: {
index: ssz.ValidatorIndex,
balance: ssz.Gwei,
balance: ssz.Number64,
status: new StringType<ValidatorStatus>(),
validator: ssz.phase0.Validator,
},
Expand All @@ -246,7 +246,7 @@ export function getReturnTypes(): ReturnTypes<Api> {
const ValidatorBalance = new ContainerType<ValidatorBalance>({
fields: {
index: ssz.ValidatorIndex,
balance: ssz.Gwei,
balance: ssz.Number64,
},
});

Expand Down
2 changes: 1 addition & 1 deletion packages/api/test/unit/beacon.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {runGenericServerTest} from "../utils/genericServerTest";

describe("beacon", () => {
const root = Buffer.alloc(32, 1);
const balance = BigInt(32e9);
const balance = 32e9;
const pubkeyHex = toHexString(Buffer.alloc(48, 1));

const blockHeaderResponse: BlockHeaderResponse = {
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-state-transition/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
"@chainsafe/lodestar-params": "^0.29.1",
"@chainsafe/lodestar-types": "^0.29.1",
"@chainsafe/lodestar-utils": "^0.29.1",
"@chainsafe/persistent-merkle-tree": "^0.3.5",
"@chainsafe/persistent-merkle-tree": "^0.3.7",
"@chainsafe/persistent-ts": "^0.19.0",
"@chainsafe/ssz": "^0.8.15",
"@chainsafe/ssz": "^0.8.17",
"bigint-buffer": "^1.1.5",
"buffer-xor": "^2.0.2"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function processDeposit(
effectiveBalance: bigIntMin(amount - (amount % EFFECTIVE_BALANCE_INCREMENT), MAX_EFFECTIVE_BALANCE),
slashed: false,
});
state.balances.push(amount);
state.balances.push(Number(amount));

// add participation caches
state.previousEpochParticipation.pushStatus({timelyHead: false, timelySource: false, timelyTarget: false});
Expand All @@ -91,6 +91,6 @@ export function processDeposit(
epochCtx.addPubkey(validators.length - 1, pubkey);
} else {
// increase balance by deposit amount
increaseBalance(state, cachedIndex, amount);
increaseBalance(state, cachedIndex, Number(amount));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,20 @@ export function slashValidatorAllForks(

const minSlashingPenaltyQuotient =
fork === ForkName.phase0 ? MIN_SLASHING_PENALTY_QUOTIENT : MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR;
decreaseBalance(state, slashedIndex, effectiveBalance / minSlashingPenaltyQuotient);
decreaseBalance(state, slashedIndex, Number(effectiveBalance / minSlashingPenaltyQuotient));

// apply proposer and whistleblower rewards
const proposerIndex = epochCtx.getBeaconProposer(state.slot);
if (whistleblowerIndex === undefined || !Number.isSafeInteger(whistleblowerIndex)) {
whistleblowerIndex = proposerIndex;
}
// TODO: could be all number here if effectiveBalance is also number
const whistleblowerReward = effectiveBalance / WHISTLEBLOWER_REWARD_QUOTIENT;
const proposerReward =
fork === ForkName.phase0
? whistleblowerReward / PROPOSER_REWARD_QUOTIENT
: (whistleblowerReward * PROPOSER_WEIGHT) / WEIGHT_DENOMINATOR;

increaseBalance(state, proposerIndex, proposerReward);
increaseBalance(state, whistleblowerIndex, whistleblowerReward - proposerReward);
increaseBalance(state, proposerIndex, Number(proposerReward));
increaseBalance(state, whistleblowerIndex, Number(whistleblowerReward - proposerReward));
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ export function processEffectiveBalanceUpdates(
let nextEpochTotalActiveBalance: Gwei = BigInt(0);

// update effective balances with hysteresis
(epochProcess.balances ?? state.balances).forEach((balance: bigint, i: number) => {
if (!epochProcess.balances) {
// only do this for genesis epoch, or spec test
epochProcess.balances = Array.from({length: state.balances.length}, (_, i) => state.balances[i]);
}
epochProcess.balances.forEach((balanceNbr: number, i: number) => {
// TODO: effectiveBalance as number
const balance = BigInt(balanceNbr);
const validator = epochProcess.validators[i];
let effectiveBalance = validator.effectiveBalance;
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ export function processSlashingsAllForks(
const effectiveBalance = process.validators[index].effectiveBalance;
const penaltyNumerator = (effectiveBalance / increment) * adjustedTotalSlashingBalance;
const penalty = (penaltyNumerator / totalBalance) * increment;
decreaseBalance(state, index, penalty);
decreaseBalance(state, index, Number(penalty));
}
}
92 changes: 92 additions & 0 deletions packages/beacon-state-transition/src/allForks/util/balanceList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {List, Number64ListType, TreeBacked} from "@chainsafe/ssz";
import {Tree} from "@chainsafe/persistent-merkle-tree";

/**
* Manage balances of BeaconState.
*/
export class BalanceList implements List<number> {
[index: number]: number;
tree: Tree;
type: Number64ListType;

constructor(type: Number64ListType, tree: Tree) {
this.type = type;
this.tree = tree;
}

get length(): number {
return this.type.tree_getLength(this.tree);
}

get(index: number): number | undefined {
return this.type.tree_getProperty(this.tree, index) as number | undefined;
}

set(index: number, value: number): void {
this.type.tree_setProperty(this.tree, index, value);
}

applyDelta(index: number, delta: number): number {
return this.type.tree_applyDeltaAtIndex(this.tree, index, delta);
}

applyDeltaInBatch(deltaByIndex: Map<number, number>): void {
this.type.tree_applyDeltaInBatch(this.tree, deltaByIndex);
}

/** Return the new balances */
updateAll(deltas: number[]): number[] {
const [newTree, newBalances] = this.type.tree_newTreeFromDeltas(this.tree, deltas);
this.tree.rootNode = newTree.rootNode;
this.type.tree_setLength(this.tree, newBalances.length);
return newBalances;
}

push(value: number): number {
return this.type.tree_push(this.tree, value);
}

pop(): number {
return this.type.tree_pop(this.tree);
}

*[Symbol.iterator](): Iterator<number> {
for (let i = 0; i < this.length; i++) {
yield this.get(i) as number;
}
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
find(fn: (value: number, index: number, list: this) => boolean): number | undefined {
return;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
findIndex(fn: (value: number, index: number, list: this) => boolean): number {
return -1;
}
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export const CachedBalanceListProxyHandler: ProxyHandler<BalanceList> = {
get(target: BalanceList, key: PropertyKey): unknown {
if (!Number.isNaN(Number(String(key)))) {
return target.get(key as number);
} else if (target[key as keyof BalanceList]) {
return target[key as keyof BalanceList];
} else {
const treeBacked = target.type.createTreeBacked(target.tree);
if (key in treeBacked) {
return treeBacked[key as keyof TreeBacked<List<number>>];
}
return undefined;
}
},
set(target: BalanceList, key: PropertyKey, value: number): boolean {
if (!Number.isNaN(Number(key))) {
target.set(key as number, value);
return true;
}
return false;
},
};

This file was deleted.

Loading

0 comments on commit 1629df1

Please sign in to comment.