Compare commits
6 Commits
v0.1.0-dev
...
v0.1.0-dev
Author | SHA1 | Date |
---|---|---|
semantic-release-bot | d9ad98f694 | |
Derrick Hammer | 232f5ba730 | |
Derrick Hammer | 11791ff08b | |
Derrick Hammer | 4836ddb32e | |
Derrick Hammer | b3e5607132 | |
Derrick Hammer | a7786fa21c |
|
@ -1,3 +1,5 @@
|
||||||
|
# [0.1.0-develop.29](https://git.lumeweb.com/LumeWeb/libethsync/compare/v0.1.0-develop.28...v0.1.0-develop.29) (2023-07-13)
|
||||||
|
|
||||||
# [0.1.0-develop.28](https://git.lumeweb.com/LumeWeb/libethsync/compare/v0.1.0-develop.27...v0.1.0-develop.28) (2023-07-13)
|
# [0.1.0-develop.28](https://git.lumeweb.com/LumeWeb/libethsync/compare/v0.1.0-develop.27...v0.1.0-develop.28) (2023-07-13)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@lumeweb/libethclient",
|
"name": "@lumeweb/libethclient",
|
||||||
"version": "0.1.0-develop.28",
|
"version": "0.1.0-develop.29",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@lumeweb/libethclient",
|
"name": "@lumeweb/libethclient",
|
||||||
"version": "0.1.0-develop.28",
|
"version": "0.1.0-develop.29",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chainsafe/as-sha256": "^0.3.1",
|
"@chainsafe/as-sha256": "^0.3.1",
|
||||||
"@chainsafe/bls": "7.1.1",
|
"@chainsafe/bls": "7.1.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lumeweb/libethsync",
|
"name": "@lumeweb/libethsync",
|
||||||
"version": "0.1.0-develop.28",
|
"version": "0.1.0-develop.29",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
} from "#util.js";
|
} from "#util.js";
|
||||||
import { LightClientUpdate, OptimisticUpdateCallback } from "#types.js";
|
import { LightClientUpdate, OptimisticUpdateCallback } from "#types.js";
|
||||||
import { assertValidLightClientUpdate } from "@lodestar/light-client/validation";
|
import { assertValidLightClientUpdate } from "@lodestar/light-client/validation";
|
||||||
|
import * as capella from "@lodestar/types/capella";
|
||||||
|
|
||||||
export interface BaseClientOptions {
|
export interface BaseClientOptions {
|
||||||
prover: IProver;
|
prover: IProver;
|
||||||
|
@ -39,6 +40,12 @@ export default abstract class BaseClient {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _latestOptimisticUpdate?: Uint8Array;
|
||||||
|
|
||||||
|
get latestOptimisticUpdate(): Uint8Array {
|
||||||
|
return this._latestOptimisticUpdate as Uint8Array;
|
||||||
|
}
|
||||||
|
|
||||||
private _latestPeriod: number = -1;
|
private _latestPeriod: number = -1;
|
||||||
|
|
||||||
get latestPeriod(): number {
|
get latestPeriod(): number {
|
||||||
|
@ -79,58 +86,6 @@ export default abstract class BaseClient {
|
||||||
return this.getNextValidExecutionInfo(retry - 1);
|
return this.getNextValidExecutionInfo(retry - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async _sync() {
|
|
||||||
await this.syncMutex.acquire();
|
|
||||||
|
|
||||||
const currentPeriod = this.getCurrentPeriod();
|
|
||||||
if (currentPeriod > this._latestPeriod) {
|
|
||||||
if (!this.booted) {
|
|
||||||
this.latestCommittee = await this.syncFromGenesis();
|
|
||||||
} else {
|
|
||||||
this.latestCommittee = await this.syncFromLastUpdate();
|
|
||||||
}
|
|
||||||
this._latestPeriod = currentPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.syncMutex.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async subscribe(callback?: (ei: ExecutionInfo) => void) {
|
|
||||||
setInterval(async () => {
|
|
||||||
try {
|
|
||||||
const ei = await this.getLatestExecution();
|
|
||||||
if (ei && ei.blockHash !== this.latestBlockHash) {
|
|
||||||
this.latestBlockHash = ei.blockHash;
|
|
||||||
return await callback?.(ei);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}, POLLING_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async getLatestExecution(): Promise<ExecutionInfo | null> {
|
|
||||||
await this._sync();
|
|
||||||
const update = await this.options.optimisticUpdateCallback();
|
|
||||||
|
|
||||||
const verify = await optimisticUpdateVerify(
|
|
||||||
this.latestCommittee as Uint8Array[],
|
|
||||||
update,
|
|
||||||
);
|
|
||||||
// TODO: check the update agains the latest sync commttee
|
|
||||||
if (!verify.correct) {
|
|
||||||
console.error(`Invalid Optimistic Update: ${verify.reason}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
console.log(
|
|
||||||
`Optimistic update verified for slot ${update.attestedHeader.beacon.slot}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
blockHash: toHexString(update.attestedHeader.execution.blockHash),
|
|
||||||
blockNumber: update.attestedHeader.execution.blockNumber,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async syncProver(
|
async syncProver(
|
||||||
startPeriod: number,
|
startPeriod: number,
|
||||||
currentPeriod: number,
|
currentPeriod: number,
|
||||||
|
@ -181,6 +136,67 @@ export default abstract class BaseClient {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async _sync() {
|
||||||
|
await this.syncMutex.acquire();
|
||||||
|
|
||||||
|
const currentPeriod = this.getCurrentPeriod();
|
||||||
|
if (currentPeriod > this._latestPeriod) {
|
||||||
|
if (!this.booted) {
|
||||||
|
this.latestCommittee = await this.syncFromGenesis();
|
||||||
|
} else {
|
||||||
|
this.latestCommittee = await this.syncFromLastUpdate();
|
||||||
|
}
|
||||||
|
this._latestPeriod = currentPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.syncMutex.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async subscribe(callback?: (ei: ExecutionInfo) => void) {
|
||||||
|
setInterval(async () => {
|
||||||
|
await this.syncToLatestBlock(callback);
|
||||||
|
}, POLLING_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async syncToLatestBlock(callback?: (ei: ExecutionInfo) => void) {
|
||||||
|
try {
|
||||||
|
const ei = await this.getLatestExecution();
|
||||||
|
if (ei && ei.blockHash !== this.latestBlockHash) {
|
||||||
|
this.latestBlockHash = ei.blockHash;
|
||||||
|
return await callback?.(ei);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async getLatestExecution(): Promise<ExecutionInfo | null> {
|
||||||
|
await this._sync();
|
||||||
|
const update = await this.options.optimisticUpdateCallback();
|
||||||
|
|
||||||
|
const verify = await optimisticUpdateVerify(
|
||||||
|
this.latestCommittee as Uint8Array[],
|
||||||
|
update,
|
||||||
|
);
|
||||||
|
// TODO: check the update against the latest sync committee
|
||||||
|
if (!verify.correct) {
|
||||||
|
console.error(`Invalid Optimistic Update: ${verify.reason}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._latestOptimisticUpdate =
|
||||||
|
capella.ssz.LightClientOptimisticUpdate.serialize(update);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Optimistic update verified for slot ${update.attestedHeader.beacon.slot}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
blockHash: toHexString(update.attestedHeader.execution.blockHash),
|
||||||
|
blockNumber: update.attestedHeader.execution.blockNumber,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected async syncUpdateVerifyGetCommittee(
|
protected async syncUpdateVerifyGetCommittee(
|
||||||
prevCommittee: Uint8Array[],
|
prevCommittee: Uint8Array[],
|
||||||
period: number,
|
period: number,
|
||||||
|
|
Loading…
Reference in New Issue