@lodestar/builder 1.51.0-dev.a736f94f66 → 1.51.0-dev.ab919f3073
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/lib/builder.d.ts +23 -1
- package/lib/builder.d.ts.map +1 -1
- package/lib/builder.js +76 -2
- package/lib/builder.js.map +1 -1
- package/lib/defaults.d.ts +11 -0
- package/lib/defaults.d.ts.map +1 -1
- package/lib/defaults.js +12 -0
- package/lib/defaults.js.map +1 -1
- package/lib/identity.js +3 -3
- package/lib/identity.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/metrics.d.ts +25 -0
- package/lib/metrics.d.ts.map +1 -1
- package/lib/metrics.js +34 -0
- package/lib/metrics.js.map +1 -1
- package/lib/services/bidLedger.d.ts +2 -0
- package/lib/services/bidLedger.d.ts.map +1 -1
- package/lib/services/bidLedger.js +13 -0
- package/lib/services/bidLedger.js.map +1 -1
- package/lib/services/bidder.d.ts +56 -0
- package/lib/services/bidder.d.ts.map +1 -0
- package/lib/services/bidder.js +144 -0
- package/lib/services/bidder.js.map +1 -0
- package/lib/services/payloadOrchestrator.d.ts +7 -3
- package/lib/services/payloadOrchestrator.d.ts.map +1 -1
- package/lib/services/payloadOrchestrator.js +7 -3
- package/lib/services/payloadOrchestrator.js.map +1 -1
- package/lib/services/revealer.d.ts +35 -0
- package/lib/services/revealer.d.ts.map +1 -0
- package/lib/services/revealer.js +56 -0
- package/lib/services/revealer.js.map +1 -0
- package/package.json +11 -11
- package/src/builder.ts +107 -1
- package/src/defaults.ts +14 -0
- package/src/identity.ts +3 -3
- package/src/index.ts +6 -0
- package/src/metrics.ts +36 -0
- package/src/services/bidLedger.ts +15 -0
- package/src/services/bidder.ts +191 -0
- package/src/services/payloadOrchestrator.ts +16 -4
- package/src/services/revealer.ts +88 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ApiClient, routes } from "@lodestar/api";
|
|
2
|
+
import { ChainForkConfig } from "@lodestar/config";
|
|
3
|
+
import { IClock } from "@lodestar/state-transition";
|
|
4
|
+
import { BuilderIndex, BuilderStatus, ExecutionAddress } from "@lodestar/types";
|
|
5
|
+
import { Logger } from "@lodestar/utils";
|
|
6
|
+
import { Metrics } from "../metrics.js";
|
|
7
|
+
import { BidLedger } from "./bidLedger.js";
|
|
8
|
+
import { BidPolicy } from "./bidPolicy.js";
|
|
9
|
+
import { BidPublisher } from "./bidPublisher.js";
|
|
10
|
+
import { PayloadOrchestrator } from "./payloadOrchestrator.js";
|
|
11
|
+
import { PayloadStore } from "./payloadStore.js";
|
|
12
|
+
import { ProposerPreferencesTracker } from "./proposerPreferencesTracker.js";
|
|
13
|
+
export type PayloadAttributesEvent = routes.events.EventData[routes.events.EventType.payloadAttributes];
|
|
14
|
+
export type BidderOptions = {
|
|
15
|
+
/** Point within the slot before the proposal slot at which the payload is retrieved and bid on, in basis points */
|
|
16
|
+
deadlineBps: number;
|
|
17
|
+
/** Do not bid while the builder balance is below this value */
|
|
18
|
+
minOperatingBalanceGwei: number;
|
|
19
|
+
};
|
|
20
|
+
export type BidderModules = {
|
|
21
|
+
config: ChainForkConfig;
|
|
22
|
+
logger: Logger;
|
|
23
|
+
clock: IClock;
|
|
24
|
+
api: ApiClient;
|
|
25
|
+
orchestrator: PayloadOrchestrator;
|
|
26
|
+
payloadStore: PayloadStore;
|
|
27
|
+
ledger: BidLedger;
|
|
28
|
+
policy: BidPolicy;
|
|
29
|
+
bidPublisher: BidPublisher;
|
|
30
|
+
proposerPreferencesTracker: ProposerPreferencesTracker;
|
|
31
|
+
getBuilderStatus: () => {
|
|
32
|
+
status: BuilderStatus | undefined;
|
|
33
|
+
balance: number | undefined;
|
|
34
|
+
};
|
|
35
|
+
builderIndex: BuilderIndex;
|
|
36
|
+
executionFeeRecipient: ExecutionAddress;
|
|
37
|
+
metrics: Metrics | null;
|
|
38
|
+
signal: AbortSignal;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Bids once per proposal slot and parent: starts a payload build when the beacon node emits payload attributes,
|
|
42
|
+
* retrieves the payload at the deadline, prices it and publishes the signed bid.
|
|
43
|
+
*/
|
|
44
|
+
export declare class Bidder {
|
|
45
|
+
private readonly modules;
|
|
46
|
+
private readonly opts;
|
|
47
|
+
private readonly activeBuilds;
|
|
48
|
+
constructor(modules: BidderModules, opts: BidderOptions);
|
|
49
|
+
onPayloadAttributes(event: PayloadAttributesEvent): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Dependent root of the proposer duties in the given epoch, identifies the proposer preferences to bid against.
|
|
52
|
+
* Not cached, a reorg can change the dependent root within an epoch. Active builds already coalesce repeated attributes.
|
|
53
|
+
*/
|
|
54
|
+
private getDependentRoot;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=bidder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bidder.d.ts","sourceRoot":"","sources":["../../src/services/bidder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAC,MAAM,EAAqB,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAC,YAAY,EAAE,aAAa,EAAS,gBAAgB,EAAiB,MAAM,iBAAiB,CAAC;AACrG,OAAO,EAAc,MAAM,EAAoD,MAAM,iBAAiB,CAAC;AACvG,OAAO,EAAY,OAAO,EAAC,MAAM,eAAe,CAAC;AACjD,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAC,mBAAmB,EAAC,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,0BAA0B,EAAC,MAAM,iCAAiC,CAAC;AAE3E,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;AAExG,MAAM,MAAM,aAAa,GAAG;IAC1B,mHAAmH;IACnH,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,SAAS,CAAC;IACf,YAAY,EAAE,mBAAmB,CAAC;IAClC,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,0BAA0B,EAAE,0BAA0B,CAAC;IACvD,gBAAgB,EAAE,MAAM;QAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAC,CAAC;IACzF,YAAY,EAAE,YAAY,CAAC;IAC3B,qBAAqB,EAAE,gBAAgB,CAAC;IACxC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,qBAAa,MAAM;IAIf,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJvB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAElD,YACmB,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,aAAa,EAClC;IAEE,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+HtE;IAED;;;OAGG;YACW,gBAAgB;CAG/B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { ForkName, MIN_DEPOSIT_AMOUNT, isForkPostGloas } from "@lodestar/params";
|
|
2
|
+
import { computeEpochAtSlot } from "@lodestar/state-transition";
|
|
3
|
+
import { GWEI_TO_WEI, isErrorAborted, prettyGweiToEth, toHex, toRootHex } from "@lodestar/utils";
|
|
4
|
+
import { BidResult } from "../metrics.js";
|
|
5
|
+
import { createExecutionPayloadBid } from "./executionPayloadBid.js";
|
|
6
|
+
/**
|
|
7
|
+
* Bids once per proposal slot and parent: starts a payload build when the beacon node emits payload attributes,
|
|
8
|
+
* retrieves the payload at the deadline, prices it and publishes the signed bid.
|
|
9
|
+
*/
|
|
10
|
+
export class Bidder {
|
|
11
|
+
modules;
|
|
12
|
+
opts;
|
|
13
|
+
activeBuilds = new Set();
|
|
14
|
+
constructor(modules, opts) {
|
|
15
|
+
this.modules = modules;
|
|
16
|
+
this.opts = opts;
|
|
17
|
+
}
|
|
18
|
+
async onPayloadAttributes(event) {
|
|
19
|
+
const { clock, config, ledger, logger, metrics, orchestrator, proposerPreferencesTracker } = this.modules;
|
|
20
|
+
if (!isForkPostGloas(event.version)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const data = event.data;
|
|
24
|
+
const slot = data.proposalSlot;
|
|
25
|
+
const parentBlockRoot = toRootHex(data.parentBlockRoot);
|
|
26
|
+
const parentBlockHash = toRootHex(data.parentBlockHash);
|
|
27
|
+
const logCtx = { slot, parentBlockRoot, parentBlockHash };
|
|
28
|
+
if (slot <= clock.getCurrentSlot()) {
|
|
29
|
+
logger.debug("Ignoring payload attributes for past slot", logCtx);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// TODO: the beacon node emits payload attributes once per slot, late in the slot and only for the parent
|
|
33
|
+
// payload variant it would build on, revisit to start the build earlier and to bid on both variants
|
|
34
|
+
const buildId = `${slot}:${parentBlockRoot}:${parentBlockHash}`;
|
|
35
|
+
if (this.activeBuilds.has(buildId) || ledger.hasSubmitted(slot, parentBlockHash, parentBlockRoot)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.activeBuilds.add(buildId);
|
|
39
|
+
try {
|
|
40
|
+
// Heze bids require inclusion list bits which are not tracked yet
|
|
41
|
+
if (event.version !== ForkName.gloas) {
|
|
42
|
+
logger.warn("Bidding is not supported for fork", { ...logCtx, fork: event.version });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const dependentRoot = await this.getDependentRoot(computeEpochAtSlot(slot), this.modules.signal);
|
|
46
|
+
const proposerPreferences = proposerPreferencesTracker.get(slot, dependentRoot);
|
|
47
|
+
if (proposerPreferences === null) {
|
|
48
|
+
logger.debug("No proposer preferences known for slot, not bidding", { ...logCtx, dependentRoot });
|
|
49
|
+
metrics?.bids.total.inc({ result: BidResult.noProposerPreferences });
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const { feeRecipient, targetGasLimit } = proposerPreferences.message;
|
|
53
|
+
// The payload is retrieved in the slot before the proposal slot, use the timing of that slot
|
|
54
|
+
const buildFork = config.getForkName(slot - 1);
|
|
55
|
+
const msToDeadline = clock.msToSlot(slot) -
|
|
56
|
+
config.getSlotDurationMs(buildFork) +
|
|
57
|
+
config.getSlotComponentDurationMs(buildFork, this.opts.deadlineBps);
|
|
58
|
+
logger.verbose("Preparing payload build", { ...logCtx, msToDeadline, targetGasLimit });
|
|
59
|
+
const payload = await orchestrator.run({
|
|
60
|
+
id: buildId,
|
|
61
|
+
request: {
|
|
62
|
+
fork: event.version,
|
|
63
|
+
forkchoiceState: {
|
|
64
|
+
headBlockHash: parentBlockHash,
|
|
65
|
+
safeBlockHash: toRootHex(data.safeBlockHash),
|
|
66
|
+
finalizedBlockHash: toRootHex(data.finalizedBlockHash),
|
|
67
|
+
},
|
|
68
|
+
payloadAttributes: {
|
|
69
|
+
...data.payloadAttributes,
|
|
70
|
+
suggestedFeeRecipient: toHex(this.modules.executionFeeRecipient),
|
|
71
|
+
targetGasLimit,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
getPayloadAt: Date.now() + msToDeadline,
|
|
75
|
+
});
|
|
76
|
+
const { status, balance } = this.modules.getBuilderStatus();
|
|
77
|
+
if (status !== "active" || balance === undefined) {
|
|
78
|
+
logger.warn("Builder is not active, not bidding", { ...logCtx, status });
|
|
79
|
+
metrics?.bids.total.inc({ result: BidResult.inactive });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (balance < this.opts.minOperatingBalanceGwei) {
|
|
83
|
+
logger.warn("Builder balance below operating minimum, not bidding", {
|
|
84
|
+
...logCtx,
|
|
85
|
+
balance: prettyGweiToEth(balance),
|
|
86
|
+
minOperatingBalance: prettyGweiToEth(this.opts.minOperatingBalanceGwei),
|
|
87
|
+
});
|
|
88
|
+
metrics?.bids.total.inc({ result: BidResult.lowBalance });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const unsettledGwei = ledger.getUnsettledValueGwei(computeEpochAtSlot(slot));
|
|
92
|
+
const coverableGwei = Math.max(balance - MIN_DEPOSIT_AMOUNT - unsettledGwei, 0);
|
|
93
|
+
const payloadValueGwei = Number(payload.executionPayloadValue / GWEI_TO_WEI);
|
|
94
|
+
const value = this.modules.policy.computeValue({ payloadValueGwei, coverableGwei });
|
|
95
|
+
if (value === null) {
|
|
96
|
+
logger.info("Bid policy declined to bid", { ...logCtx, payloadValueGwei, coverableGwei, unsettledGwei });
|
|
97
|
+
metrics?.bids.total.inc({ result: BidResult.policyDeclined });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const { executionPayload } = payload;
|
|
101
|
+
const blockHash = toRootHex(executionPayload.blockHash);
|
|
102
|
+
this.modules.payloadStore.add({ slot, parentBlockRoot: data.parentBlockRoot, blockHash, payload });
|
|
103
|
+
const bid = createExecutionPayloadBid({
|
|
104
|
+
slot,
|
|
105
|
+
parentBlockRoot: data.parentBlockRoot,
|
|
106
|
+
prevRandao: data.payloadAttributes.prevRandao,
|
|
107
|
+
builderIndex: this.modules.builderIndex,
|
|
108
|
+
feeRecipient,
|
|
109
|
+
value,
|
|
110
|
+
payload: { ...payload, fork: ForkName.gloas },
|
|
111
|
+
});
|
|
112
|
+
await this.modules.bidPublisher.publish(bid, this.modules.signal);
|
|
113
|
+
metrics?.bids.total.inc({ result: BidResult.published });
|
|
114
|
+
logger.info("Published execution payload bid", {
|
|
115
|
+
...logCtx,
|
|
116
|
+
blockHash,
|
|
117
|
+
value: prettyGweiToEth(value),
|
|
118
|
+
payloadValue: prettyGweiToEth(payloadValueGwei),
|
|
119
|
+
feeRecipient: toHex(feeRecipient),
|
|
120
|
+
gasLimit: executionPayload.gasLimit,
|
|
121
|
+
transactions: executionPayload.transactions.length,
|
|
122
|
+
blobs: bid.blobKzgCommitments.length,
|
|
123
|
+
secFromSlot: clock.secFromSlot(slot),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
if (!isErrorAborted(e)) {
|
|
128
|
+
metrics?.bids.total.inc({ result: BidResult.error });
|
|
129
|
+
logger.error("Failed to bid", logCtx, e);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
this.activeBuilds.delete(buildId);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Dependent root of the proposer duties in the given epoch, identifies the proposer preferences to bid against.
|
|
138
|
+
* Not cached, a reorg can change the dependent root within an epoch. Active builds already coalesce repeated attributes.
|
|
139
|
+
*/
|
|
140
|
+
async getDependentRoot(epoch, signal) {
|
|
141
|
+
return (await this.modules.api.validator.getProposerDutiesV2({ epoch }, { signal })).meta().dependentRoot;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=bidder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bidder.js","sourceRoot":"","sources":["../../src/services/bidder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,QAAQ,EAAE,kBAAkB,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAS,kBAAkB,EAAC,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAC,WAAW,EAAU,cAAc,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AACvG,OAAO,EAAC,SAAS,EAAU,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAgCnE;;;GAGG;AACH,MAAM,OAAO,MAAM;IAIE,OAAO;IACP,IAAI;IAJN,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAElD,YACmB,OAAsB,EACtB,IAAmB;uBADnB,OAAO;oBACP,IAAI;IACpB,CAAC;IAEJ,KAAK,CAAC,mBAAmB,CAAC,KAA6B;QACrD,MAAM,EAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACxG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAkC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/B,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACxD,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,EAAC,IAAI,EAAE,eAAe,EAAE,eAAe,EAAC,CAAC;QAExD,IAAI,IAAI,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,2CAA2C,EAAE,MAAM,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,yGAAyG;QACzG,oGAAoG;QACpG,MAAM,OAAO,GAAG,GAAG,IAAI,IAAI,eAAe,IAAI,eAAe,EAAE,CAAC;QAChE,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC;YAClG,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE/B,IAAI,CAAC;YACH,kEAAkE;YAClE,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACrC,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAC,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAC,CAAC,CAAC;gBACnF,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACjG,MAAM,mBAAmB,GAAG,0BAA0B,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YAChF,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;gBACjC,MAAM,CAAC,KAAK,CAAC,qDAAqD,EAAE,EAAC,GAAG,MAAM,EAAE,aAAa,EAAC,CAAC,CAAC;gBAChG,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,qBAAqB,EAAC,CAAC,CAAC;gBACnE,OAAO;YACT,CAAC;YACD,MAAM,EAAC,YAAY,EAAE,cAAc,EAAC,GAAG,mBAAmB,CAAC,OAAO,CAAC;YAEnE,6FAA6F;YAC7F,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YAC/C,MAAM,YAAY,GAChB,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACpB,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC;gBACnC,MAAM,CAAC,0BAA0B,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACtE,MAAM,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAC,GAAG,MAAM,EAAE,YAAY,EAAE,cAAc,EAAC,CAAC,CAAC;YAErF,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC;gBACrC,EAAE,EAAE,OAAO;gBACX,OAAO,EAAE;oBACP,IAAI,EAAE,KAAK,CAAC,OAAO;oBACnB,eAAe,EAAE;wBACf,aAAa,EAAE,eAAe;wBAC9B,aAAa,EAAE,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC;wBAC5C,kBAAkB,EAAE,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC;qBACvD;oBACD,iBAAiB,EAAE;wBACjB,GAAG,IAAI,CAAC,iBAAiB;wBACzB,qBAAqB,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC;wBAChE,cAAc;qBACf;iBACF;gBACD,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY;aACxC,CAAC,CAAC;YAEH,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC1D,IAAI,MAAM,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBACjD,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAC,GAAG,MAAM,EAAE,MAAM,EAAC,CAAC,CAAC;gBACvE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAC,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YACD,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBAChD,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;oBAClE,GAAG,MAAM;oBACT,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC;oBACjC,mBAAmB,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC;iBACxE,CAAC,CAAC;gBACH,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,UAAU,EAAC,CAAC,CAAC;gBACxD,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,MAAM,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7E,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,kBAAkB,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC;YAChF,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,GAAG,WAAW,CAAC,CAAC;YAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,EAAC,gBAAgB,EAAE,aAAa,EAAC,CAAC,CAAC;YAClF,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAC,GAAG,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAC,CAAC,CAAC;gBACvG,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,cAAc,EAAC,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;YAED,MAAM,EAAC,gBAAgB,EAAC,GAAG,OAAO,CAAC;YACnC,MAAM,SAAS,GAAG,SAAS,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,OAAO,EAAC,CAAC,CAAC;YAEjG,MAAM,GAAG,GAAG,yBAAyB,CAAC;gBACpC,IAAI;gBACJ,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,UAAU;gBAC7C,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY;gBACvC,YAAY;gBACZ,KAAK;gBACL,OAAO,EAAE,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAC;aAC5C,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAElE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,SAAS,EAAC,CAAC,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;gBAC7C,GAAG,MAAM;gBACT,SAAS;gBACT,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;gBAC7B,YAAY,EAAE,eAAe,CAAC,gBAAgB,CAAC;gBAC/C,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC;gBACjC,QAAQ,EAAE,gBAAgB,CAAC,QAAQ;gBACnC,YAAY,EAAE,gBAAgB,CAAC,YAAY,CAAC,MAAM;gBAClD,KAAK,EAAE,GAAG,CAAC,kBAAkB,CAAC,MAAM;gBACpC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;aACrC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAC,CAAC,CAAC;gBACnD,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,MAAM,EAAE,CAAU,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,gBAAgB,CAAC,KAAY,EAAE,MAAmB;QAC9D,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,mBAAmB,CAAC,EAAC,KAAK,EAAC,EAAE,EAAC,MAAM,EAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,aAAa,CAAC;IACxG,CAAC;CACF"}
|
|
@@ -21,14 +21,18 @@ export type PayloadOrchestratorErrorType = {
|
|
|
21
21
|
jobId: string;
|
|
22
22
|
getPayloadAt: number;
|
|
23
23
|
} | {
|
|
24
|
-
code: PayloadOrchestratorErrorCode.PREPARE_TIMEOUT
|
|
24
|
+
code: PayloadOrchestratorErrorCode.PREPARE_TIMEOUT;
|
|
25
|
+
jobId: string;
|
|
26
|
+
lastError: string | null;
|
|
27
|
+
} | {
|
|
28
|
+
code: PayloadOrchestratorErrorCode.GET_PAYLOAD_TIMEOUT;
|
|
25
29
|
jobId: string;
|
|
26
30
|
};
|
|
27
31
|
export declare class PayloadOrchestratorError extends LodestarError<PayloadOrchestratorErrorType> {
|
|
28
32
|
}
|
|
29
33
|
/**
|
|
30
|
-
* Prepares a payload and retrieves it at the requested time.
|
|
31
|
-
* retrieval time
|
|
34
|
+
* Prepares a payload and retrieves it at the requested time. A missing payload ID is retried until the
|
|
35
|
+
* retrieval time, the execution client may not have imported the parent payload yet. Other errors fail the build.
|
|
32
36
|
*/
|
|
33
37
|
export declare class PayloadOrchestrator {
|
|
34
38
|
private readonly source;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payloadOrchestrator.d.ts","sourceRoot":"","sources":["../../src/services/payloadOrchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAA0C,MAAM,iBAAiB,CAAC;AACvF,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAC;AAI5B,MAAM,MAAM,eAAe,GAAG;IAC5B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,wFAAwF;IACxF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,kEAAkE;IAClE,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,oBAAY,4BAA4B;IACtC,wBAAwB,wDAAwD;IAChF,eAAe,+CAA+C;IAC9D,mBAAmB,mDAAmD;CACvE;AAED,MAAM,MAAM,4BAA4B,GACpC;IACE,IAAI,EAAE,4BAA4B,CAAC,wBAAwB,CAAC;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB,GACD;IACE,IAAI,EAAE,4BAA4B,CAAC,eAAe,GAAG,4BAA4B,CAAC,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"payloadOrchestrator.d.ts","sourceRoot":"","sources":["../../src/services/payloadOrchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAA0C,MAAM,iBAAiB,CAAC;AACvF,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAC;AAI5B,MAAM,MAAM,eAAe,GAAG;IAC5B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,wFAAwF;IACxF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,kEAAkE;IAClE,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,oBAAY,4BAA4B;IACtC,wBAAwB,wDAAwD;IAChF,eAAe,+CAA+C;IAC9D,mBAAmB,mDAAmD;CACvE;AAED,MAAM,MAAM,4BAA4B,GACpC;IACE,IAAI,EAAE,4BAA4B,CAAC,wBAAwB,CAAC;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB,GACD;IACE,IAAI,EAAE,4BAA4B,CAAC,eAAe,CAAC;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,IAAI,EAAE,4BAA4B,CAAC,mBAAmB,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,qBAAa,wBAAyB,SAAQ,aAAa,CAAC,4BAA4B,CAAC;CAAG;AAE5F;;;GAGG;AACH,qBAAa,mBAAmB;IAI5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4C;IAEjE,YACmB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,0BAA0B,EACnC,MAAM,EAAE,WAAW,EAClC;IAEJ,GAAG,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAQ/C;YAEa,MAAM;CA+CrB"}
|
|
@@ -10,8 +10,8 @@ export var PayloadOrchestratorErrorCode;
|
|
|
10
10
|
export class PayloadOrchestratorError extends LodestarError {
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Prepares a payload and retrieves it at the requested time.
|
|
14
|
-
* retrieval time
|
|
13
|
+
* Prepares a payload and retrieves it at the requested time. A missing payload ID is retried until the
|
|
14
|
+
* retrieval time, the execution client may not have imported the parent payload yet. Other errors fail the build.
|
|
15
15
|
*/
|
|
16
16
|
export class PayloadOrchestrator {
|
|
17
17
|
source;
|
|
@@ -37,14 +37,18 @@ export class PayloadOrchestrator {
|
|
|
37
37
|
if (!(prepareTimeout > 0)) {
|
|
38
38
|
throw new PayloadOrchestratorError({ code: PayloadOrchestratorErrorCode.PREPARE_DEADLINE_REACHED, jobId: id, getPayloadAt }, `Payload preparation deadline reached jobId=${id} getPayloadAt=${getPayloadAt}`);
|
|
39
39
|
}
|
|
40
|
+
let lastError = null;
|
|
40
41
|
const handle = await withTimeout((signal = this.signal) => retry(() => this.source.prepare(request, signal), {
|
|
41
42
|
retries: Infinity,
|
|
42
43
|
retryDelay: PREPARE_RETRY_DELAY,
|
|
43
44
|
shouldRetry: (error) => error instanceof PayloadSourceError && error.type.code === PayloadSourceErrorCode.NO_PAYLOAD_ID,
|
|
45
|
+
onRetry: (error) => {
|
|
46
|
+
lastError = error;
|
|
47
|
+
},
|
|
44
48
|
signal,
|
|
45
49
|
}), prepareTimeout, this.signal).catch((error) => {
|
|
46
50
|
if (error instanceof TimeoutError) {
|
|
47
|
-
throw new PayloadOrchestratorError({ code: PayloadOrchestratorErrorCode.PREPARE_TIMEOUT, jobId: id });
|
|
51
|
+
throw new PayloadOrchestratorError({ code: PayloadOrchestratorErrorCode.PREPARE_TIMEOUT, jobId: id, lastError: lastError?.message ?? null }, `Payload preparation timed out jobId=${id} lastError=${lastError?.message}`);
|
|
48
52
|
}
|
|
49
53
|
throw error;
|
|
50
54
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payloadOrchestrator.js","sourceRoot":"","sources":["../../src/services/payloadOrchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAC,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAIL,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAehC,MAAM,CAAN,IAAY,4BAIX;AAJD,WAAY,4BAA4B;IACtC,gHAAgF,CAAA;IAChF,8FAA8D,CAAA;IAC9D,sGAAsE,CAAA;AACxE,CAAC,EAJW,4BAA4B,KAA5B,4BAA4B,QAIvC;
|
|
1
|
+
{"version":3,"file":"payloadOrchestrator.js","sourceRoot":"","sources":["../../src/services/payloadOrchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ChainForkConfig } from "@lodestar/config";
|
|
2
|
+
import { IClock } from "@lodestar/state-transition";
|
|
3
|
+
import { BuilderIndex } from "@lodestar/types";
|
|
4
|
+
import { Logger } from "@lodestar/utils";
|
|
5
|
+
import { Metrics } from "../metrics.js";
|
|
6
|
+
import { BidSelector } from "./bidSelector.js";
|
|
7
|
+
import { ObservedBlock } from "./blockObserver.js";
|
|
8
|
+
import { EnvelopePublisher } from "./envelopePublisher.js";
|
|
9
|
+
import { PayloadStore } from "./payloadStore.js";
|
|
10
|
+
export type RevealerOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* Latest point within the block's slot at which a reveal may start, in basis points.
|
|
13
|
+
* Defaults to the network's PAYLOAD_ATTESTATION_DUE_BPS
|
|
14
|
+
*/
|
|
15
|
+
cutoffBps: number;
|
|
16
|
+
};
|
|
17
|
+
export type RevealerModules = {
|
|
18
|
+
config: ChainForkConfig;
|
|
19
|
+
logger: Logger;
|
|
20
|
+
clock: IClock;
|
|
21
|
+
bidSelector: BidSelector;
|
|
22
|
+
payloadStore: PayloadStore;
|
|
23
|
+
envelopePublisher: EnvelopePublisher;
|
|
24
|
+
builderIndex: BuilderIndex;
|
|
25
|
+
metrics: Metrics | null;
|
|
26
|
+
signal: AbortSignal;
|
|
27
|
+
};
|
|
28
|
+
/** Reveals the payload once a block committing to one of our bids is imported by the beacon node. */
|
|
29
|
+
export declare class Revealer {
|
|
30
|
+
private readonly modules;
|
|
31
|
+
private readonly opts;
|
|
32
|
+
constructor(modules: RevealerModules, opts: RevealerOptions);
|
|
33
|
+
onBlock(observed: ObservedBlock): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=revealer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revealer.d.ts","sourceRoot":"","sources":["../../src/services/revealer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAC;AAClD,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAC,OAAO,EAAe,MAAM,eAAe,CAAC;AACpD,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAE/C,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;IAC3B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,qGAAqG;AACrG,qBAAa,QAAQ;IAEjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFvB,YACmB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,eAAe,EACpC;IAEE,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDpD;CACF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { RevealResult } from "../metrics.js";
|
|
2
|
+
import { createExecutionPayloadEnvelopeContents } from "./executionPayloadEnvelope.js";
|
|
3
|
+
/** Reveals the payload once a block committing to one of our bids is imported by the beacon node. */
|
|
4
|
+
export class Revealer {
|
|
5
|
+
modules;
|
|
6
|
+
opts;
|
|
7
|
+
constructor(modules, opts) {
|
|
8
|
+
this.modules = modules;
|
|
9
|
+
this.opts = opts;
|
|
10
|
+
}
|
|
11
|
+
async onBlock(observed) {
|
|
12
|
+
const { bidSelector, clock, config, envelopePublisher, logger, metrics, payloadStore } = this.modules;
|
|
13
|
+
const selection = bidSelector.match(observed);
|
|
14
|
+
if (selection.status !== "selected") {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
metrics?.bids.won.inc();
|
|
18
|
+
const { blockRoot, slot } = observed;
|
|
19
|
+
const { blockHash } = selection.bid;
|
|
20
|
+
const logCtx = { slot, blockRoot, blockHash };
|
|
21
|
+
const storedPayload = payloadStore.get(blockHash);
|
|
22
|
+
if (storedPayload === null) {
|
|
23
|
+
logger.error("Payload of selected bid is not retained, cannot reveal", logCtx);
|
|
24
|
+
metrics?.reveals.total.inc({ result: RevealResult.unknownPayload });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const msFromSlot = clock.msFromSlot(slot);
|
|
28
|
+
const cutoffMs = config.getSlotComponentDurationMs(config.getForkName(slot), this.opts.cutoffBps);
|
|
29
|
+
if (msFromSlot > cutoffMs) {
|
|
30
|
+
logger.warn("Block with our bid arrived after reveal cutoff, not revealing", { ...logCtx, msFromSlot, cutoffMs });
|
|
31
|
+
metrics?.reveals.total.inc({ result: RevealResult.late });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const contents = createExecutionPayloadEnvelopeContents({
|
|
35
|
+
blockRoot,
|
|
36
|
+
builderIndex: this.modules.builderIndex,
|
|
37
|
+
selectedBid: observed.signedBid.message,
|
|
38
|
+
storedPayload,
|
|
39
|
+
});
|
|
40
|
+
try {
|
|
41
|
+
await envelopePublisher.publish(contents, this.modules.signal);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
metrics?.reveals.total.inc({ result: RevealResult.error });
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
47
|
+
metrics?.reveals.total.inc({ result: RevealResult.published });
|
|
48
|
+
logger.info("Revealed execution payload", {
|
|
49
|
+
...logCtx,
|
|
50
|
+
blobs: contents.blobs.length,
|
|
51
|
+
transactions: contents.envelope.payload.transactions.length,
|
|
52
|
+
secFromSlot: clock.secFromSlot(slot),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=revealer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revealer.js","sourceRoot":"","sources":["../../src/services/revealer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lodestar/builder",
|
|
3
|
-
"version": "1.51.0-dev.
|
|
3
|
+
"version": "1.51.0-dev.ab919f3073",
|
|
4
4
|
"description": "A Typescript implementation of the builder client",
|
|
5
5
|
"author": "ChainSafe Systems",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,17 +47,17 @@
|
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@chainsafe/lodestar-z": "catalog:",
|
|
50
|
-
"@chainsafe/ssz": "^1.
|
|
51
|
-
"@lodestar/api": "^1.51.0-dev.
|
|
52
|
-
"@lodestar/config": "^1.51.0-dev.
|
|
53
|
-
"@lodestar/params": "^1.51.0-dev.
|
|
54
|
-
"@lodestar/state-transition": "^1.51.0-dev.
|
|
55
|
-
"@lodestar/types": "^1.51.0-dev.
|
|
56
|
-
"@lodestar/utils": "^1.51.0-dev.
|
|
50
|
+
"@chainsafe/ssz": "^1.9.0",
|
|
51
|
+
"@lodestar/api": "^1.51.0-dev.ab919f3073",
|
|
52
|
+
"@lodestar/config": "^1.51.0-dev.ab919f3073",
|
|
53
|
+
"@lodestar/params": "^1.51.0-dev.ab919f3073",
|
|
54
|
+
"@lodestar/state-transition": "^1.51.0-dev.ab919f3073",
|
|
55
|
+
"@lodestar/types": "^1.51.0-dev.ab919f3073",
|
|
56
|
+
"@lodestar/utils": "^1.51.0-dev.ab919f3073"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@lodestar/logger": "^1.51.0-dev.
|
|
60
|
-
"@lodestar/test-utils": "^1.51.0-dev.
|
|
59
|
+
"@lodestar/logger": "^1.51.0-dev.ab919f3073",
|
|
60
|
+
"@lodestar/test-utils": "^1.51.0-dev.ab919f3073"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "ad189abc417dde323db703fab9c72dba01a735cc"
|
|
63
63
|
}
|
package/src/builder.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {ApiClient, routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig, assertEqualParams, createBeaconConfig} from "@lodestar/config";
|
|
3
|
+
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
4
|
import {Clock, ClockOptions, IClock} from "@lodestar/state-transition";
|
|
4
5
|
import {BuilderIndex, ExecutionAddress} from "@lodestar/types";
|
|
5
6
|
import {Logger, isErrorAborted, toHex, toRootHex} from "@lodestar/utils";
|
|
@@ -7,11 +8,26 @@ import {waitForGenesis} from "./genesis.js";
|
|
|
7
8
|
import {resolveBuilderIdentity} from "./identity.js";
|
|
8
9
|
import {Metrics} from "./metrics.js";
|
|
9
10
|
import {logNodeVersion, waitForNodeReady} from "./readiness.js";
|
|
11
|
+
import {Bidder, BidderOptions} from "./services/bidder.js";
|
|
12
|
+
import {BidLedger} from "./services/bidLedger.js";
|
|
13
|
+
import {ProportionalBidPolicy, ProportionalBidPolicyOpts} from "./services/bidPolicy.js";
|
|
14
|
+
import {BidPublisher} from "./services/bidPublisher.js";
|
|
15
|
+
import {BidSelector} from "./services/bidSelector.js";
|
|
10
16
|
import {BlockObserver} from "./services/blockObserver.js";
|
|
11
17
|
import {BuilderSigner, Keypair} from "./services/builderSigner.js";
|
|
12
18
|
import {BuilderStatusTracker} from "./services/builderStatusTracker.js";
|
|
19
|
+
import {EnvelopePublisher} from "./services/envelopePublisher.js";
|
|
20
|
+
import {PayloadOrchestrator} from "./services/payloadOrchestrator.js";
|
|
21
|
+
import {PayloadSource} from "./services/payloadSource.js";
|
|
13
22
|
import {PayloadStore} from "./services/payloadStore.js";
|
|
14
23
|
import {ProposerPreferencesTracker} from "./services/proposerPreferencesTracker.js";
|
|
24
|
+
import {Revealer} from "./services/revealer.js";
|
|
25
|
+
|
|
26
|
+
// Payments of won bids are assumed to be reflected in the builder balance after this many slots.
|
|
27
|
+
// The payment is queued as a builder withdrawal at the epoch transition after the bid epoch and only debited once that
|
|
28
|
+
// withdrawal is processed, so with a backlog of withdrawals the ledger releases the reservation before the balance drops.
|
|
29
|
+
// Reconciling against the pending payments and pending withdrawals of the state is a follow-up.
|
|
30
|
+
const PAYMENT_SETTLEMENT_SLOTS = 3 * SLOTS_PER_EPOCH;
|
|
15
31
|
|
|
16
32
|
export type BuilderModules = {
|
|
17
33
|
opts: BuilderOptions;
|
|
@@ -22,6 +38,9 @@ export type BuilderModules = {
|
|
|
22
38
|
clock: IClock;
|
|
23
39
|
index: BuilderIndex;
|
|
24
40
|
payloadStore: PayloadStore;
|
|
41
|
+
ledger: BidLedger;
|
|
42
|
+
bidder: Bidder;
|
|
43
|
+
revealer: Revealer;
|
|
25
44
|
};
|
|
26
45
|
|
|
27
46
|
export type BuilderOptions = {
|
|
@@ -31,8 +50,20 @@ export type BuilderOptions = {
|
|
|
31
50
|
abortController: AbortController;
|
|
32
51
|
api: ApiClient;
|
|
33
52
|
clock?: ClockOptions;
|
|
53
|
+
/** Fee recipient of built payloads, receives priority fees and MEV */
|
|
34
54
|
executionFeeRecipient: ExecutionAddress;
|
|
35
55
|
metrics: Metrics | null;
|
|
56
|
+
/** Payload construction engine, an execution client is one implementation */
|
|
57
|
+
payloadSource: PayloadSource;
|
|
58
|
+
bidding: BidderOptions &
|
|
59
|
+
ProportionalBidPolicyOpts & {
|
|
60
|
+
/** Maximum time in milliseconds to wait for payload retrieval at the bid deadline */
|
|
61
|
+
getPayloadTimeout: number;
|
|
62
|
+
};
|
|
63
|
+
reveal: {
|
|
64
|
+
/** Defaults to PAYLOAD_ATTESTATION_DUE_BPS of the network */
|
|
65
|
+
cutoffBps?: number;
|
|
66
|
+
};
|
|
36
67
|
};
|
|
37
68
|
|
|
38
69
|
/**
|
|
@@ -49,6 +80,9 @@ export class Builder {
|
|
|
49
80
|
private readonly logger: Logger;
|
|
50
81
|
private readonly executionFeeRecipient: ExecutionAddress;
|
|
51
82
|
private readonly payloadStore: PayloadStore;
|
|
83
|
+
private readonly ledger: BidLedger;
|
|
84
|
+
private readonly bidder: Bidder;
|
|
85
|
+
private readonly revealer: Revealer;
|
|
52
86
|
|
|
53
87
|
constructor({
|
|
54
88
|
opts,
|
|
@@ -59,6 +93,9 @@ export class Builder {
|
|
|
59
93
|
clock,
|
|
60
94
|
index,
|
|
61
95
|
payloadStore,
|
|
96
|
+
ledger,
|
|
97
|
+
bidder,
|
|
98
|
+
revealer,
|
|
62
99
|
}: BuilderModules) {
|
|
63
100
|
this.builderSigner = builderSigner;
|
|
64
101
|
this.blockObserver = blockObserver;
|
|
@@ -69,9 +106,13 @@ export class Builder {
|
|
|
69
106
|
this.logger = opts.logger;
|
|
70
107
|
this.index = index;
|
|
71
108
|
this.payloadStore = payloadStore;
|
|
109
|
+
this.ledger = ledger;
|
|
110
|
+
this.bidder = bidder;
|
|
111
|
+
this.revealer = revealer;
|
|
72
112
|
|
|
73
113
|
this.executionFeeRecipient = opts.executionFeeRecipient;
|
|
74
114
|
|
|
115
|
+
this.blockObserver.runOnBlock((block) => this.revealer.onBlock(block));
|
|
75
116
|
this.clock.runEverySlot(async (slot) => this.onSlot(slot));
|
|
76
117
|
this.clock.runEveryEpoch((epoch) => this.builderStatusTracker.poll(epoch));
|
|
77
118
|
this.clock.start(this.controller.signal);
|
|
@@ -80,6 +121,9 @@ export class Builder {
|
|
|
80
121
|
this.logger.info("Builder client initialized", {
|
|
81
122
|
index: this.index,
|
|
82
123
|
executionFeeRecipient: toHex(this.executionFeeRecipient),
|
|
124
|
+
payloadSource: opts.payloadSource.id,
|
|
125
|
+
shareBps: opts.bidding.shareBps,
|
|
126
|
+
deadlineBps: opts.bidding.deadlineBps,
|
|
83
127
|
});
|
|
84
128
|
}
|
|
85
129
|
|
|
@@ -112,10 +156,60 @@ export class Builder {
|
|
|
112
156
|
);
|
|
113
157
|
|
|
114
158
|
const builderStatusTracker = new BuilderStatusTracker(api, logger, index, opts.metrics);
|
|
159
|
+
await builderStatusTracker.poll(clock.getCurrentEpoch());
|
|
115
160
|
const blockObserver = new BlockObserver(config, logger, api);
|
|
116
161
|
const proposerPreferencesTracker = new ProposerPreferencesTracker();
|
|
117
162
|
|
|
118
163
|
const payloadStore = new PayloadStore();
|
|
164
|
+
const ledger = new BidLedger();
|
|
165
|
+
const signal = opts.abortController.signal;
|
|
166
|
+
|
|
167
|
+
const bidder = new Bidder(
|
|
168
|
+
{
|
|
169
|
+
config,
|
|
170
|
+
logger,
|
|
171
|
+
clock,
|
|
172
|
+
api,
|
|
173
|
+
orchestrator: new PayloadOrchestrator(
|
|
174
|
+
opts.payloadSource,
|
|
175
|
+
{getPayloadTimeout: opts.bidding.getPayloadTimeout},
|
|
176
|
+
signal
|
|
177
|
+
),
|
|
178
|
+
payloadStore,
|
|
179
|
+
ledger,
|
|
180
|
+
policy: new ProportionalBidPolicy(opts.bidding),
|
|
181
|
+
bidPublisher: new BidPublisher({
|
|
182
|
+
api,
|
|
183
|
+
config,
|
|
184
|
+
signer: builderSigner,
|
|
185
|
+
ledger,
|
|
186
|
+
builderIndex: index,
|
|
187
|
+
hasPayload: ({blockHash}) => payloadStore.has(blockHash),
|
|
188
|
+
}),
|
|
189
|
+
proposerPreferencesTracker,
|
|
190
|
+
getBuilderStatus: () => builderStatusTracker.getStatus(),
|
|
191
|
+
builderIndex: index,
|
|
192
|
+
executionFeeRecipient: opts.executionFeeRecipient,
|
|
193
|
+
metrics: opts.metrics,
|
|
194
|
+
signal,
|
|
195
|
+
},
|
|
196
|
+
opts.bidding
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const revealer = new Revealer(
|
|
200
|
+
{
|
|
201
|
+
config,
|
|
202
|
+
logger,
|
|
203
|
+
clock,
|
|
204
|
+
bidSelector: new BidSelector({config, ledger, builderIndex: index}),
|
|
205
|
+
payloadStore,
|
|
206
|
+
envelopePublisher: new EnvelopePublisher({api, signer: builderSigner, ledger, builderIndex: index}),
|
|
207
|
+
builderIndex: index,
|
|
208
|
+
metrics: opts.metrics,
|
|
209
|
+
signal,
|
|
210
|
+
},
|
|
211
|
+
{cutoffBps: opts.reveal.cutoffBps ?? config.PAYLOAD_ATTESTATION_DUE_BPS}
|
|
212
|
+
);
|
|
119
213
|
|
|
120
214
|
return new Builder({
|
|
121
215
|
opts,
|
|
@@ -126,19 +220,28 @@ export class Builder {
|
|
|
126
220
|
clock,
|
|
127
221
|
index,
|
|
128
222
|
payloadStore,
|
|
223
|
+
ledger,
|
|
224
|
+
bidder,
|
|
225
|
+
revealer,
|
|
129
226
|
});
|
|
130
227
|
}
|
|
131
228
|
|
|
132
229
|
private async onSlot(slot: number): Promise<void> {
|
|
133
230
|
this.payloadStore.prune(slot);
|
|
134
231
|
this.proposerPreferencesTracker.prune(slot);
|
|
232
|
+
this.ledger.settlePaymentsBefore(slot - PAYMENT_SETTLEMENT_SLOTS);
|
|
233
|
+
this.ledger.prune(slot);
|
|
135
234
|
}
|
|
136
235
|
|
|
137
236
|
private subscribeToEvents(api: ApiClient): void {
|
|
138
237
|
const signal = this.controller.signal;
|
|
139
238
|
if (signal.aborted) return;
|
|
140
239
|
|
|
141
|
-
const topics = [
|
|
240
|
+
const topics = [
|
|
241
|
+
routes.events.EventType.block,
|
|
242
|
+
routes.events.EventType.proposerPreferences,
|
|
243
|
+
routes.events.EventType.payloadAttributes,
|
|
244
|
+
];
|
|
142
245
|
this.logger.verbose("Subscribing to builder events", {topics: topics.join(",")});
|
|
143
246
|
api.events
|
|
144
247
|
.eventstream({
|
|
@@ -209,6 +312,9 @@ export class Builder {
|
|
|
209
312
|
case routes.events.EventType.proposerPreferences:
|
|
210
313
|
this.proposerPreferencesTracker.onProposerPreferences(event.message.data);
|
|
211
314
|
break;
|
|
315
|
+
case routes.events.EventType.payloadAttributes:
|
|
316
|
+
await this.bidder.onPayloadAttributes(event.message);
|
|
317
|
+
break;
|
|
212
318
|
}
|
|
213
319
|
} catch (error) {
|
|
214
320
|
if (!signal.aborted && !isErrorAborted(error)) {
|