Skip to content

Commit c6eeab1

Browse files
authored
Merge pull request #575 from NodeFactoryIo/beroburny/prysm-upate
Prysm update
2 parents fcc04a7 + c88015b commit c6eeab1

23 files changed

Lines changed: 365 additions & 176 deletions

.env.dist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ SENTRY_PROJECT=chainguardian
55
SENTRY_AUTH_TOKEN=xxx
66
DOCKER_LIGHTHOUSE_IMAGE=sigp/lighthouse:v1.3.0
77
DOCKER_TEKU_IMAGE=consensys/teku:21.5
8-
DOCKER_PRYSM_IMAGE=gcr.io/prysmaticlabs/prysm/beacon-chain:v1.3.11
9-
DOCKER_PRYSM_VALIDATOR_IMAGE=gcr.io/prysmaticlabs/prysm/validator:v1.3.11
8+
DOCKER_PRYSM_IMAGE=gcr.io/prysmaticlabs/prysm/beacon-chain:v1.4.2
9+
DOCKER_PRYSM_VALIDATOR_IMAGE=gcr.io/prysmaticlabs/prysm/validator:v1.4.2
1010
DOCKER_NIMBUS_IMAGE=statusim/nimbus-eth2:amd64-v1.4.0

integration/prysm.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import {CgPrysmEth2Api} from "../src/renderer/services/eth2/client/module";
77
(async function (): Promise<void> {
88
const {proposer, attestation} = await restValidation({
99
baseUrl: "http://localhost:5050",
10-
getValidatorPrivateKey: async () => getInteropKey(7),
11-
limit: 5,
10+
getValidatorPrivateKey: async () => getInteropKey(15),
11+
limit: 2,
1212
config,
1313
ApiClient: CgPrysmEth2Api,
1414
});

prysm-testnet.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ version: '3.6'
22

33
services:
44
prysm_beacon:
5-
image: "${DOCKER_PRYSM_IMAGE:-gcr.io/prysmaticlabs/prysm/beacon-chain:v1.3.11}"
5+
image: "${DOCKER_PRYSM_IMAGE:-gcr.io/prysmaticlabs/prysm/beacon-chain:v1.4.2}"
66
container_name: "eth2_testnet_prysm_beacon"
77
volumes:
88
- ./testnet/prysm/data:/data
99
ports:
1010
- '5050:5050'
11+
- '5051:5051'
1112
- '4000:4000'
1213
- '13000:13000'
1314
- '12000:12000'
@@ -19,14 +20,15 @@ services:
1920
--force-clear-db
2021
--datadir=/data
2122
--grpc-gateway-port=5050
23+
--eth-api-port=5051
2224
--min-sync-peers=0
2325
--bootstrap-node=
2426
--disable-sync
2527
--interop-genesis-state /data/genesis.ssz
2628
--interop-eth1data-votes
2729
2830
prysm_validator:
29-
image: "${DOCKER_PRYSM_VALIDATOR_IMAGE:-gcr.io/prysmaticlabs/prysm/validator:v1.3.11}"
31+
image: "${DOCKER_PRYSM_VALIDATOR_IMAGE:-gcr.io/prysmaticlabs/prysm/validator:v1.4.2}"
3032
container_name: "eth2_testnet_prysm_validator"
3133
volumes:
3234
- ./testnet/prysm/data:/data

src/renderer/containers/BeaconNode/BeaconNodeContainer.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ export const BeaconNodeContainer: React.FC = () => {
1919

2020
const tabs = [{tabId: 0, tabName: "Dashboard", index: 0}];
2121
if (beacon.docker) {
22-
tabs.push({tabId: 1, tabName: "Logs", index: 0}, {tabId: 2, tabName: "Performance", index: 0});
22+
tabs.push(
23+
{tabId: 1, tabName: "Logs", index: 0},
24+
{tabId: 2, tabName: "Performance", index: 0},
25+
{tabId: 3, tabName: "Metrics", index: 0},
26+
);
2327
}
24-
tabs.push({tabId: 3, tabName: "Metrics", index: 0});
2528

2629
return (
2730
<Background scrollable={true}>

src/renderer/ducks/beacon/sagas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ export function* watchOnHead(
241241
typeof CgEth2ApiClient &
242242
boolean
243243
> {
244-
const config = yield retry(30, 1000, readBeaconChainNetwork, url);
244+
const config = yield retry(30, 1000, readBeaconChainNetwork, url, true);
245245
const ApiClient: typeof CgEth2ApiClient = yield call(getBeaconNodeEth2ApiClient, url);
246246
const client = new ApiClient(config?.eth2Config || mainnetConfig, url);
247247
const eventStream = client.events.getEventStream([BeaconEventType.HEAD]);

src/renderer/ducks/validator/sagas.ts

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
CallEffect,
1818
call,
1919
takeLatest,
20+
retry,
2021
} from "redux-saga/effects";
2122
import {CGAccount} from "../../models/account";
2223
import {deleteKeystore, saveValidatorData} from "../../services/utils/account";
@@ -163,6 +164,7 @@ export function* addNewValidatorSaga(action: ReturnType<typeof addNewValidator>)
163164
yield put(addValidator(validator));
164165
yield put(setLoadingValidator(false));
165166
yield spawn(validatorInfoUpdater, validator.publicKey, validator.network);
167+
yield put(startValidatorDutiesWatcher(validator.publicKey));
166168
}
167169

168170
function* removeValidatorSaga(
@@ -524,9 +526,24 @@ export function* watchValidatorDuties({
524526
}: ReturnType<typeof startValidatorDutiesWatcher>): Generator<
525527
SelectEffect | TakeEffect | CallEffect,
526528
void,
527-
IValidatorComplete & typeof CgEth2ApiClient & ICGValidatorResponse & ReturnType<typeof updateEpoch> & Beacon
529+
IValidatorComplete &
530+
typeof CgEth2ApiClient &
531+
ICGValidatorResponse &
532+
ReturnType<typeof updateEpoch> &
533+
Beacon &
534+
ReturnType<typeof setValidatorBeaconNode>
528535
> {
529-
const validator = yield select(getValidator, {publicKey: payload});
536+
let validator: IValidatorComplete = yield select(getValidator, {publicKey: payload});
537+
if (!validator.beaconNodes.length) {
538+
while (true) {
539+
const updatedValidator = yield take(setValidatorBeaconNode);
540+
if (updatedValidator.payload.length && validator.publicKey === updatedValidator.meta) {
541+
validator = {...validator, beaconNodes: updatedValidator.payload};
542+
break;
543+
}
544+
}
545+
}
546+
530547
const config = getNetworkConfig(validator.network)?.eth2Config || mainnetConfig;
531548
const {genesisTime} = getNetworkConfig(validator.network);
532549

@@ -539,11 +556,27 @@ export function* watchValidatorDuties({
539556
function* processDuties(
540557
epoch: number,
541558
): Generator<CallEffect | AllEffect<CallEffect>, void, AttesterDuty[] & ProposerDuty[]> {
542-
const attestations = yield call(eth2API.validator.getAttesterDuties, epoch, [validatorState.index]);
543-
const attestationsFuture = yield call(eth2API.validator.getAttesterDuties, epoch + 1, [validatorState.index]);
544-
const propositions = yield call(eth2API.validator.getProposerDuties, epoch, [validatorId]);
545-
const propositionsFuture = yield call(eth2API.validator.getProposerDuties, epoch + 1, [validatorId]);
546-
const propositionsSuperFuture = yield call(eth2API.validator.getProposerDuties, epoch + 2, [validatorId]);
559+
let attestations: AttesterDuty[], attestationsFuture: AttesterDuty[];
560+
try {
561+
attestations = yield retry(2, 0, eth2API.validator.getAttesterDuties, epoch, [validatorState.index]);
562+
attestationsFuture = yield call(eth2API.validator.getAttesterDuties, epoch + 1, [validatorState.index]);
563+
} catch (e) {
564+
attestations = attestations || [];
565+
attestationsFuture = [];
566+
cgLogger.warn("processDuties attestations", e);
567+
}
568+
569+
let propositions: ProposerDuty[], propositionsFuture: ProposerDuty[], propositionsSuperFuture: ProposerDuty[];
570+
try {
571+
propositions = yield call(eth2API.validator.getProposerDuties, epoch, [validatorId]);
572+
propositionsFuture = yield call(eth2API.validator.getProposerDuties, epoch + 1, [validatorId]);
573+
propositionsSuperFuture = yield call(eth2API.validator.getProposerDuties, epoch + 2, [validatorId]);
574+
} catch (e) {
575+
propositions = propositions || [];
576+
propositionsFuture = propositionsFuture || [];
577+
propositionsSuperFuture = [];
578+
cgLogger.warn("processDuties propositions", e);
579+
}
547580

548581
// store data to database
549582
yield all([
@@ -579,6 +612,13 @@ export function* watchValidatorDuties({
579612
yield take(addBeacons);
580613
beaconNode = yield select(getBeaconByKey, {key: validator.beaconNodes[0]});
581614
}
615+
if (beaconNode.status !== BeaconStatus.active) {
616+
while (true) {
617+
const newStatus = yield take(updateStatus);
618+
if (newStatus.payload === BeaconStatus.active && newStatus.meta === beaconNode.url) break;
619+
}
620+
}
621+
582622
yield call(processDuties, computeEpochAtSlot(config, beaconNode.slot));
583623
while (true) {
584624
const newEpoch = yield take(updateEpoch);
@@ -592,14 +632,15 @@ function* updateDutiesStatus({
592632
meta,
593633
}: ReturnType<typeof updateSlot>): Generator<SelectEffect | AllEffect<AllEffect<CallEffect>>, void, BeaconValidators> {
594634
const validatorsByBeaconNode = yield select(getValidatorsByBeaconNode);
595-
yield all(
596-
validatorsByBeaconNode[meta].map(({publicKey}) =>
597-
all([
598-
call(database.validator.propositionDuties.updateMissed, publicKey, payload),
599-
call(database.validator.attestationDuties.updateMissed, publicKey, payload),
600-
]),
601-
),
602-
);
635+
if (validatorsByBeaconNode[meta])
636+
yield all(
637+
validatorsByBeaconNode[meta].map(({publicKey}) =>
638+
all([
639+
call(database.validator.propositionDuties.updateMissed, publicKey, payload),
640+
call(database.validator.attestationDuties.updateMissed, publicKey, payload),
641+
]),
642+
),
643+
);
603644
}
604645

605646
function* onPublishedBlock({

src/renderer/services/api/http/httpClient.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import axios, {AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse} from "axios";
22
import database from "../../db/api/database";
33

4+
const axiosConfigDefault: AxiosRequestConfig = {timeout: 3000};
5+
46
export class HttpClient {
57
private client: AxiosInstance;
68

79
public constructor(baseURL: string, options: {axios?: AxiosRequestConfig} = {}) {
810
if (!options) {
911
// eslint-disable-next-line no-param-reassign
10-
options = {axios: {}};
12+
options = {axios: axiosConfigDefault};
1113
}
1214
this.client = axios.create({
1315
baseURL,
14-
...options.axios,
16+
...{...axiosConfigDefault, ...options.axios},
1517
});
1618
}
1719

src/renderer/services/eth2/client/eth2ApiClient/cgEth2BeaconPoolApi.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export class CgEth2BeaconPoolApi implements ICGBeaconPoolApi {
2121
}
2222

2323
public submitAttestation = async (attestation: Attestation): Promise<void> => {
24+
await this.httpClient.post("/eth/v1/beacon/pool/attestations", [
25+
this.config.types.Attestation.toJson(attestation, {case: "snake"}),
26+
]);
2427
if (this.publicKey && this.dispatch) {
2528
const validatorIndexInCommittee = attestation.aggregationBits.findIndex((bit) => bit);
2629
if (validatorIndexInCommittee !== -1)
@@ -34,9 +37,6 @@ export class CgEth2BeaconPoolApi implements ICGBeaconPoolApi {
3437
),
3538
);
3639
}
37-
await this.httpClient.post("/eth/v1/beacon/pool/attestations", [
38-
this.config.types.Attestation.toJson(attestation, {case: "snake"}),
39-
]);
4040
};
4141

4242
public async submitVoluntaryExit(signedVoluntaryExit: SignedVoluntaryExit): Promise<void> {

src/renderer/services/eth2/client/prysm/CgPrysmEth2BeaconApi.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,21 @@ export class CgPrysmEth2BeaconApi extends CgEth2BeaconApi {
2020

2121
public getGenesis = async (): Promise<Genesis | null> => {
2222
try {
23-
const {genesisTime, genesisValidatorsRoot} = await this.httpClient.get<{
24-
genesisTime: string;
25-
genesisValidatorsRoot: string;
26-
}>("/eth/v1alpha1/node/genesis");
23+
const genesisResponse = await this.httpClient.get<{
24+
data: {
25+
// eslint-disable-next-line camelcase
26+
genesis_time: string;
27+
// eslint-disable-next-line camelcase
28+
genesis_validators_root: string;
29+
// eslint-disable-next-line camelcase
30+
genesis_fork_version: string;
31+
};
32+
}>("/eth/v1/beacon/genesis");
2733

2834
const result = {
29-
genesisTime: Math.round(new Date(genesisTime).getTime() / 1000).toString(),
30-
genesisValidatorsRoot: base64ToHex(genesisValidatorsRoot),
31-
// TODO: change mocked data with real
32-
genesisForkVersion: "0x00000000",
35+
genesisTime: Math.round(new Date(genesisResponse.data.genesis_time).getTime() / 1000).toString(),
36+
genesisValidatorsRoot: base64ToHex(genesisResponse.data.genesis_validators_root),
37+
genesisForkVersion: base64ToHex(genesisResponse.data.genesis_fork_version),
3338
};
3439

3540
return this.config.types.Genesis.fromJson(result, {case: "camel"});

src/renderer/services/eth2/client/prysm/CgPrysmEth2BeaconPoolApi.ts

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {Attestation, SignedVoluntaryExit} from "@chainsafe/lodestar-types";
66
import {signedNewAttestation} from "../../../../ducks/validator/actions";
77
import {toHex} from "@chainsafe/lodestar-utils";
88
import {hexToBase64} from "./utils";
9-
import {Attestation as PrysmAttestation} from "./types";
9+
import {Attestation as PrysmAttestation} from "./map.types";
1010

1111
type AttestationData = {
1212
aggregationBits: string;
@@ -32,26 +32,16 @@ export class CgPrysmEth2BeaconPoolApi extends CgEth2BeaconPoolApi {
3232
}
3333

3434
public submitAttestation = async (attestation: Attestation): Promise<void> => {
35-
if (this.publicKey && this.dispatch) {
36-
const validatorIndexInCommittee = attestation.aggregationBits.findIndex((bit) => bit);
37-
if (validatorIndexInCommittee !== -1)
38-
this.dispatch(
39-
signedNewAttestation(
40-
this.publicKey,
41-
toHex(attestation.data.beaconBlockRoot),
42-
attestation.data.index,
43-
attestation.data.slot,
44-
validatorIndexInCommittee,
45-
),
46-
);
47-
}
4835
const data = this.config.types.Attestation.toJson(attestation) as AttestationData;
4936
const mapped: PrysmAttestation = {
50-
aggregationBits: hexToBase64(data.aggregationBits),
37+
// eslint-disable-next-line camelcase,@typescript-eslint/camelcase
38+
aggregation_bits: hexToBase64(data.aggregationBits),
5139
data: {
5240
slot: data.data.slot,
53-
committeeIndex: data.data.index,
54-
beaconBlockRoot: hexToBase64(data.data.beaconBlockRoot),
41+
// eslint-disable-next-line camelcase,@typescript-eslint/camelcase
42+
index: data.data.index,
43+
// eslint-disable-next-line camelcase,@typescript-eslint/camelcase
44+
beacon_block_root: hexToBase64(data.data.beaconBlockRoot),
5545
source: {
5646
epoch: data.data.source.epoch,
5747
root: hexToBase64(data.data.source.root),
@@ -63,7 +53,20 @@ export class CgPrysmEth2BeaconPoolApi extends CgEth2BeaconPoolApi {
6353
},
6454
signature: hexToBase64(data.signature),
6555
};
66-
await this.httpClient.post("/eth/v1alpha1/validator/attestation", mapped);
56+
await this.httpClient.post("/eth/v1/beacon/pool/attestations", {data: [mapped]});
57+
if (this.publicKey && this.dispatch) {
58+
const validatorIndexInCommittee = attestation.aggregationBits.findIndex((bit) => bit);
59+
if (validatorIndexInCommittee !== -1)
60+
this.dispatch(
61+
signedNewAttestation(
62+
this.publicKey,
63+
toHex(attestation.data.beaconBlockRoot),
64+
attestation.data.index,
65+
attestation.data.slot,
66+
validatorIndexInCommittee,
67+
),
68+
);
69+
}
6770
};
6871

6972
// eslint-disable-next-line @typescript-eslint/no-unused-vars

0 commit comments

Comments
 (0)