diff --git a/packages/api/src/beacon/routes/beacon/index.ts b/packages/api/src/beacon/routes/beacon/index.ts index 4354f086bd56..2e0326b3e13a 100644 --- a/packages/api/src/beacon/routes/beacon/index.ts +++ b/packages/api/src/beacon/routes/beacon/index.ts @@ -13,13 +13,6 @@ export {block, pool, state, rewards}; export type {BlockHeaderResponse, BlockId} from "./block.js"; export {BroadcastValidation} from "./block.js"; -export type { - AttestationsRewards, - BlockRewards, - IdealAttestationsReward, - SyncCommitteeRewards, - TotalAttestationsReward, -} from "./rewards.js"; // TODO: Review if re-exporting all these types is necessary export type { EpochCommitteeResponse, diff --git a/packages/api/src/beacon/routes/beacon/pool.ts b/packages/api/src/beacon/routes/beacon/pool.ts index ee43280d73bb..aa15390c2d97 100644 --- a/packages/api/src/beacon/routes/beacon/pool.ts +++ b/packages/api/src/beacon/routes/beacon/pool.ts @@ -2,6 +2,7 @@ import {ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {ForkPostElectra, ForkPreElectra, isForkPostElectra} from "@lodestar/params"; import { + ArrayOf, AttesterSlashing, CommitteeIndex, SingleAttestation, @@ -12,7 +13,6 @@ import { ssz, } from "@lodestar/types"; import { - ArrayOf, EmptyArgs, EmptyMeta, EmptyMetaCodec, diff --git a/packages/api/src/beacon/routes/beacon/rewards.ts b/packages/api/src/beacon/routes/beacon/rewards.ts index 4335b5886c95..1a2ba2310851 100644 --- a/packages/api/src/beacon/routes/beacon/rewards.ts +++ b/packages/api/src/beacon/routes/beacon/rewards.ts @@ -1,112 +1,20 @@ -import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; -import {Epoch, ssz} from "@lodestar/types"; -import {ArrayOf, JsonOnlyReq} from "../../../utils/codecs.js"; +import { + AttestationsRewards, + AttestationsRewardsType, + BlockRewards, + BlockRewardsType, + Epoch, + SyncCommitteeRewards, + SyncCommitteeRewardsType, +} from "@lodestar/types"; +import {JsonOnlyReq} from "../../../utils/codecs.js"; import {Endpoint, RouteDefinitions, Schema} from "../../../utils/index.js"; import {ExecutionOptimisticAndFinalizedCodec, ExecutionOptimisticAndFinalizedMeta} from "../../../utils/metadata.js"; import {fromValidatorIdsStr, toValidatorIdsStr} from "../../../utils/serdes.js"; import {BlockArgs} from "./block.js"; import {ValidatorId} from "./state.js"; -const BlockRewardsType = new ContainerType( - { - /** Proposer of the block, the proposer index who receives these rewards */ - proposerIndex: ssz.ValidatorIndex, - /** Total block reward, equal to attestations + sync_aggregate + proposer_slashings + attester_slashings */ - total: ssz.UintNum64, - /** Block reward component due to included attestations */ - attestations: ssz.UintNum64, - /** Block reward component due to included sync_aggregate */ - syncAggregate: ssz.UintNum64, - /** Block reward component due to included proposer_slashings */ - proposerSlashings: ssz.UintNum64, - /** Block reward component due to included attester_slashings */ - attesterSlashings: ssz.UintNum64, - }, - {jsonCase: "eth2"} -); - -const AttestationsRewardType = new ContainerType( - { - /** Reward for head vote. Could be negative to indicate penalty */ - head: ssz.UintNum64, - /** Reward for target vote. Could be negative to indicate penalty */ - target: ssz.UintNum64, - /** Reward for source vote. Could be negative to indicate penalty */ - source: ssz.UintNum64, - /** Inclusion delay reward (phase0 only) */ - inclusionDelay: ssz.UintNum64, - /** Inactivity penalty. Should be a negative number to indicate penalty */ - inactivity: ssz.UintNum64, - }, - {jsonCase: "eth2"} -); - -const IdealAttestationsRewardsType = new ContainerType( - { - ...AttestationsRewardType.fields, - effectiveBalance: ssz.UintNum64, - }, - {jsonCase: "eth2"} -); - -const TotalAttestationsRewardsType = new ContainerType( - { - ...AttestationsRewardType.fields, - validatorIndex: ssz.ValidatorIndex, - }, - {jsonCase: "eth2"} -); - -const AttestationsRewardsType = new ContainerType( - { - idealRewards: ArrayOf(IdealAttestationsRewardsType), - totalRewards: ArrayOf(TotalAttestationsRewardsType), - }, - {jsonCase: "eth2"} -); - -const SyncCommitteeRewardsType = ArrayOf( - new ContainerType( - { - validatorIndex: ssz.ValidatorIndex, - reward: ssz.UintNum64, - }, - {jsonCase: "eth2"} - ) -); - -/** - * Rewards info for a single block. Every reward value is in Gwei. - */ -export type BlockRewards = ValueOf; - -/** - * Rewards for a single set of (ideal or actual depending on usage) attestations. Reward value is in Gwei - */ -export type AttestationsReward = ValueOf; - -/** - * Rewards info for ideal attestations ie. Maximum rewards could be earned by making timely head, target and source vote. - * `effectiveBalance` is in Gwei - */ -export type IdealAttestationsReward = ValueOf; - -/** - * Rewards info for actual attestations - */ -export type TotalAttestationsReward = ValueOf; - -export type AttestationsRewards = ValueOf; - -/** - * Rewards info for sync committee participation. Every reward value is in Gwei. - * Note: In the case that block proposer is present in `SyncCommitteeRewards`, the reward value only reflects rewards for - * participating in sync committee. Please refer to `BlockRewards.syncAggregate` for rewards of proposer including sync committee - * outputs into their block - */ -export type SyncCommitteeRewards = ValueOf; - export type Endpoints = { /** * Get block rewards diff --git a/packages/api/src/beacon/routes/beacon/state.ts b/packages/api/src/beacon/routes/beacon/state.ts index e2b05ae0dfab..79c82b7935c8 100644 --- a/packages/api/src/beacon/routes/beacon/state.ts +++ b/packages/api/src/beacon/routes/beacon/state.ts @@ -2,6 +2,7 @@ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {MAX_VALIDATORS_PER_COMMITTEE} from "@lodestar/params"; import { + ArrayOf, CommitteeIndex, Epoch, RootHex, @@ -13,7 +14,7 @@ import { phase0, ssz, } from "@lodestar/types"; -import {ArrayOf, JsonOnlyReq} from "../../../utils/codecs.js"; +import {JsonOnlyReq} from "../../../utils/codecs.js"; import {Endpoint, RequestCodec, RouteDefinitions, Schema} from "../../../utils/index.js"; import { ExecutionOptimisticAndFinalizedCodec, diff --git a/packages/api/src/beacon/routes/config.ts b/packages/api/src/beacon/routes/config.ts index 923070f432f9..a53b7878cc52 100644 --- a/packages/api/src/beacon/routes/config.ts +++ b/packages/api/src/beacon/routes/config.ts @@ -1,8 +1,7 @@ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig, SpecJson} from "@lodestar/config"; -import {ssz} from "@lodestar/types"; +import {ArrayOf, ssz} from "@lodestar/types"; import { - ArrayOf, EmptyArgs, EmptyMeta, EmptyMetaCodec, diff --git a/packages/api/src/beacon/routes/debug.ts b/packages/api/src/beacon/routes/debug.ts index b9512564716c..bd09548534a7 100644 --- a/packages/api/src/beacon/routes/debug.ts +++ b/packages/api/src/beacon/routes/debug.ts @@ -1,8 +1,7 @@ import {ContainerType, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; -import {BeaconState, StringType, fulu, ssz} from "@lodestar/types"; +import {ArrayOf, BeaconState, StringType, fulu, ssz} from "@lodestar/types"; import { - ArrayOf, EmptyArgs, EmptyMeta, EmptyMetaCodec, diff --git a/packages/api/src/beacon/routes/lodestar.ts b/packages/api/src/beacon/routes/lodestar.ts index a75f5f333b0a..07cc45508862 100644 --- a/packages/api/src/beacon/routes/lodestar.ts +++ b/packages/api/src/beacon/routes/lodestar.ts @@ -1,8 +1,7 @@ import {ContainerType, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; -import {BeaconState, Epoch, RootHex, Slot, ssz} from "@lodestar/types"; +import {ArrayOf, BeaconState, Epoch, RootHex, Slot, ssz} from "@lodestar/types"; import { - ArrayOf, EmptyArgs, EmptyMeta, EmptyRequest, diff --git a/packages/api/src/beacon/routes/node.ts b/packages/api/src/beacon/routes/node.ts index 7b1b49593f23..8f96168d1eac 100644 --- a/packages/api/src/beacon/routes/node.ts +++ b/packages/api/src/beacon/routes/node.ts @@ -1,8 +1,7 @@ import {ContainerType, OptionalType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; -import {StringType, fulu, ssz, stringType} from "@lodestar/types"; +import {ArrayOf, StringType, fulu, ssz, stringType} from "@lodestar/types"; import { - ArrayOf, EmptyArgs, EmptyMeta, EmptyMetaCodec, diff --git a/packages/api/src/beacon/routes/proof.ts b/packages/api/src/beacon/routes/proof.ts index 5bdb863e4393..7190dbb5c37f 100644 --- a/packages/api/src/beacon/routes/proof.ts +++ b/packages/api/src/beacon/routes/proof.ts @@ -1,9 +1,8 @@ import {CompactMultiProof, ProofType} from "@chainsafe/persistent-merkle-tree"; import {ByteListType, ContainerType} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; -import {ssz} from "@lodestar/types"; +import {ArrayOf, ssz} from "@lodestar/types"; import {fromHex, toHex} from "@lodestar/utils"; -import {ArrayOf} from "../../utils/codecs.js"; import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js"; import {VersionCodec, VersionMeta} from "../../utils/metadata.js"; diff --git a/packages/api/src/beacon/routes/validator.ts b/packages/api/src/beacon/routes/validator.ts index 0d2c0fa2a0cd..32a94959a71d 100644 --- a/packages/api/src/beacon/routes/validator.ts +++ b/packages/api/src/beacon/routes/validator.ts @@ -8,6 +8,7 @@ import { isForkPostElectra, } from "@lodestar/params"; import { + ArrayOf, Attestation, BLSSignature, BeaconBlock, @@ -28,7 +29,6 @@ import { } from "@lodestar/types"; import {fromHex, toHex, toRootHex} from "@lodestar/utils"; import { - ArrayOf, EmptyMeta, EmptyMetaCodec, EmptyResponseCodec, diff --git a/packages/api/src/builder/routes.ts b/packages/api/src/builder/routes.ts index db93da53fd93..edf7df6be4d7 100644 --- a/packages/api/src/builder/routes.ts +++ b/packages/api/src/builder/routes.ts @@ -1,6 +1,7 @@ import {ChainForkConfig} from "@lodestar/config"; import {ForkName, VALIDATOR_REGISTRY_LIMIT, isForkPostDeneb} from "@lodestar/params"; import { + ArrayOf, BLSPubkey, ExecutionPayload, ExecutionPayloadAndBlobsBundle, @@ -14,7 +15,6 @@ import { } from "@lodestar/types"; import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import { - ArrayOf, EmptyArgs, EmptyMeta, EmptyRequest, diff --git a/packages/api/src/utils/codecs.ts b/packages/api/src/utils/codecs.ts index fad6396af085..24fbacb4437d 100644 --- a/packages/api/src/utils/codecs.ts +++ b/packages/api/src/utils/codecs.ts @@ -1,4 +1,4 @@ -import {ArrayType, ListBasicType, ListCompositeType, Type, isBasicType, isCompositeType} from "@chainsafe/ssz"; +import {Type} from "@chainsafe/ssz"; import {ForkName} from "@lodestar/params"; import {objectToExpectedCase} from "@lodestar/utils"; import { @@ -68,16 +68,6 @@ export const EmptyResponseCodec: ResponseCodec = { isEmpty: true, }; -export function ArrayOf(elementType: Type, limit = Infinity): ArrayType, unknown, unknown> { - if (isCompositeType(elementType)) { - return new ListCompositeType(elementType, limit) as unknown as ArrayType, unknown, unknown>; - } - if (isBasicType(elementType)) { - return new ListBasicType(elementType, limit) as unknown as ArrayType, unknown, unknown>; - } - throw Error(`Unknown type ${elementType.typeName}`); -} - export function WithMeta(getType: (m: M) => Type): ResponseDataCodec { return { toJson: (data, meta: M) => getType(meta).toJson(data), diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index c8b8dade5cd1..3c880f80060b 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -14,23 +14,29 @@ import { EpochShuffling, Index2PubkeyCache, computeAnchorCheckpoint, + computeAttestationsRewards, + computeBlockRewards, computeEndSlotAtEpoch, computeEpochAtSlot, computeStartSlotAtEpoch, + computeSyncCommitteeRewards, getEffectiveBalanceIncrementsZeroInactive, getEffectiveBalancesFromStateBytes, processSlots, } from "@lodestar/state-transition"; import { + AttestationsRewards, BeaconBlock, BlindedBeaconBlock, BlindedBeaconBlockBody, + BlockRewards, Epoch, Root, RootHex, SignedBeaconBlock, Slot, Status, + SyncCommitteeRewards, UintNum64, ValidatorIndex, Wei, @@ -77,9 +83,6 @@ import {AssembledBlockType, BlockType, ProduceResult} from "./produceBlock/index import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produceBlock/produceBlockBody.js"; import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js"; import {ReprocessController} from "./reprocess.js"; -import {AttestationsRewards, computeAttestationsRewards} from "./rewards/attestationsRewards.js"; -import {BlockRewards, computeBlockRewards} from "./rewards/blockRewards.js"; -import {SyncCommitteeRewards, computeSyncCommitteeRewards} from "./rewards/syncCommitteeRewards.js"; import { SeenAggregators, SeenAttesters, diff --git a/packages/beacon-node/src/chain/interface.ts b/packages/beacon-node/src/chain/interface.ts index 5b51be3b9acb..938a15e29dc9 100644 --- a/packages/beacon-node/src/chain/interface.ts +++ b/packages/beacon-node/src/chain/interface.ts @@ -9,14 +9,17 @@ import { Index2PubkeyCache, } from "@lodestar/state-transition"; import { + AttestationsRewards, BeaconBlock, BlindedBeaconBlock, + BlockRewards, Epoch, Root, RootHex, SignedBeaconBlock, Slot, Status, + SyncCommitteeRewards, UintNum64, ValidatorIndex, Wei, @@ -48,9 +51,6 @@ import {IChainOptions} from "./options.js"; import {AssembledBlockType, BlockAttributes, BlockType, ProduceResult} from "./produceBlock/produceBlockBody.js"; import {IStateRegenerator, RegenCaller} from "./regen/index.js"; import {ReprocessController} from "./reprocess.js"; -import {AttestationsRewards} from "./rewards/attestationsRewards.js"; -import {BlockRewards} from "./rewards/blockRewards.js"; -import {SyncCommitteeRewards} from "./rewards/syncCommitteeRewards.js"; import { SeenAggregators, SeenAttesters, diff --git a/packages/state-transition/src/index.ts b/packages/state-transition/src/index.ts index d06cfe676774..67ae559fe138 100644 --- a/packages/state-transition/src/index.ts +++ b/packages/state-transition/src/index.ts @@ -40,6 +40,7 @@ export { export * from "./constants/index.js"; export type {EpochTransitionStep} from "./epoch/index.js"; export {type BeaconStateTransitionMetrics, getMetrics} from "./metrics.js"; +export * from "./rewards/index.js"; export * from "./signatureSets/index.js"; export * from "./stateTransition.js"; export type { diff --git a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts b/packages/state-transition/src/rewards/attestationsRewards.ts similarity index 94% rename from packages/beacon-node/src/chain/rewards/attestationsRewards.ts rename to packages/state-transition/src/rewards/attestationsRewards.ts index 7e53b4d943d5..8bdbd40aa78e 100644 --- a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts +++ b/packages/state-transition/src/rewards/attestationsRewards.ts @@ -1,5 +1,4 @@ import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; -import {routes} from "@lodestar/api"; import {BeaconConfig} from "@lodestar/config"; import { EFFECTIVE_BALANCE_INCREMENT, @@ -14,24 +13,19 @@ import { WEIGHT_DENOMINATOR, isForkPostElectra, } from "@lodestar/params"; +import {AttestationsRewards, IdealAttestationsReward, TotalAttestationsReward, ValidatorIndex} from "@lodestar/types"; +import {fromHex} from "@lodestar/utils"; +import {EpochTransitionCache, beforeProcessEpoch} from "../cache/epochTransitionCache.js"; +import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js"; import { - CachedBeaconStateAllForks, - CachedBeaconStateAltair, - EpochTransitionCache, FLAG_ELIGIBLE_ATTESTER, FLAG_PREV_HEAD_ATTESTER_UNSLASHED, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED, FLAG_PREV_TARGET_ATTESTER_UNSLASHED, - beforeProcessEpoch, hasMarkers, isInInactivityLeak, -} from "@lodestar/state-transition"; -import {ValidatorIndex} from "@lodestar/types"; -import {fromHex} from "@lodestar/utils"; +} from "../util/index.js"; -export type AttestationsRewards = routes.beacon.AttestationsRewards; -type IdealAttestationsReward = routes.beacon.IdealAttestationsReward; -type TotalAttestationsReward = routes.beacon.TotalAttestationsReward; /** Attestations penalty with respect to effective balance in Gwei */ type AttestationsPenalty = {target: number; source: number; effectiveBalance: number}; diff --git a/packages/beacon-node/src/chain/rewards/blockRewards.ts b/packages/state-transition/src/rewards/blockRewards.ts similarity index 94% rename from packages/beacon-node/src/chain/rewards/blockRewards.ts rename to packages/state-transition/src/rewards/blockRewards.ts index 3bdc7910423f..3dacd0eb915c 100644 --- a/packages/beacon-node/src/chain/rewards/blockRewards.ts +++ b/packages/state-transition/src/rewards/blockRewards.ts @@ -1,4 +1,3 @@ -import {routes} from "@lodestar/api"; import {BeaconConfig} from "@lodestar/config"; import { ForkName, @@ -6,16 +5,11 @@ import { WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA, isForkPostElectra, } from "@lodestar/params"; -import { - CachedBeaconStateAllForks, - CachedBeaconStateAltair, - CachedBeaconStatePhase0, - getAttesterSlashableIndices, - processAttestationsAltair, -} from "@lodestar/state-transition"; -import {BeaconBlock, altair, phase0} from "@lodestar/types"; - -export type BlockRewards = routes.beacon.BlockRewards; +import {BeaconBlock, BlockRewards, altair, phase0} from "@lodestar/types"; +import {processAttestationsAltair} from "../block/processAttestationsAltair.js"; +import {CachedBeaconStateAllForks, CachedBeaconStateAltair, CachedBeaconStatePhase0} from "../cache/stateCache.js"; +import {getAttesterSlashableIndices} from "../util/attestation.js"; + type SubRewardValue = number; // All reward values should be integer /** diff --git a/packages/state-transition/src/rewards/index.ts b/packages/state-transition/src/rewards/index.ts new file mode 100644 index 000000000000..a667a28fe799 --- /dev/null +++ b/packages/state-transition/src/rewards/index.ts @@ -0,0 +1,3 @@ +export * from "./attestationsRewards.js"; +export * from "./blockRewards.js"; +export * from "./syncCommitteeRewards.js"; diff --git a/packages/beacon-node/src/chain/rewards/syncCommitteeRewards.ts b/packages/state-transition/src/rewards/syncCommitteeRewards.ts similarity index 88% rename from packages/beacon-node/src/chain/rewards/syncCommitteeRewards.ts rename to packages/state-transition/src/rewards/syncCommitteeRewards.ts index caba0881770e..0f4332929f70 100644 --- a/packages/beacon-node/src/chain/rewards/syncCommitteeRewards.ts +++ b/packages/state-transition/src/rewards/syncCommitteeRewards.ts @@ -1,10 +1,9 @@ -import {routes} from "@lodestar/api"; import {BeaconConfig} from "@lodestar/config"; import {ForkName, SYNC_COMMITTEE_SIZE} from "@lodestar/params"; -import {CachedBeaconStateAllForks, CachedBeaconStateAltair, Index2PubkeyCache} from "@lodestar/state-transition"; -import {BeaconBlock, ValidatorIndex, altair} from "@lodestar/types"; +import {BeaconBlock, SyncCommitteeRewards, ValidatorIndex, altair} from "@lodestar/types"; +import {Index2PubkeyCache} from "../cache/pubkeyCache.js"; +import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../cache/stateCache.js"; -export type SyncCommitteeRewards = routes.beacon.SyncCommitteeRewards; type BalanceRecord = {val: number}; // Use val for convenient way to increment/decrement balance export async function computeSyncCommitteeRewards( diff --git a/packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts b/packages/state-transition/test/unit/rewards/blockRewards.test.ts similarity index 92% rename from packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts rename to packages/state-transition/test/unit/rewards/blockRewards.test.ts index 67502b2f00d4..522e494c51d9 100644 --- a/packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts +++ b/packages/state-transition/test/unit/rewards/blockRewards.test.ts @@ -2,19 +2,13 @@ import {describe, expect, it, vi} from "vitest"; import {createBeaconConfig} from "@lodestar/config"; import {chainConfig as chainConfigDef} from "@lodestar/config/default"; import {SYNC_COMMITTEE_SIZE} from "@lodestar/params"; -import { - CachedBeaconStateAllForks, - DataAvailabilityStatus, - ExecutionPayloadStatus, - stateTransition, -} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; -import {BlockAltairOpts, getBlockAltair} from "../../../../../state-transition/test/perf/block/util.js"; -import { - cachedStateAltairPopulateCaches, - generatePerfTestCachedStateAltair, -} from "../../../../../state-transition/test/perf/util.js"; -import {computeBlockRewards} from "../../../../src/chain/rewards/blockRewards.js"; +import {DataAvailabilityStatus, ExecutionPayloadStatus} from "../../../src/block/externalData.js"; +import {computeBlockRewards} from "../../../src/rewards/blockRewards.js"; +import {stateTransition} from "../../../src/stateTransition.js"; +import {CachedBeaconStateAllForks} from "../../../src/types.js"; +import {BlockAltairOpts, getBlockAltair} from "../../perf/block/util.js"; +import {cachedStateAltairPopulateCaches, generatePerfTestCachedStateAltair} from "../../perf/util.js"; describe("chain / rewards / blockRewards", () => { const config = createBeaconConfig({...chainConfigDef, ALTAIR_FORK_EPOCH: 0}, Buffer.alloc(32, 0xaa)); diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 3f907e3c26a7..a097a091fca7 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -5,6 +5,8 @@ import * as ssz from "./sszTypes.js"; import {sszTypesFor} from "./sszTypes.js"; export {sszTypesFor, SSZTypesFor, ssz}; +export * from "./rewards.js"; +export * from "./utils/array.js"; // Container utils export * from "./utils/container.js"; export {ExecutionAddressType} from "./utils/executionAddress.js"; diff --git a/packages/types/src/rewards.ts b/packages/types/src/rewards.ts new file mode 100644 index 000000000000..68a70231006c --- /dev/null +++ b/packages/types/src/rewards.ts @@ -0,0 +1,102 @@ +import {ContainerType, ValueOf} from "@chainsafe/ssz"; +import {UintNum64, ValidatorIndex} from "./sszTypes.js"; +import {ArrayOf} from "./utils/array.js"; + +export const BlockRewardsType = new ContainerType( + { + /** Proposer of the block, the proposer index who receives these rewards */ + proposerIndex: ValidatorIndex, + /** Total block reward, equal to attestations + sync_aggregate + proposer_slashings + attester_slashings */ + total: UintNum64, + /** Block reward component due to included attestations */ + attestations: UintNum64, + /** Block reward component due to included sync_aggregate */ + syncAggregate: UintNum64, + /** Block reward component due to included proposer_slashings */ + proposerSlashings: UintNum64, + /** Block reward component due to included attester_slashings */ + attesterSlashings: UintNum64, + }, + {jsonCase: "eth2"} +); + +export const AttestationsRewardType = new ContainerType( + { + /** Reward for head vote. Could be negative to indicate penalty */ + head: UintNum64, + /** Reward for target vote. Could be negative to indicate penalty */ + target: UintNum64, + /** Reward for source vote. Could be negative to indicate penalty */ + source: UintNum64, + /** Inclusion delay reward (phase0 only) */ + inclusionDelay: UintNum64, + /** Inactivity penalty. Should be a negative number to indicate penalty */ + inactivity: UintNum64, + }, + {jsonCase: "eth2"} +); + +export const IdealAttestationsRewardsType = new ContainerType( + { + ...AttestationsRewardType.fields, + effectiveBalance: UintNum64, + }, + {jsonCase: "eth2"} +); + +export const TotalAttestationsRewardsType = new ContainerType( + { + ...AttestationsRewardType.fields, + validatorIndex: ValidatorIndex, + }, + {jsonCase: "eth2"} +); + +export const AttestationsRewardsType = new ContainerType( + { + idealRewards: ArrayOf(IdealAttestationsRewardsType), + totalRewards: ArrayOf(TotalAttestationsRewardsType), + }, + {jsonCase: "eth2"} +); + +export const SyncCommitteeRewardsType = ArrayOf( + new ContainerType( + { + validatorIndex: ValidatorIndex, + reward: UintNum64, + }, + {jsonCase: "eth2"} + ) +); + +/** + * Rewards info for a single block. Every reward value is in Gwei. + */ +export type BlockRewards = ValueOf; + +/** + * Rewards for a single set of (ideal or actual depending on usage) attestations. Reward value is in Gwei + */ +export type AttestationsReward = ValueOf; + +/** + * Rewards info for ideal attestations ie. Maximum rewards could be earned by making timely head, target and source vote. + * `effectiveBalance` is in Gwei + */ +export type IdealAttestationsReward = ValueOf; + +/** + * Rewards info for actual attestations + */ +export type TotalAttestationsReward = ValueOf; + +export type AttestationsRewards = ValueOf; + +/** + * Rewards info for sync committee participation. Every reward value is in Gwei. + * Note: In the case that block proposer is present in `SyncCommitteeRewards`, the reward value only reflects rewards for + * participating in sync committee. Please refer to `BlockRewards.syncAggregate` for rewards of proposer including sync committee + * outputs into their block + */ +export type SyncCommitteeRewards = ValueOf; diff --git a/packages/types/src/utils/array.ts b/packages/types/src/utils/array.ts new file mode 100644 index 000000000000..0fb368013852 --- /dev/null +++ b/packages/types/src/utils/array.ts @@ -0,0 +1,11 @@ +import {ArrayType, ListBasicType, ListCompositeType, Type, isBasicType, isCompositeType} from "@chainsafe/ssz"; + +export function ArrayOf(elementType: Type, limit = Infinity): ArrayType, unknown, unknown> { + if (isCompositeType(elementType)) { + return new ListCompositeType(elementType, limit) as unknown as ArrayType, unknown, unknown>; + } + if (isBasicType(elementType)) { + return new ListBasicType(elementType, limit) as unknown as ArrayType, unknown, unknown>; + } + throw Error(`Unknown type ${elementType.typeName}`); +}