@xyo-network/chain-sdk 5.2.0 → 5.2.1

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.
Files changed (23) hide show
  1. package/dist/browser/modules/analyze/ChainHeadSelector.d.ts +16 -0
  2. package/dist/browser/modules/analyze/ChainHeadSelector.d.ts.map +1 -1
  3. package/dist/browser/modules/services/implementation/processPendingBlocks.d.ts +6 -1
  4. package/dist/browser/modules/services/implementation/processPendingBlocks.d.ts.map +1 -1
  5. package/dist/browser/modules/services/simple/block/runner/SimpleBlockRunner.d.ts +7 -0
  6. package/dist/browser/modules/services/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
  7. package/dist/neutral/analyze.mjs +33 -3
  8. package/dist/neutral/analyze.mjs.map +2 -2
  9. package/dist/neutral/modules/analyze/ChainHeadSelector.d.ts +16 -0
  10. package/dist/neutral/modules/analyze/ChainHeadSelector.d.ts.map +1 -1
  11. package/dist/neutral/modules/services/implementation/processPendingBlocks.d.ts +6 -1
  12. package/dist/neutral/modules/services/implementation/processPendingBlocks.d.ts.map +1 -1
  13. package/dist/neutral/modules/services/simple/block/runner/SimpleBlockRunner.d.ts +7 -0
  14. package/dist/neutral/modules/services/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
  15. package/dist/neutral/services.mjs +5 -1
  16. package/dist/neutral/services.mjs.map +2 -2
  17. package/dist/node/modules/analyze/ChainHeadSelector.d.ts +16 -0
  18. package/dist/node/modules/analyze/ChainHeadSelector.d.ts.map +1 -1
  19. package/dist/node/modules/services/implementation/processPendingBlocks.d.ts +6 -1
  20. package/dist/node/modules/services/implementation/processPendingBlocks.d.ts.map +1 -1
  21. package/dist/node/modules/services/simple/block/runner/SimpleBlockRunner.d.ts +7 -0
  22. package/dist/node/modules/services/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
  23. package/package.json +1 -1
@@ -24,6 +24,12 @@ export interface ChainHeadSelectorParams extends ChainFinalizerParams {
24
24
  * asked, which is what keeps a node with no stake readers running exactly as it does today.
25
25
  */
26
26
  eligibility?: ProducerEligibilityEvaluator;
27
+ /**
28
+ * Minimum epoch spacing (ms) between transaction-less heartbeat blocks this selector will
29
+ * qualify — a defense against producers heartbeating faster than the network's intended pace.
30
+ * Transaction-carrying candidates are exempt. Undefined disables the check.
31
+ */
32
+ heartbeatInterval?: number;
27
33
  mempoolViewer: MempoolViewer;
28
34
  /**
29
35
  * Minimum number of uncle candidates required before accepting one.
@@ -42,6 +48,7 @@ export declare class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorP
42
48
  protected admission: AdmissionMode;
43
49
  protected allowedProducers?: Address[];
44
50
  protected backoffMs?: number;
51
+ protected heartbeatInterval?: number;
45
52
  protected minCandidates?: number;
46
53
  private _timeSinceLastUncle;
47
54
  constructor(params: ChainHeadSelectorParams);
@@ -78,6 +85,15 @@ export declare class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorP
78
85
  * chain from finalizing.
79
86
  */
80
87
  protected assess(all: SignedHydratedBlockWithHashMeta[]): Promise<AdmissionAssessment[]>;
88
+ /**
89
+ * Defense against unwanted heartbeat rates: a transaction-less (heartbeat) candidate qualifies
90
+ * only when its signing epoch is at least heartbeatInterval after the current head's. Measured
91
+ * on chain data, so every finalizer applies the same pace deterministically regardless of wall
92
+ * clock. A producer heartbeating faster than the network's pace — misconfigured or hostile —
93
+ * cannot drive the chain's block rate: its candidates never qualify and age out of the pool,
94
+ * while transaction-carrying candidates are exempt and finalize immediately.
95
+ */
96
+ protected filterPacedHeartbeatCandidates(proposedBlocks: SignedHydratedBlockWithHashMeta[]): SignedHydratedBlockWithHashMeta[];
81
97
  /** Whether the configured allow-list admits a candidate. An empty list admits everyone. */
82
98
  protected isAllowed(candidate: SignedHydratedBlockWithHashMeta): boolean;
83
99
  /** Publishes what the two gates concluded, swallowing failures. */
@@ -1 +1 @@
1
- {"version":3,"file":"ChainHeadSelector.d.ts","sourceRoot":"","sources":["../../../../src/modules/analyze/ChainHeadSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,+BAA+B,EAC5D,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACxF,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,aAAa,EAAE,aAAa,CAAA;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAOD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5E;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,+BAA+B,QAAO;IAEtD,SAAS,CAAC,SAAS,EAAE,aAAa,CAAA;IAClC,SAAS,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IACtC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,CAAC,mBAAmB,CAAa;gBAE5B,MAAM,EAAE,uBAAuB;IAQ3C,SAAS,KAAK,OAAO;;;;;;;MAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAEK,YAAY,IAAI,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAchE;;;;;;;;;;;;;OAaG;cACa,KAAK,CACnB,GAAG,EAAE,+BAA+B,EAAE,EACtC,OAAO,EAAE,+BAA+B,EAAE,GACzC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAW7C;;;;;;OAMG;cACa,MAAM,CAAC,GAAG,EAAE,+BAA+B,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAmB9F,2FAA2F;IAC3F,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,+BAA+B,GAAG,OAAO;IAOxE,mEAAmE;cACnD,aAAa,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;CAoBpC"}
1
+ {"version":3,"file":"ChainHeadSelector.d.ts","sourceRoot":"","sources":["../../../../src/modules/analyze/ChainHeadSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,+BAA+B,EAC5D,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACxF,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,aAAa,CAAA;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAOD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5E;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,+BAA+B,QAAO;IAEtD,SAAS,CAAC,SAAS,EAAE,aAAa,CAAA;IAClC,SAAS,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IACtC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IACpC,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,CAAC,mBAAmB,CAAa;gBAE5B,MAAM,EAAE,uBAAuB;IAS3C,SAAS,KAAK,OAAO;;;;;;;MAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAEK,YAAY,IAAI,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAehE;;;;;;;;;;;;;OAaG;cACa,KAAK,CACnB,GAAG,EAAE,+BAA+B,EAAE,EACtC,OAAO,EAAE,+BAA+B,EAAE,GACzC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAW7C;;;;;;OAMG;cACa,MAAM,CAAC,GAAG,EAAE,+BAA+B,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAmB9F;;;;;;;OAOG;IACH,SAAS,CAAC,8BAA8B,CAAC,cAAc,EAAE,+BAA+B,EAAE,GAAG,+BAA+B,EAAE;IAqB9H,2FAA2F;IAC3F,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,+BAA+B,GAAG,OAAO;IAOxE,mEAAmE;cACnD,aAAa,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;CAoBpC"}
@@ -14,6 +14,11 @@ interface ProcessPendingBlocksParams {
14
14
  /** Computes producer standing, for the shadow and enforce postures. */
15
15
  eligibility?: ProducerEligibilityEvaluator;
16
16
  finalizationRunner: FinalizationRunner;
17
+ /**
18
+ * Minimum epoch spacing (ms) between transaction-less heartbeat blocks the head selector will
19
+ * qualify; transaction-carrying candidates are exempt. Undefined disables the pace check.
20
+ */
21
+ heartbeatInterval?: number;
17
22
  logger?: Logger;
18
23
  mempoolViewer: MempoolViewer;
19
24
  minCandidates?: number;
@@ -25,7 +30,7 @@ interface ProcessPendingBlocksParams {
25
30
  /** Where to publish what both admission gates concluded, in shadow posture. */
26
31
  publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>;
27
32
  }
28
- export declare function processPendingBlocks({ blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, minCandidates, deadLetterQueueRunner, observer, admission, eligibility, publishAdmissionShadow, }: ProcessPendingBlocksParams): Promise<[{
33
+ export declare function processPendingBlocks({ blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, heartbeatInterval, minCandidates, deadLetterQueueRunner, observer, admission, eligibility, publishAdmissionShadow, }: ProcessPendingBlocksParams): Promise<[{
29
34
  schema: "network.xyo.boundwitness" & {
30
35
  readonly __schema: true;
31
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"processPendingBlocks.d.ts","sourceRoot":"","sources":["../../../../../src/modules/services/implementation/processPendingBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EACV,WAAW,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAA6B,aAAa,EACrI,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACnE,MAAM,UAAU,CAAA;AAKjB,UAAU,0BAA0B;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,uEAAuE;IACvE,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAgCD,wBAAsB,oBAAoB,CAAC,EACzC,qBAAqB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EACnK,SAAS,EAAE,WAAW,EAAE,sBAAsB,GAC/C,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA2E5B"}
1
+ {"version":3,"file":"processPendingBlocks.d.ts","sourceRoot":"","sources":["../../../../../src/modules/services/implementation/processPendingBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EACV,WAAW,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAA6B,aAAa,EACrI,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACnE,MAAM,UAAU,CAAA;AAKjB,UAAU,0BAA0B;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,uEAAuE;IACvE,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,kBAAkB,EAAE,kBAAkB,CAAA;IACtC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAgCD,wBAAsB,oBAAoB,CAAC,EACzC,qBAAqB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EACtL,SAAS,EAAE,WAAW,EAAE,sBAAsB,GAC/C,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA4E5B"}
@@ -13,6 +13,13 @@ interface ExcludedTransactionEntry {
13
13
  * The default block size for a block
14
14
  */
15
15
  export declare const DEFAULT_BLOCK_SIZE = 10;
16
+ /**
17
+ * Default minimum age (ms) of the head before a producer emits a transaction-less heartbeat
18
+ * block. Five minutes keeps a quiet chain visibly alive without accumulating meaningful storage
19
+ * or block-reward drift. Finalizers use the same default as the floor for how fast they will
20
+ * finalize heartbeat blocks.
21
+ */
22
+ export declare const DEFAULT_HEARTBEAT_INTERVAL = 300000;
16
23
  /**
17
24
  * The amount of time for which a producer will restake their intent
18
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleBlockRunner.d.ts","sourceRoot":"","sources":["../../../../../../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAAQ,UAAU,EAC1B,MAAM,iBAAiB,CAAA;AAKxB,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAAE,YAAY,EAChC,MAAM,kBAAkB,CAAA;AAKzB,OAAO,KAAK,EACV,oBAAoB,EAAuB,iBAAiB,EACxC,iBAAiB,EAAE,WAAW,EAAE,qBAAqB,EACzE,gBAAgB,EAAE,uBAAuB,EACzC,qBAAqB,EACrB,kBAAkB,EAClB,oCAAoC,EAAgC,aAAa,EACjF,mCAAmC,EACnC,+BAA+B,EAClB,cAAc,EAAE,QAAQ,EACtC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,yBAAyB,EAQ1B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAKlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AAK3E,uFAAuF;AACvF,UAAU,wBAAwB;IAChC,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;GAEG;AACH,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,iCAAiC,MAAM,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,4FAA4F;IAC5F,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,6BAA6B,CAAC,EAAE,iBAAiB,CAAA;IACjD,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,0BAA0B,CAAC,EAAE,oCAAoC,CAAA;CAClE;AAED,qBACa,iBAAkB,SAAQ,yBAAyB,CAAC,uBAAuB,CAAE,YAAW,WAAW;IAC9G;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,sBAAsB,QAAO;IAE7C,MAAM,CAAC,QAAQ,CAAC,eAAe,uCAAuC;IACtE,MAAM,CAAC,QAAQ,CAAC,cAAc,gBAAqB;IACnD,MAAM,CAAC,QAAQ,CAAC,YAAY,yIAO3B;IAED,MAAM,CAAC,QAAQ,CAAC,QAAQ,kBAAuB;IAE/C,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAG,MAAM,CAAS;IAEzC,OAAO,gBAAmC;IAE1C,SAAS,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,CAAA;IAClD,SAAS,CAAC,sBAAsB,CAAC,EAAE,qBAAqB,CAAA;IAMxD,SAAS,CAAC,0BAA0B,uEAA4C;IAChF,SAAS,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAC1C,SAAS,CAAC,8BAA8B,CAAC,EAAE,iBAAiB,CAAA;IAE5D,OAAO,CAAC,QAAQ,CAAC,CAAiB;IAClC,OAAO,CAAC,qBAAqB,CAAC,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAC9C,OAAO,CAAC,sBAAsB,CAAC,CAAuB;IACtD,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAC9C,OAAO,CAAC,mBAAmB,CAAC,CAAoB;IAChD,OAAO,CAAC,oBAAoB,CAAI;IAChC,0FAA0F;IAC1F,OAAO,CAAC,oBAAoB,CAAC,CAA+C;IAC5E,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,eAAe,CAAC,CAAgB;IAExC;;OAEG;IACH,MAAM,KAAK,gBAAgB,IAAI,MAAM,CAEpC;IAED;;;OAGG;IACH,MAAM,KAAK,qBAAqB,IAAI,MAAM,CAEzC;IAED;;;OAGG;IACH,MAAM,KAAK,mBAAmB,IAAI,MAAM,CAEvC;IAED,SAAS,KAAK,OAAO,oBAEpB;IAED,SAAS,KAAK,oBAAoB,yBAEjC;IAED,SAAS,KAAK,OAAO;;;;MAEpB;IAED,SAAS,KAAK,iBAAiB,sBAE9B;IAED,SAAS,KAAK,qBAAqB,0BAElC;IAED,SAAS,KAAK,kBAAkB,uBAE/B;IAED,SAAS,KAAK,iBAAiB,WAE9B;IAED,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,cAAc;;;;MAE3B;IAMD,SAAS,KAAK,6BAA6B,mPAE1C;IAED,SAAS,KAAK,aAAa,IAAI,OAAO,CAErC;IAMD,SAAS,KAAK,cAAc,IAAI,cAAc,CAE7C;IAMc,aAAa;IAwBtB,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,+BAA+B,GAAG,SAAS,CAAC;IAgBjG,gBAAgB,CAAC,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,+BAA+B,CAAC;IAClH,gBAAgB,CAAC,IAAI,EAAE,mCAAmC,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,+BAA+B,GAAG,SAAS,CAAC;cAOtH,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAiB3E;;;;OAIG;IACH,SAAS,CAAC,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC,iBAAiB,CAAC,GAAG,UAAU,CAAC,gBAAgB,GAAG,SAAS,CAAC;cAsBnG,qBAAqB,CAAC,IAAI,EAAE,YAAY,CAAC,iBAAiB,CAAC,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,KAAK,UAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2DtH,OAAO,CAAC,kBAAkB;YASZ,mBAAmB;IAyBjC;;;;;;;;OAQG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;YASd,cAAc;YAsDd,mBAAmB;IAUjC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,4BAA4B;IAMpC;;;;;;;;;;;;;OAaG;YACW,wBAAwB;YAOxB,oBAAoB;YAkBpB,4BAA4B;IAiC1C;;;;;;;;;;;;OAYG;YACW,iBAAiB;YASjB,yBAAyB;CAoExC"}
1
+ {"version":3,"file":"SimpleBlockRunner.d.ts","sourceRoot":"","sources":["../../../../../../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts"],"names":[],"mappings":"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"}
@@ -173,7 +173,8 @@ import {
173
173
  import {
174
174
  findBestUncle,
175
175
  findUncles,
176
- getWindowedChain
176
+ getWindowedChain,
177
+ isTransactionBoundWitness
177
178
  } from "@xyo-network/xl1-sdk";
178
179
  var ChainHeadSelector = class _ChainHeadSelector extends ChainFinalizer {
179
180
  /**
@@ -184,6 +185,7 @@ var ChainHeadSelector = class _ChainHeadSelector extends ChainFinalizer {
184
185
  admission;
185
186
  allowedProducers;
186
187
  backoffMs;
188
+ heartbeatInterval;
187
189
  minCandidates;
188
190
  _timeSinceLastUncle = Date.now();
189
191
  constructor(params) {
@@ -191,6 +193,7 @@ var ChainHeadSelector = class _ChainHeadSelector extends ChainFinalizer {
191
193
  this.admission = params.admission ?? "allowlist";
192
194
  this.allowedProducers = params.allowedProducers;
193
195
  this.backoffMs = params.backoffMs;
196
+ this.heartbeatInterval = params.heartbeatInterval;
194
197
  this.minCandidates = params.minCandidates;
195
198
  }
196
199
  get context() {
@@ -205,8 +208,9 @@ var ChainHeadSelector = class _ChainHeadSelector extends ChainFinalizer {
205
208
  const allowed = allProposedBlocks.filter((pb) => this.isAllowed(pb));
206
209
  const proposedBlocks = await this.admit(allProposedBlocks, allowed);
207
210
  this.windowedFinalizedChain = await getWindowedChain(this.context, this.blockViewer, this.maxWindowSize, this.windowedFinalizedChain);
208
- const uncles = findUncles(this.context, this.windowedFinalizedChain, proposedBlocks);
209
- this.reportSilentUncleRejections(proposedBlocks, uncles.length);
211
+ const pacedBlocks = this.filterPacedHeartbeatCandidates(proposedBlocks);
212
+ const uncles = findUncles(this.context, this.windowedFinalizedChain, pacedBlocks);
213
+ this.reportSilentUncleRejections(pacedBlocks, uncles.length);
210
214
  return findBestUncle(this.windowedFinalizedChain, uncles, { backoffMs: this.backoffMs, minCandidates: this.minCandidates }) ?? this.windowedFinalizedChain;
211
215
  }, this.context);
212
216
  }
@@ -257,6 +261,32 @@ var ChainHeadSelector = class _ChainHeadSelector extends ChainFinalizer {
257
261
  producer: candidate[0].addresses[0]
258
262
  })));
259
263
  }
264
+ /**
265
+ * Defense against unwanted heartbeat rates: a transaction-less (heartbeat) candidate qualifies
266
+ * only when its signing epoch is at least heartbeatInterval after the current head's. Measured
267
+ * on chain data, so every finalizer applies the same pace deterministically regardless of wall
268
+ * clock. A producer heartbeating faster than the network's pace — misconfigured or hostile —
269
+ * cannot drive the chain's block rate: its candidates never qualify and age out of the pool,
270
+ * while transaction-carrying candidates are exempt and finalize immediately.
271
+ */
272
+ filterPacedHeartbeatCandidates(proposedBlocks) {
273
+ const interval = this.heartbeatInterval;
274
+ if (interval === void 0 || proposedBlocks.length === 0) return proposedBlocks;
275
+ const headEpoch = this.windowedFinalizedChain.at(-1)?.[0].$epoch;
276
+ if (!isDefined2(headEpoch)) return proposedBlocks;
277
+ const paced = proposedBlocks.filter((candidate) => {
278
+ if (candidate[1].some((payload) => isTransactionBoundWitness(payload))) return true;
279
+ const candidateEpoch = candidate[0].$epoch;
280
+ if (!isDefined2(candidateEpoch)) return true;
281
+ return candidateEpoch - headEpoch >= interval;
282
+ });
283
+ if (paced.length < proposedBlocks.length) {
284
+ this.context.logger?.debug(
285
+ `findBestHead: paced out ${proposedBlocks.length - paced.length} heartbeat candidate(s) younger than ${interval}ms since the head`
286
+ );
287
+ }
288
+ return paced;
289
+ }
260
290
  /** Whether the configured allow-list admits a candidate. An empty list admits everyone. */
261
291
  isAllowed(candidate) {
262
292
  const allowedProducers = this.allowedProducers;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/modules/analyze/admission.ts", "../../src/modules/analyze/analyzeChain.ts", "../../src/modules/analyze/BalanceAnalyzer/BalanceAnalyzer.ts", "../../src/modules/analyze/BalanceAnalyzer/ChainSummaryBalances.ts", "../../src/modules/analyze/ChainFinalizer.ts", "../../src/modules/analyze/ChainHeadSelector.ts", "../../src/modules/analyze/producer/ChainProducersAnalyzer.ts", "../../src/modules/analyze/producer/ChainSummaryProducers.ts", "../../src/modules/analyze/producer/ChainStakeIntentAnalyzer.ts", "../../src/modules/analyze/producer/ChainSummaryStakeIntent.ts", "../../src/modules/analyze/TransferAnalyzer/ChainSummaryTransfers.ts", "../../src/modules/analyze/TransferAnalyzer/TransferAnalyzer.ts"],
4
- "sourcesContent": ["import type { Promisable } from '@ariestools/sdk'\nimport type { XyoAddress } from '@xyo-network/sdk'\nimport type { SignedHydratedBlockWithHashMeta } from '@xyo-network/xl1-sdk'\n\nimport type { EligibilityEvaluation } from '#slashing'\n\n/**\n * How a finalizer decides which candidates it will consider.\n *\n * Three postures, and moving between them is a configuration change rather than a different\n * build. That constraint is deliberate: a network that had to be redeployed to step back from\n * enforcement would, in the moment it most needed to step back, be unable to.\n *\n * - `allowlist` \u2014 only the named producers, which is how the chain runs today\n * - `shadow` \u2014 the same gate, plus participation computed and published for every candidate\n * - `enforce` \u2014 participation itself gates\n */\nexport const AdmissionModes = ['allowlist', 'shadow', 'enforce'] as const\n\n/** How a finalizer decides which candidates it will consider. */\nexport type AdmissionMode = typeof AdmissionModes[number]\n\n/** Evaluates whether a candidate's producer had standing to produce it. */\nexport type ProducerEligibilityEvaluator\n = (candidate: SignedHydratedBlockWithHashMeta) => Promisable<EligibilityEvaluation>\n\n/** What both gates concluded about one candidate. */\nexport interface AdmissionAssessment {\n /** Whether the allow-list admits it. */\n admittedByAllowList: boolean\n /** The candidate's height. */\n block: number\n /** The candidate's signed identity. */\n dataHash: string\n /** What the participation predicate concluded. */\n eligibility: EligibilityEvaluation\n /** The producer. */\n producer: XyoAddress\n}\n\n/**\n * What the two gates said about a round of candidates, and where they disagreed.\n *\n * Published rather than logged, because the whole purpose of the shadow posture is that anyone \u2014\n * not just the operator holding the terminal \u2014 can see what enforcement would have done before it\n * does it. An operator convinced by their own logs has convinced nobody.\n */\nexport interface AdmissionShadowReport {\n /** Every candidate considered this round. */\n assessments: AdmissionAssessment[]\n /** Only those where the two gates disagreed. */\n divergent: AdmissionAssessment[]\n /** The finalized height this round was selected against. */\n head: number\n}\n\n/** Moniker the admission shadow publisher resolves under. */\nexport const AdmissionShadowPublishRunnerMoniker = 'AdmissionShadowPublishRunner'\n\n/**\n * Publishes what both admission gates concluded.\n *\n * An interface rather than a class here because the finalizer must not depend on the launcher\n * that supplies the implementation \u2014 the actor states what it needs, and orchestration decides\n * what satisfies it.\n */\nexport interface AdmissionShadowPublishRunner {\n publish(report: AdmissionShadowReport): Promisable<void>\n}\n\n/** Whether a resolved provider can actually publish shadow reports. */\nexport function isAdmissionShadowPublishRunner(value: unknown): value is AdmissionShadowPublishRunner {\n return typeof (value as Partial<AdmissionShadowPublishRunner> | undefined)?.publish === 'function'\n}\n\n/** Whether the two gates reached different conclusions about a candidate. */\nexport function isDivergent(assessment: AdmissionAssessment): boolean {\n // an unresolvable evaluation is not a disagreement \u2014 it is an absence of one\n if (!assessment.eligibility.resolvable) return false\n return assessment.admittedByAllowList !== (assessment.eligibility.eligible === true)\n}\n", "/* eslint-disable complexity */\nimport type { Hash } from '@ariestools/sdk'\nimport {\n assertEx, isError, spanRootAsync,\n} from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport type {\n BlockContextRead,\n ChainAnalyzer,\n HydratedBlock, HydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { hydrateBlock } from '@xyo-network/xl1-sdk'\n\nconst analyzeBlock = async (block: HydratedBlock, handlers: ChainAnalyzer[]): Promise<HydratedBlock> => {\n await Promise.all(handlers.map(async (handler) => {\n await handler.onBlock(block)\n }))\n return block\n}\n\nexport const analyzeChain = async (\n context: BlockContextRead,\n handlers: ChainAnalyzer[],\n /* the hash to start at */\n head: Hash | HydratedBlockWithHashMeta,\n /* a hash that we should stop at if we reach it */\n previousHead: Hash | null = null,\n /* max number of blocks to analyze (-1 for no limit) */\n maxDepth = -1n,\n): Promise<Payload[]> => {\n const { logger } = context\n logger?.log('analyzeChain.start', previousHead)\n return assertEx(await spanRootAsync('analyzeChain', async () => {\n let lastBlockNumber = -1\n let maxDepthLimit = maxDepth === -1n ? BigInt(Number.MAX_SAFE_INTEGER) : maxDepth\n let cursor: HydratedBlockWithHashMeta | null = typeof head === 'string' ? await hydrateBlock(context, head) : head\n // If the terminal block is the current head, we don't need to analyze it\n logger?.log('analyzeChain.cursor', cursor?.[0].block)\n if (previousHead !== null && cursor?.[0]._hash === previousHead) return []\n while (cursor && (maxDepthLimit > 0n)) {\n maxDepthLimit -= 1n\n await analyzeBlock(cursor, handlers)\n lastBlockNumber = cursor[0].block\n try {\n cursor = cursor[0].previous === null ? null : await hydrateBlock(context, cursor[0].previous)\n } catch (ex) {\n if (isError(ex)) {\n logger?.warn('Error in hydrateBlock', ex)\n }\n break\n }\n if (cursor?.[0]._hash === previousHead) break\n }\n if (previousHead === null && maxDepth === -1n && lastBlockNumber !== 0) {\n logger?.warn(`Expected root block number to be 0, but was ${lastBlockNumber} : ${previousHead}`)\n }\n logger?.log('analyzeChain.done', lastBlockNumber)\n return handlers.map((handler) => {\n return handler.result()\n })\n }, context), () => 'analyzeChain failed')\n}\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport { isDefined, toAddress } from '@ariestools/sdk'\nimport { trace, type Tracer } from '@opentelemetry/api'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n ChainAnalyzer,\n HydratedBlockWithHashMeta, SignedBigInt,\n} from '@xyo-network/xl1-sdk'\nimport {\n netBalancesForPayloads,\n parseSignedBigInt, toSignedBigInt,\n} from '@xyo-network/xl1-sdk'\n\nimport type { ChainSummaryBalances } from './ChainSummaryBalances.ts'\nimport { ChainSummaryBalancesSchema } from './ChainSummaryBalances.ts'\n\nconst bigintBalances = (balances: Partial<Record<Address, SignedBigInt>>) => {\n const result: Record<string, bigint> = {}\n for (const [address, balance] of Object.entries(balances)) {\n if (isDefined(balance)) {\n const propertyKey = String(toAddress(address))\n result[propertyKey] = parseSignedBigInt(balance)\n }\n }\n return result\n}\n\nexport class BalanceAnalyzer implements ChainAnalyzer {\n protected _tracer: Tracer | undefined\n private _addresses: Address[]\n private _balances: Record<string, bigint> = {}\n private _firstBlock?: Hash\n private _lastBlock?: Hash\n private _minBalances: bigint[]\n\n constructor(addresses: Address[] = [], minBalances: bigint[] = [], startingBalances?: ChainSummaryBalances) {\n this._addresses = addresses\n this._minBalances = minBalances\n this._balances = startingBalances ? bigintBalances(startingBalances.balances) : {}\n }\n\n protected get tracer() {\n if (this._tracer) return this._tracer\n this._tracer = trace.getTracer('BalanceAnalyzer')\n return this._tracer\n }\n\n onBlock([block, payloads]: HydratedBlockWithHashMeta): boolean {\n this._firstBlock = this._firstBlock ?? block._hash\n this._lastBlock = block._hash\n const netBalances = netBalancesForPayloads({ singletons: {} }, payloads)\n for (const [address, balance] of Object.entries(netBalances)) {\n const propertyKey = String(toAddress(address))\n this._balances[propertyKey] = (this._balances[propertyKey] ?? 0n) + balance\n }\n return this.shouldContinue()\n }\n\n result() {\n const balances: Record<string, SignedBigInt> = {}\n const positiveBalances = Object.entries(this._balances).filter(([, balance]) => balance > 0n)\n for (const [address, balance] of positiveBalances) {\n const propertyKey = String(toAddress(address))\n balances[propertyKey] = toSignedBigInt(balance)\n }\n const builder = new PayloadBuilder<ChainSummaryBalances>({ schema: ChainSummaryBalancesSchema })\n return builder.fields({\n firstBlock: this._firstBlock ?? null,\n lastBlock: this._lastBlock ?? null,\n balances,\n }).build()\n }\n\n shouldContinue() {\n return !this.allMinBalancesReached()\n }\n\n protected allMinBalancesReached() {\n if (this._minBalances.length === 0) return true\n for (let i = 0; i < this._addresses.length; i++) {\n const propertyKey = String(this._addresses[i])\n if ((this._balances[propertyKey] ?? 0n) < this._minBalances[i]) return false\n }\n return true\n }\n}\n", "import {\n type Address, type Hash, type Hex,\n} from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\nimport type { SignedBigInt } from '@xyo-network/xl1-sdk'\n\nexport const ChainSummaryBalancesSchema = asSchema('network.xyo.chain.summary.balances', true)\nexport type ChainSummaryBalancesSchema = typeof ChainSummaryBalancesSchema\n\nexport interface ChainSummaryBalancesFields {\n balances: Partial<Record<Address, SignedBigInt>>\n firstBlock: Hash | null\n hasMinBalance?: Record<Address, Hex>\n lastBlock: Hash | null\n}\n\nexport type ChainSummaryBalances = Payload<ChainSummaryBalancesFields, ChainSummaryBalancesSchema>\nexport const isChainSummaryBalances = isPayloadOfSchemaType<ChainSummaryBalances>(ChainSummaryBalancesSchema)\n", "import type { BaseParams, Promisable } from '@ariestools/sdk'\nimport { Base } from '@ariestools/sdk'\nimport type { Tracer } from '@opentelemetry/api'\nimport type { BlockViewer, SignedHydratedBlockWithHashMeta } from '@xyo-network/xl1-sdk'\nimport { asXL1BlockRange } from '@xyo-network/xl1-sdk'\n\nexport interface ChainFinalizerParams extends BaseParams {\n blockViewer: BlockViewer\n maxWindowSize?: number\n windowedFinalizedChain?: SignedHydratedBlockWithHashMeta[]\n}\n\nexport class ChainFinalizer<TParams extends ChainFinalizerParams = ChainFinalizerParams> extends Base<TParams> {\n protected _tracer: Tracer | undefined\n // the chainArchivist is assumed to be an archivist with already validated blocks in it along with all the transactions and payloads\n // it is also assumed that the sequence order of archivist is that newer blocks come after older blocks\n\n protected windowedFinalizedChain: SignedHydratedBlockWithHashMeta[]\n\n constructor(params: TParams) {\n super(params)\n this.windowedFinalizedChain = [...(params.windowedFinalizedChain ?? [])]\n }\n\n protected get blockViewer() {\n return this.params.blockViewer\n }\n\n protected get finalizedBlockNumber() {\n return this.windowedFinalizedChain?.at(-1)?.[0].block ?? -1\n }\n\n protected get maxWindowSize() {\n return this.params.maxWindowSize ?? 100\n }\n\n protected get windowRange() {\n return asXL1BlockRange([this.windowedFinalizedChain.at(0)?.[0].block ?? 0, this.finalizedBlockNumber])\n }\n\n finalizeChainFragment(chain: SignedHydratedBlockWithHashMeta[]): Promisable<void> {\n this.windowedFinalizedChain = [...this.windowedFinalizedChain, ...chain].slice(-this.maxWindowSize)\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport {\n isDefined, spanRootAsync, toAddress,\n} from '@ariestools/sdk'\nimport type {\n BaseContext, MempoolViewer, SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport {\n findBestUncle, findUncles, getWindowedChain,\n} from '@xyo-network/xl1-sdk'\n\nimport type {\n AdmissionAssessment, AdmissionMode, AdmissionShadowReport, ProducerEligibilityEvaluator,\n} from './admission.ts'\nimport { isDivergent } from './admission.ts'\nimport type { ChainFinalizerParams } from './ChainFinalizer.ts'\nimport { ChainFinalizer } from './ChainFinalizer.ts'\n\nexport interface ChainHeadSelectorParams extends ChainFinalizerParams {\n /**\n * How candidates are admitted. Defaults to `allowlist`, which is how the chain runs today.\n */\n admission?: AdmissionMode\n /**\n * List of allowed producer addresses, if undefined anyone can participate\n */\n allowedProducers?: Address[]\n /**\n * Back-off timeout (ms) after which a head is accepted even with fewer than\n * minCandidates uncle chains available.\n * When undefined, findBestUncle applies DEFAULT_BACKOFF_MS from the protocol SDK.\n */\n backoffMs?: number\n context: BaseContext\n /**\n * Computes whether a candidate's producer had standing. Absent means the question is never\n * asked, which is what keeps a node with no stake readers running exactly as it does today.\n */\n eligibility?: ProducerEligibilityEvaluator\n mempoolViewer: MempoolViewer\n /**\n * Minimum number of uncle candidates required before accepting one.\n * When undefined, findBestUncle applies DEFAULT_MIN_CANDIDATES from the protocol SDK.\n */\n minCandidates?: number\n /** Where to publish what the two gates concluded, in shadow posture. */\n publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>\n}\n\ninterface UncleSelectionHealth {\n lastWarnedAt: number\n unqualifiedSince?: number\n}\n\nexport class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorParams> {\n /**\n * How long uncle selection may go without a single qualifying candidate (while candidates are\n * present) before a warning is emitted; also the minimum interval between repeat warnings.\n */\n static readonly SilentUncleRejectionWarnAfterMs = 5000\n\n protected admission: AdmissionMode\n protected allowedProducers?: Address[]\n protected backoffMs?: number\n protected minCandidates?: number\n private _timeSinceLastUncle = Date.now()\n\n constructor(params: ChainHeadSelectorParams) {\n super(params)\n this.admission = params.admission ?? 'allowlist'\n this.allowedProducers = params.allowedProducers\n this.backoffMs = params.backoffMs\n this.minCandidates = params.minCandidates\n }\n\n protected get context() {\n return this.params.context\n }\n\n protected get mempoolViewer() {\n return this.params.mempoolViewer\n }\n\n async findBestHead(): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await spanRootAsync('findBestHead', async () => {\n const allProposedBlocks = await this.mempoolViewer.pendingBlocks()\n const allowed = allProposedBlocks.filter(pb => this.isAllowed(pb))\n const proposedBlocks = await this.admit(allProposedBlocks, allowed)\n\n // TODO: Validate proposed blocks\n this.windowedFinalizedChain = await getWindowedChain(this.context, this.blockViewer, this.maxWindowSize, this.windowedFinalizedChain)\n const uncles = findUncles(this.context, this.windowedFinalizedChain, proposedBlocks)\n this.reportSilentUncleRejections(proposedBlocks, uncles.length)\n return findBestUncle(this.windowedFinalizedChain, uncles, { backoffMs: this.backoffMs, minCandidates: this.minCandidates }) ?? this.windowedFinalizedChain\n }, this.context)\n }\n\n /**\n * Applies the configured admission posture.\n *\n * In `shadow` the allow-list still decides \u2014 participation is computed and published beside it,\n * and changes nothing. That is the entire value of the posture: the network keeps behaving\n * exactly as it did while everyone gets to see what the new rule would have done.\n *\n * In `enforce` participation gates, but only when it reached a conclusion. A candidate whose\n * standing cannot be established is admitted, not rejected \u2014 otherwise a finalizer that lost\n * its stake reader would quietly stop accepting anyone's blocks and stall the chain.\n *\n * Assessments publish in both postures. The audit trail must not disappear at the moment\n * admission starts gating \u2014 enforce is when it matters most.\n */\n protected async admit(\n all: SignedHydratedBlockWithHashMeta[],\n allowed: SignedHydratedBlockWithHashMeta[],\n ): Promise<SignedHydratedBlockWithHashMeta[]> {\n if (this.admission === 'allowlist' || this.params.eligibility === undefined) return allowed\n const assessments = await this.assess(all)\n await this.publishShadow(assessments)\n if (this.admission === 'shadow') return allowed\n const ineligible = new Set(assessments\n .filter(assessment => assessment.eligibility.resolvable && assessment.eligibility.eligible !== true)\n .map(assessment => assessment.dataHash))\n return allowed.filter(candidate => !ineligible.has(candidate[0]._dataHash))\n }\n\n /**\n * Runs both gates over every candidate.\n *\n * An evaluator that throws yields an unresolvable assessment rather than an exception: this\n * sits on the head-selection path, and a flaky stake reader must never be able to stop the\n * chain from finalizing.\n */\n protected async assess(all: SignedHydratedBlockWithHashMeta[]): Promise<AdmissionAssessment[]> {\n const evaluate = this.params.eligibility\n if (evaluate === undefined) return []\n const evaluateSafely = async (candidate: SignedHydratedBlockWithHashMeta) => {\n try {\n return await evaluate(candidate)\n } catch {\n return { resolvable: false }\n }\n }\n return await Promise.all(all.map(async candidate => ({\n admittedByAllowList: this.isAllowed(candidate),\n block: candidate[0].block,\n dataHash: candidate[0]._dataHash,\n eligibility: await evaluateSafely(candidate),\n producer: candidate[0].addresses[0],\n })))\n }\n\n /** Whether the configured allow-list admits a candidate. An empty list admits everyone. */\n protected isAllowed(candidate: SignedHydratedBlockWithHashMeta): boolean {\n const allowedProducers = this.allowedProducers\n return isDefined(allowedProducers) && allowedProducers.length > 0\n ? allowedProducers.includes(toAddress(candidate[0].addresses[0]))\n : true\n }\n\n /** Publishes what the two gates concluded, swallowing failures. */\n protected async publishShadow(assessments: AdmissionAssessment[]): Promise<void> {\n const publish = this.params.publishAdmissionShadow\n // an empty round says nothing worth a write\n if (publish === undefined || assessments.length === 0) return\n try {\n await publish({\n assessments,\n divergent: assessments.filter(assessment => isDivergent(assessment)),\n head: this.windowedFinalizedChain[0]?.[0]?.block ?? 0,\n })\n } catch {\n // observing must never be able to stop the chain from finalizing\n }\n }\n\n /**\n * Surfaces the otherwise-silent case where candidates are continuously present but none\n * qualifies as an uncle \u2014 without this, the only signal of a stalled selector is an endless\n * \"No new blocks found N to N\" while rejected candidates cycle through the pool. Zero-qualify\n * moments are routine in healthy operation (a just-finalized candidate lingers until the pool\n * GC), so this warns only after candidates have been failing continuously for\n * SilentUncleRejectionWarnAfterMs \u2014 an idle (candidate-free) tick resets the clock \u2014 then\n * rate-limits to one warn per that interval. State lives in context.singletons because a\n * fresh ChainHeadSelector is constructed on every finalization tick.\n */\n private reportSilentUncleRejections(proposedBlocks: SignedHydratedBlockWithHashMeta[], uncleCount: number): void {\n const singletons = this.context.singletons\n const stateKey = 'ChainHeadSelector:uncleSelectionHealth'\n const now = Date.now()\n const state = (singletons[stateKey] ?? { lastWarnedAt: 0 }) as UncleSelectionHealth\n singletons[stateKey] = state\n if (uncleCount > 0 || proposedBlocks.length === 0) {\n state.unqualifiedSince = undefined\n return\n }\n state.unqualifiedSince ??= now\n if (now - state.unqualifiedSince < ChainHeadSelector.SilentUncleRejectionWarnAfterMs) return\n if (now - state.lastWarnedAt < ChainHeadSelector.SilentUncleRejectionWarnAfterMs) return\n state.lastWarnedAt = now\n this.context.logger?.warn(\n `findBestHead: candidates have failed uncle qualification continuously for ${now - state.unqualifiedSince}ms \u2014 `\n + `${proposedBlocks.length} pending candidate(s): `\n + proposedBlocks.map(b => `${b[0].block} [${b[0]._hash}]`).join(', '),\n )\n }\n}\n\n/*\n\nComparing two heads for which is better\n\nProducer Energy\n\n1. +1 Point for every block not produced by it in recent chain LOG(active producers * 100)\n2a. Energy Multiplied by - # of transactions in block is above normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n2b. Energy Divided by - # of transactions in block is below normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n3a. Energy Multiplied by - # of gas in block is above normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n3b. Energy Divided by - # of gas in block is below normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n\nOther Ideas\n\n1. Total diverse addresses in block (not quite incentivizing what we really want)\n2. Total transactions in block (more is better, encourages non-lethargic blocks)\n3. Sum total of transactions in block (higher value means more influential/better)\n4. Sum of gas of transactions in block (higher is better, prioritizes paying contributors)\n5. Exp of transactions in block (lower is better, prioritizes not aging out before inclusion)\n6. Recency of this producer's last produced block (encourages diversification in block producers)\n\n*/\n", "import type { Promisable } from '@ariestools/sdk'\nimport { isDefined, toAddress } from '@ariestools/sdk'\nimport { type ChainAnalyzer, type HydratedBlock } from '@xyo-network/xl1-sdk'\n\nimport type { AnalyzedProducer, ChainSummaryProducers } from './ChainSummaryProducers.ts'\nimport { ChainSummaryProducersSchema } from './ChainSummaryProducers.ts'\n\nexport class ChainProducersAnalyzer implements ChainAnalyzer<ChainSummaryProducers> {\n private endingBlock = 0\n private producers: Record<string, AnalyzedProducer> = {}\n private startingBlock = 0\n\n onBlock([block]: HydratedBlock): Promisable<boolean> {\n // avoid analyzing the same block twice\n if (block.block === this.endingBlock) return true\n\n // update the ending block\n this.endingBlock = block.block\n const blockProducerAddressRaw = block.addresses[0]\n\n if (blockProducerAddressRaw === undefined) return true\n\n const blockProducerAddress = toAddress(blockProducerAddressRaw)\n\n const producerKey = String(blockProducerAddress)\n const existingProducer: AnalyzedProducer | undefined = this.producers[producerKey]\n if (isDefined(existingProducer)) {\n existingProducer.rewardsEarned = (existingProducer.rewardsEarned ?? 0n) + 0n\n existingProducer.blocksProduced++\n } else {\n const newProducer: AnalyzedProducer = {\n address: blockProducerAddress, rewardsEarned: 0n, blocksProduced: 1,\n }\n this.producers[producerKey] = newProducer\n }\n\n return true\n }\n\n result(): ChainSummaryProducers {\n return {\n endingBlock: this.endingBlock,\n producers: this.producers,\n schema: ChainSummaryProducersSchema,\n startingBlock: this.startingBlock,\n }\n }\n\n shouldContinue(): boolean {\n return true\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\n\nexport const ChainSummaryProducersSchema = asSchema('network.xyo.chain.summary.producers', true)\nexport type ChainSummaryProducersSchema = typeof ChainSummaryProducersSchema\n\nexport interface AnalyzedProducer {\n address: Address\n blocksProduced: number\n rewardsEarned: bigint\n}\n\nexport interface ChainSummaryProducersFields {\n endingBlock: number\n producers: Record<string, AnalyzedProducer>\n startingBlock: number\n}\n\nexport type ChainSummaryProducers = Payload<ChainSummaryProducersFields, ChainSummaryProducersSchema>\nexport const isChainSummaryProducers = isPayloadOfSchemaType<ChainSummaryProducers>(ChainSummaryProducersSchema)\n", "import type { Promisable } from '@ariestools/sdk'\nimport { assertEx } from '@ariestools/sdk'\nimport {\n type ChainAnalyzer, type ChainStakeIntent, type HydratedBlock,\n type Intent,\n isChainStakeIntentWithStorageMeta,\n} from '@xyo-network/xl1-sdk'\n\nimport type { ChainSummaryStakeIntent } from './ChainSummaryStakeIntent.ts'\nimport { ChainSummaryStakeIntentSchema } from './ChainSummaryStakeIntent.ts'\n\nexport class ChainStakeIntentAnalyzer implements ChainAnalyzer<ChainSummaryStakeIntent> {\n private _endingBlock: number | undefined = undefined\n private _intent: Intent\n private _intentPayloads: ChainStakeIntent[] = []\n private _startingBlock: number | undefined = undefined\n\n constructor(intent: Intent) {\n this._intent = intent\n }\n\n onBlock([block, validatedPayloads]: HydratedBlock): Promisable<boolean> {\n this._startingBlock ??= block.block\n\n // Update the ending block\n this._endingBlock = block.block\n const intents = validatedPayloads.filter(isChainStakeIntentWithStorageMeta)\n const desiredIntents = intents.filter(intent => intent.intent === this._intent)\n this._intentPayloads.push(...desiredIntents)\n return true\n }\n\n result(): ChainSummaryStakeIntent {\n assertEx(this._startingBlock !== undefined, () => 'ChainStakeIntentAnalyzer: Invalid startingBlock')\n assertEx(this._endingBlock !== undefined, () => 'ChainStakeIntentAnalyzer: Invalid endingBlock')\n return {\n endingBlock: this._endingBlock!,\n intents: this._intentPayloads,\n schema: ChainSummaryStakeIntentSchema,\n startingBlock: this._startingBlock!,\n }\n }\n\n shouldContinue(): boolean {\n return true\n }\n}\n", "import type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\nimport type { ChainStakeIntent } from '@xyo-network/xl1-sdk'\n\nexport const ChainSummaryStakeIntentSchema = asSchema('network.xyo.chain.summary.staked.intent', true)\nexport type ChainSummaryStakeIntentSchema = typeof ChainSummaryStakeIntentSchema\n\ninterface ChainSummaryStakeIntentFields {\n endingBlock: number\n intents: ChainStakeIntent[]\n startingBlock: number\n}\n\nexport type ChainSummaryStakeIntent = Payload<ChainSummaryStakeIntentFields, ChainSummaryStakeIntentSchema>\nexport const isChainSummaryStakeIntent = isPayloadOfSchemaType<ChainSummaryStakeIntent>(ChainSummaryStakeIntentSchema)\n", "import {\n type Address, type Hash, type Hex,\n} from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\nimport type { SignedBigInt } from '@xyo-network/xl1-sdk'\n\nexport const ChainSummaryTransfersSchema = asSchema('network.xyo.chain.summary.transfers', true)\nexport type ChainSummaryTransfersSchema = typeof ChainSummaryTransfersSchema\n\nexport interface ChainSummaryTransfersFields {\n firstBlock: Hash | null\n hasMinTransfer?: Record<Address, Hex>\n lastBlock: Hash | null\n transfers: Record<Address, Record<Address, SignedBigInt>>\n}\n\nexport type ChainSummaryTransfers = Payload<ChainSummaryTransfersFields, ChainSummaryTransfersSchema>\nexport const isChainSummaryTransfers = isPayloadOfSchemaType<ChainSummaryTransfers>(ChainSummaryTransfersSchema)\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport { isDefined, toAddress } from '@ariestools/sdk'\nimport { trace, type Tracer } from '@opentelemetry/api'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n ChainAnalyzer,\n HydratedBlockWithHashMeta, SignedBigInt,\n} from '@xyo-network/xl1-sdk'\nimport {\n netTransfersForPayloads,\n parseSignedBigInt, toSignedBigInt,\n} from '@xyo-network/xl1-sdk'\n\nimport type { ChainSummaryTransfers } from './ChainSummaryTransfers.ts'\nimport { ChainSummaryTransfersSchema } from './ChainSummaryTransfers.ts'\n\nconst bigintTransfers = (transfers: Record<Address, Record<Address, SignedBigInt>>) => {\n const result: Record<string, Record<string, bigint>> = {}\n for (const [from, toMap] of Object.entries(transfers)) {\n const fromKey = String(toAddress(from))\n for (const [to, balance] of Object.entries(toMap)) {\n const toKey = String(toAddress(to))\n if (isDefined(balance)) {\n const fromTransfers = result[fromKey] ?? {}\n result[fromKey] = fromTransfers\n fromTransfers[toKey] = parseSignedBigInt(balance)\n }\n }\n }\n return result\n}\n\nexport class TransferAnalyzer implements ChainAnalyzer {\n protected _tracer: Tracer | undefined\n private _firstBlock?: Hash\n private _lastBlock?: Hash\n private _transfers: Record<string, Record<string, bigint>> = {}\n\n constructor(startingTransfers?: ChainSummaryTransfers) {\n this._transfers = startingTransfers ? bigintTransfers(startingTransfers.transfers) : {}\n }\n\n protected get tracer() {\n if (this._tracer) return this._tracer\n this._tracer = trace.getTracer('TransferAnalyzer')\n return this._tracer\n }\n\n onBlock([block, payloads]: HydratedBlockWithHashMeta): boolean {\n this._firstBlock = this._firstBlock ?? block._hash\n this._lastBlock = block._hash\n const netTransfers = netTransfersForPayloads({ singletons: {} }, payloads)\n for (const [from, toMap] of Object.entries(netTransfers)) {\n const fromKey = String(toAddress(from))\n const fromTransfers = this._transfers[fromKey] ?? {}\n this._transfers[fromKey] = fromTransfers\n for (const [to, balance] of Object.entries(toMap)) {\n const toKey = String(toAddress(to))\n fromTransfers[toKey] = (fromTransfers[toKey] ?? 0n) + balance\n }\n }\n return this.shouldContinue()\n }\n\n result() {\n const transfers: Record<string, Record<string, SignedBigInt>> = {}\n for (const [from, toMap] of Object.entries(this._transfers)) {\n const fromKey = String(toAddress(from))\n const positiveTransfers = Object.entries(toMap).filter(([, balance]) => balance > 0n)\n for (const [to, balance] of positiveTransfers) {\n const fromTransfers = transfers[fromKey] ?? {}\n transfers[fromKey] = fromTransfers\n const toKey = String(toAddress(to))\n fromTransfers[toKey] = toSignedBigInt(balance)\n }\n }\n const builder = new PayloadBuilder<ChainSummaryTransfers>({ schema: ChainSummaryTransfersSchema })\n return builder.fields({\n firstBlock: this._firstBlock ?? null,\n lastBlock: this._lastBlock ?? null,\n transfers,\n }).build()\n }\n\n shouldContinue() {\n return true\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Promisable } from '@ariestools/sdk'\nimport type { XyoAddress } from '@xyo-network/sdk'\nimport type { SignedHydratedBlockWithHashMeta } from '@xyo-network/xl1-sdk'\n\nimport type { EligibilityEvaluation } from '#slashing'\n\n/**\n * How a finalizer decides which candidates it will consider.\n *\n * Three postures, and moving between them is a configuration change rather than a different\n * build. That constraint is deliberate: a network that had to be redeployed to step back from\n * enforcement would, in the moment it most needed to step back, be unable to.\n *\n * - `allowlist` \u2014 only the named producers, which is how the chain runs today\n * - `shadow` \u2014 the same gate, plus participation computed and published for every candidate\n * - `enforce` \u2014 participation itself gates\n */\nexport const AdmissionModes = ['allowlist', 'shadow', 'enforce'] as const\n\n/** How a finalizer decides which candidates it will consider. */\nexport type AdmissionMode = typeof AdmissionModes[number]\n\n/** Evaluates whether a candidate's producer had standing to produce it. */\nexport type ProducerEligibilityEvaluator\n = (candidate: SignedHydratedBlockWithHashMeta) => Promisable<EligibilityEvaluation>\n\n/** What both gates concluded about one candidate. */\nexport interface AdmissionAssessment {\n /** Whether the allow-list admits it. */\n admittedByAllowList: boolean\n /** The candidate's height. */\n block: number\n /** The candidate's signed identity. */\n dataHash: string\n /** What the participation predicate concluded. */\n eligibility: EligibilityEvaluation\n /** The producer. */\n producer: XyoAddress\n}\n\n/**\n * What the two gates said about a round of candidates, and where they disagreed.\n *\n * Published rather than logged, because the whole purpose of the shadow posture is that anyone \u2014\n * not just the operator holding the terminal \u2014 can see what enforcement would have done before it\n * does it. An operator convinced by their own logs has convinced nobody.\n */\nexport interface AdmissionShadowReport {\n /** Every candidate considered this round. */\n assessments: AdmissionAssessment[]\n /** Only those where the two gates disagreed. */\n divergent: AdmissionAssessment[]\n /** The finalized height this round was selected against. */\n head: number\n}\n\n/** Moniker the admission shadow publisher resolves under. */\nexport const AdmissionShadowPublishRunnerMoniker = 'AdmissionShadowPublishRunner'\n\n/**\n * Publishes what both admission gates concluded.\n *\n * An interface rather than a class here because the finalizer must not depend on the launcher\n * that supplies the implementation \u2014 the actor states what it needs, and orchestration decides\n * what satisfies it.\n */\nexport interface AdmissionShadowPublishRunner {\n publish(report: AdmissionShadowReport): Promisable<void>\n}\n\n/** Whether a resolved provider can actually publish shadow reports. */\nexport function isAdmissionShadowPublishRunner(value: unknown): value is AdmissionShadowPublishRunner {\n return typeof (value as Partial<AdmissionShadowPublishRunner> | undefined)?.publish === 'function'\n}\n\n/** Whether the two gates reached different conclusions about a candidate. */\nexport function isDivergent(assessment: AdmissionAssessment): boolean {\n // an unresolvable evaluation is not a disagreement \u2014 it is an absence of one\n if (!assessment.eligibility.resolvable) return false\n return assessment.admittedByAllowList !== (assessment.eligibility.eligible === true)\n}\n", "/* eslint-disable complexity */\nimport type { Hash } from '@ariestools/sdk'\nimport {\n assertEx, isError, spanRootAsync,\n} from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport type {\n BlockContextRead,\n ChainAnalyzer,\n HydratedBlock, HydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { hydrateBlock } from '@xyo-network/xl1-sdk'\n\nconst analyzeBlock = async (block: HydratedBlock, handlers: ChainAnalyzer[]): Promise<HydratedBlock> => {\n await Promise.all(handlers.map(async (handler) => {\n await handler.onBlock(block)\n }))\n return block\n}\n\nexport const analyzeChain = async (\n context: BlockContextRead,\n handlers: ChainAnalyzer[],\n /* the hash to start at */\n head: Hash | HydratedBlockWithHashMeta,\n /* a hash that we should stop at if we reach it */\n previousHead: Hash | null = null,\n /* max number of blocks to analyze (-1 for no limit) */\n maxDepth = -1n,\n): Promise<Payload[]> => {\n const { logger } = context\n logger?.log('analyzeChain.start', previousHead)\n return assertEx(await spanRootAsync('analyzeChain', async () => {\n let lastBlockNumber = -1\n let maxDepthLimit = maxDepth === -1n ? BigInt(Number.MAX_SAFE_INTEGER) : maxDepth\n let cursor: HydratedBlockWithHashMeta | null = typeof head === 'string' ? await hydrateBlock(context, head) : head\n // If the terminal block is the current head, we don't need to analyze it\n logger?.log('analyzeChain.cursor', cursor?.[0].block)\n if (previousHead !== null && cursor?.[0]._hash === previousHead) return []\n while (cursor && (maxDepthLimit > 0n)) {\n maxDepthLimit -= 1n\n await analyzeBlock(cursor, handlers)\n lastBlockNumber = cursor[0].block\n try {\n cursor = cursor[0].previous === null ? null : await hydrateBlock(context, cursor[0].previous)\n } catch (ex) {\n if (isError(ex)) {\n logger?.warn('Error in hydrateBlock', ex)\n }\n break\n }\n if (cursor?.[0]._hash === previousHead) break\n }\n if (previousHead === null && maxDepth === -1n && lastBlockNumber !== 0) {\n logger?.warn(`Expected root block number to be 0, but was ${lastBlockNumber} : ${previousHead}`)\n }\n logger?.log('analyzeChain.done', lastBlockNumber)\n return handlers.map((handler) => {\n return handler.result()\n })\n }, context), () => 'analyzeChain failed')\n}\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport { isDefined, toAddress } from '@ariestools/sdk'\nimport { trace, type Tracer } from '@opentelemetry/api'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n ChainAnalyzer,\n HydratedBlockWithHashMeta, SignedBigInt,\n} from '@xyo-network/xl1-sdk'\nimport {\n netBalancesForPayloads,\n parseSignedBigInt, toSignedBigInt,\n} from '@xyo-network/xl1-sdk'\n\nimport type { ChainSummaryBalances } from './ChainSummaryBalances.ts'\nimport { ChainSummaryBalancesSchema } from './ChainSummaryBalances.ts'\n\nconst bigintBalances = (balances: Partial<Record<Address, SignedBigInt>>) => {\n const result: Record<string, bigint> = {}\n for (const [address, balance] of Object.entries(balances)) {\n if (isDefined(balance)) {\n const propertyKey = String(toAddress(address))\n result[propertyKey] = parseSignedBigInt(balance)\n }\n }\n return result\n}\n\nexport class BalanceAnalyzer implements ChainAnalyzer {\n protected _tracer: Tracer | undefined\n private _addresses: Address[]\n private _balances: Record<string, bigint> = {}\n private _firstBlock?: Hash\n private _lastBlock?: Hash\n private _minBalances: bigint[]\n\n constructor(addresses: Address[] = [], minBalances: bigint[] = [], startingBalances?: ChainSummaryBalances) {\n this._addresses = addresses\n this._minBalances = minBalances\n this._balances = startingBalances ? bigintBalances(startingBalances.balances) : {}\n }\n\n protected get tracer() {\n if (this._tracer) return this._tracer\n this._tracer = trace.getTracer('BalanceAnalyzer')\n return this._tracer\n }\n\n onBlock([block, payloads]: HydratedBlockWithHashMeta): boolean {\n this._firstBlock = this._firstBlock ?? block._hash\n this._lastBlock = block._hash\n const netBalances = netBalancesForPayloads({ singletons: {} }, payloads)\n for (const [address, balance] of Object.entries(netBalances)) {\n const propertyKey = String(toAddress(address))\n this._balances[propertyKey] = (this._balances[propertyKey] ?? 0n) + balance\n }\n return this.shouldContinue()\n }\n\n result() {\n const balances: Record<string, SignedBigInt> = {}\n const positiveBalances = Object.entries(this._balances).filter(([, balance]) => balance > 0n)\n for (const [address, balance] of positiveBalances) {\n const propertyKey = String(toAddress(address))\n balances[propertyKey] = toSignedBigInt(balance)\n }\n const builder = new PayloadBuilder<ChainSummaryBalances>({ schema: ChainSummaryBalancesSchema })\n return builder.fields({\n firstBlock: this._firstBlock ?? null,\n lastBlock: this._lastBlock ?? null,\n balances,\n }).build()\n }\n\n shouldContinue() {\n return !this.allMinBalancesReached()\n }\n\n protected allMinBalancesReached() {\n if (this._minBalances.length === 0) return true\n for (let i = 0; i < this._addresses.length; i++) {\n const propertyKey = String(this._addresses[i])\n if ((this._balances[propertyKey] ?? 0n) < this._minBalances[i]) return false\n }\n return true\n }\n}\n", "import {\n type Address, type Hash, type Hex,\n} from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\nimport type { SignedBigInt } from '@xyo-network/xl1-sdk'\n\nexport const ChainSummaryBalancesSchema = asSchema('network.xyo.chain.summary.balances', true)\nexport type ChainSummaryBalancesSchema = typeof ChainSummaryBalancesSchema\n\nexport interface ChainSummaryBalancesFields {\n balances: Partial<Record<Address, SignedBigInt>>\n firstBlock: Hash | null\n hasMinBalance?: Record<Address, Hex>\n lastBlock: Hash | null\n}\n\nexport type ChainSummaryBalances = Payload<ChainSummaryBalancesFields, ChainSummaryBalancesSchema>\nexport const isChainSummaryBalances = isPayloadOfSchemaType<ChainSummaryBalances>(ChainSummaryBalancesSchema)\n", "import type { BaseParams, Promisable } from '@ariestools/sdk'\nimport { Base } from '@ariestools/sdk'\nimport type { Tracer } from '@opentelemetry/api'\nimport type { BlockViewer, SignedHydratedBlockWithHashMeta } from '@xyo-network/xl1-sdk'\nimport { asXL1BlockRange } from '@xyo-network/xl1-sdk'\n\nexport interface ChainFinalizerParams extends BaseParams {\n blockViewer: BlockViewer\n maxWindowSize?: number\n windowedFinalizedChain?: SignedHydratedBlockWithHashMeta[]\n}\n\nexport class ChainFinalizer<TParams extends ChainFinalizerParams = ChainFinalizerParams> extends Base<TParams> {\n protected _tracer: Tracer | undefined\n // the chainArchivist is assumed to be an archivist with already validated blocks in it along with all the transactions and payloads\n // it is also assumed that the sequence order of archivist is that newer blocks come after older blocks\n\n protected windowedFinalizedChain: SignedHydratedBlockWithHashMeta[]\n\n constructor(params: TParams) {\n super(params)\n this.windowedFinalizedChain = [...(params.windowedFinalizedChain ?? [])]\n }\n\n protected get blockViewer() {\n return this.params.blockViewer\n }\n\n protected get finalizedBlockNumber() {\n return this.windowedFinalizedChain?.at(-1)?.[0].block ?? -1\n }\n\n protected get maxWindowSize() {\n return this.params.maxWindowSize ?? 100\n }\n\n protected get windowRange() {\n return asXL1BlockRange([this.windowedFinalizedChain.at(0)?.[0].block ?? 0, this.finalizedBlockNumber])\n }\n\n finalizeChainFragment(chain: SignedHydratedBlockWithHashMeta[]): Promisable<void> {\n this.windowedFinalizedChain = [...this.windowedFinalizedChain, ...chain].slice(-this.maxWindowSize)\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport {\n isDefined, spanRootAsync, toAddress,\n} from '@ariestools/sdk'\nimport type {\n BaseContext, MempoolViewer, SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport {\n findBestUncle, findUncles, getWindowedChain, isTransactionBoundWitness,\n} from '@xyo-network/xl1-sdk'\n\nimport type {\n AdmissionAssessment, AdmissionMode, AdmissionShadowReport, ProducerEligibilityEvaluator,\n} from './admission.ts'\nimport { isDivergent } from './admission.ts'\nimport type { ChainFinalizerParams } from './ChainFinalizer.ts'\nimport { ChainFinalizer } from './ChainFinalizer.ts'\n\nexport interface ChainHeadSelectorParams extends ChainFinalizerParams {\n /**\n * How candidates are admitted. Defaults to `allowlist`, which is how the chain runs today.\n */\n admission?: AdmissionMode\n /**\n * List of allowed producer addresses, if undefined anyone can participate\n */\n allowedProducers?: Address[]\n /**\n * Back-off timeout (ms) after which a head is accepted even with fewer than\n * minCandidates uncle chains available.\n * When undefined, findBestUncle applies DEFAULT_BACKOFF_MS from the protocol SDK.\n */\n backoffMs?: number\n context: BaseContext\n /**\n * Computes whether a candidate's producer had standing. Absent means the question is never\n * asked, which is what keeps a node with no stake readers running exactly as it does today.\n */\n eligibility?: ProducerEligibilityEvaluator\n /**\n * Minimum epoch spacing (ms) between transaction-less heartbeat blocks this selector will\n * qualify \u2014 a defense against producers heartbeating faster than the network's intended pace.\n * Transaction-carrying candidates are exempt. Undefined disables the check.\n */\n heartbeatInterval?: number\n mempoolViewer: MempoolViewer\n /**\n * Minimum number of uncle candidates required before accepting one.\n * When undefined, findBestUncle applies DEFAULT_MIN_CANDIDATES from the protocol SDK.\n */\n minCandidates?: number\n /** Where to publish what the two gates concluded, in shadow posture. */\n publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>\n}\n\ninterface UncleSelectionHealth {\n lastWarnedAt: number\n unqualifiedSince?: number\n}\n\nexport class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorParams> {\n /**\n * How long uncle selection may go without a single qualifying candidate (while candidates are\n * present) before a warning is emitted; also the minimum interval between repeat warnings.\n */\n static readonly SilentUncleRejectionWarnAfterMs = 5000\n\n protected admission: AdmissionMode\n protected allowedProducers?: Address[]\n protected backoffMs?: number\n protected heartbeatInterval?: number\n protected minCandidates?: number\n private _timeSinceLastUncle = Date.now()\n\n constructor(params: ChainHeadSelectorParams) {\n super(params)\n this.admission = params.admission ?? 'allowlist'\n this.allowedProducers = params.allowedProducers\n this.backoffMs = params.backoffMs\n this.heartbeatInterval = params.heartbeatInterval\n this.minCandidates = params.minCandidates\n }\n\n protected get context() {\n return this.params.context\n }\n\n protected get mempoolViewer() {\n return this.params.mempoolViewer\n }\n\n async findBestHead(): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await spanRootAsync('findBestHead', async () => {\n const allProposedBlocks = await this.mempoolViewer.pendingBlocks()\n const allowed = allProposedBlocks.filter(pb => this.isAllowed(pb))\n const proposedBlocks = await this.admit(allProposedBlocks, allowed)\n\n // TODO: Validate proposed blocks\n this.windowedFinalizedChain = await getWindowedChain(this.context, this.blockViewer, this.maxWindowSize, this.windowedFinalizedChain)\n const pacedBlocks = this.filterPacedHeartbeatCandidates(proposedBlocks)\n const uncles = findUncles(this.context, this.windowedFinalizedChain, pacedBlocks)\n this.reportSilentUncleRejections(pacedBlocks, uncles.length)\n return findBestUncle(this.windowedFinalizedChain, uncles, { backoffMs: this.backoffMs, minCandidates: this.minCandidates }) ?? this.windowedFinalizedChain\n }, this.context)\n }\n\n /**\n * Applies the configured admission posture.\n *\n * In `shadow` the allow-list still decides \u2014 participation is computed and published beside it,\n * and changes nothing. That is the entire value of the posture: the network keeps behaving\n * exactly as it did while everyone gets to see what the new rule would have done.\n *\n * In `enforce` participation gates, but only when it reached a conclusion. A candidate whose\n * standing cannot be established is admitted, not rejected \u2014 otherwise a finalizer that lost\n * its stake reader would quietly stop accepting anyone's blocks and stall the chain.\n *\n * Assessments publish in both postures. The audit trail must not disappear at the moment\n * admission starts gating \u2014 enforce is when it matters most.\n */\n protected async admit(\n all: SignedHydratedBlockWithHashMeta[],\n allowed: SignedHydratedBlockWithHashMeta[],\n ): Promise<SignedHydratedBlockWithHashMeta[]> {\n if (this.admission === 'allowlist' || this.params.eligibility === undefined) return allowed\n const assessments = await this.assess(all)\n await this.publishShadow(assessments)\n if (this.admission === 'shadow') return allowed\n const ineligible = new Set(assessments\n .filter(assessment => assessment.eligibility.resolvable && assessment.eligibility.eligible !== true)\n .map(assessment => assessment.dataHash))\n return allowed.filter(candidate => !ineligible.has(candidate[0]._dataHash))\n }\n\n /**\n * Runs both gates over every candidate.\n *\n * An evaluator that throws yields an unresolvable assessment rather than an exception: this\n * sits on the head-selection path, and a flaky stake reader must never be able to stop the\n * chain from finalizing.\n */\n protected async assess(all: SignedHydratedBlockWithHashMeta[]): Promise<AdmissionAssessment[]> {\n const evaluate = this.params.eligibility\n if (evaluate === undefined) return []\n const evaluateSafely = async (candidate: SignedHydratedBlockWithHashMeta) => {\n try {\n return await evaluate(candidate)\n } catch {\n return { resolvable: false }\n }\n }\n return await Promise.all(all.map(async candidate => ({\n admittedByAllowList: this.isAllowed(candidate),\n block: candidate[0].block,\n dataHash: candidate[0]._dataHash,\n eligibility: await evaluateSafely(candidate),\n producer: candidate[0].addresses[0],\n })))\n }\n\n /**\n * Defense against unwanted heartbeat rates: a transaction-less (heartbeat) candidate qualifies\n * only when its signing epoch is at least heartbeatInterval after the current head's. Measured\n * on chain data, so every finalizer applies the same pace deterministically regardless of wall\n * clock. A producer heartbeating faster than the network's pace \u2014 misconfigured or hostile \u2014\n * cannot drive the chain's block rate: its candidates never qualify and age out of the pool,\n * while transaction-carrying candidates are exempt and finalize immediately.\n */\n protected filterPacedHeartbeatCandidates(proposedBlocks: SignedHydratedBlockWithHashMeta[]): SignedHydratedBlockWithHashMeta[] {\n const interval = this.heartbeatInterval\n if (interval === undefined || proposedBlocks.length === 0) return proposedBlocks\n const headEpoch = this.windowedFinalizedChain.at(-1)?.[0].$epoch\n if (!isDefined(headEpoch)) return proposedBlocks\n const paced = proposedBlocks.filter((candidate) => {\n if (candidate[1].some(payload => isTransactionBoundWitness(payload))) return true\n const candidateEpoch = candidate[0].$epoch\n // a candidate without an epoch cannot be paced here; shape validation owns that case\n if (!isDefined(candidateEpoch)) return true\n return candidateEpoch - headEpoch >= interval\n })\n if (paced.length < proposedBlocks.length) {\n this.context.logger?.debug(\n `findBestHead: paced out ${proposedBlocks.length - paced.length} heartbeat candidate(s) `\n + `younger than ${interval}ms since the head`,\n )\n }\n return paced\n }\n\n /** Whether the configured allow-list admits a candidate. An empty list admits everyone. */\n protected isAllowed(candidate: SignedHydratedBlockWithHashMeta): boolean {\n const allowedProducers = this.allowedProducers\n return isDefined(allowedProducers) && allowedProducers.length > 0\n ? allowedProducers.includes(toAddress(candidate[0].addresses[0]))\n : true\n }\n\n /** Publishes what the two gates concluded, swallowing failures. */\n protected async publishShadow(assessments: AdmissionAssessment[]): Promise<void> {\n const publish = this.params.publishAdmissionShadow\n // an empty round says nothing worth a write\n if (publish === undefined || assessments.length === 0) return\n try {\n await publish({\n assessments,\n divergent: assessments.filter(assessment => isDivergent(assessment)),\n head: this.windowedFinalizedChain[0]?.[0]?.block ?? 0,\n })\n } catch {\n // observing must never be able to stop the chain from finalizing\n }\n }\n\n /**\n * Surfaces the otherwise-silent case where candidates are continuously present but none\n * qualifies as an uncle \u2014 without this, the only signal of a stalled selector is an endless\n * \"No new blocks found N to N\" while rejected candidates cycle through the pool. Zero-qualify\n * moments are routine in healthy operation (a just-finalized candidate lingers until the pool\n * GC), so this warns only after candidates have been failing continuously for\n * SilentUncleRejectionWarnAfterMs \u2014 an idle (candidate-free) tick resets the clock \u2014 then\n * rate-limits to one warn per that interval. State lives in context.singletons because a\n * fresh ChainHeadSelector is constructed on every finalization tick.\n */\n private reportSilentUncleRejections(proposedBlocks: SignedHydratedBlockWithHashMeta[], uncleCount: number): void {\n const singletons = this.context.singletons\n const stateKey = 'ChainHeadSelector:uncleSelectionHealth'\n const now = Date.now()\n const state = (singletons[stateKey] ?? { lastWarnedAt: 0 }) as UncleSelectionHealth\n singletons[stateKey] = state\n if (uncleCount > 0 || proposedBlocks.length === 0) {\n state.unqualifiedSince = undefined\n return\n }\n state.unqualifiedSince ??= now\n if (now - state.unqualifiedSince < ChainHeadSelector.SilentUncleRejectionWarnAfterMs) return\n if (now - state.lastWarnedAt < ChainHeadSelector.SilentUncleRejectionWarnAfterMs) return\n state.lastWarnedAt = now\n this.context.logger?.warn(\n `findBestHead: candidates have failed uncle qualification continuously for ${now - state.unqualifiedSince}ms \u2014 `\n + `${proposedBlocks.length} pending candidate(s): `\n + proposedBlocks.map(b => `${b[0].block} [${b[0]._hash}]`).join(', '),\n )\n }\n}\n\n/*\n\nComparing two heads for which is better\n\nProducer Energy\n\n1. +1 Point for every block not produced by it in recent chain LOG(active producers * 100)\n2a. Energy Multiplied by - # of transactions in block is above normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n2b. Energy Divided by - # of transactions in block is below normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n3a. Energy Multiplied by - # of gas in block is above normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n3b. Energy Divided by - # of gas in block is below normal (last 1000 blocks) (+0.5 per std deviation) (max 2.5)\n\nOther Ideas\n\n1. Total diverse addresses in block (not quite incentivizing what we really want)\n2. Total transactions in block (more is better, encourages non-lethargic blocks)\n3. Sum total of transactions in block (higher value means more influential/better)\n4. Sum of gas of transactions in block (higher is better, prioritizes paying contributors)\n5. Exp of transactions in block (lower is better, prioritizes not aging out before inclusion)\n6. Recency of this producer's last produced block (encourages diversification in block producers)\n\n*/\n", "import type { Promisable } from '@ariestools/sdk'\nimport { isDefined, toAddress } from '@ariestools/sdk'\nimport { type ChainAnalyzer, type HydratedBlock } from '@xyo-network/xl1-sdk'\n\nimport type { AnalyzedProducer, ChainSummaryProducers } from './ChainSummaryProducers.ts'\nimport { ChainSummaryProducersSchema } from './ChainSummaryProducers.ts'\n\nexport class ChainProducersAnalyzer implements ChainAnalyzer<ChainSummaryProducers> {\n private endingBlock = 0\n private producers: Record<string, AnalyzedProducer> = {}\n private startingBlock = 0\n\n onBlock([block]: HydratedBlock): Promisable<boolean> {\n // avoid analyzing the same block twice\n if (block.block === this.endingBlock) return true\n\n // update the ending block\n this.endingBlock = block.block\n const blockProducerAddressRaw = block.addresses[0]\n\n if (blockProducerAddressRaw === undefined) return true\n\n const blockProducerAddress = toAddress(blockProducerAddressRaw)\n\n const producerKey = String(blockProducerAddress)\n const existingProducer: AnalyzedProducer | undefined = this.producers[producerKey]\n if (isDefined(existingProducer)) {\n existingProducer.rewardsEarned = (existingProducer.rewardsEarned ?? 0n) + 0n\n existingProducer.blocksProduced++\n } else {\n const newProducer: AnalyzedProducer = {\n address: blockProducerAddress, rewardsEarned: 0n, blocksProduced: 1,\n }\n this.producers[producerKey] = newProducer\n }\n\n return true\n }\n\n result(): ChainSummaryProducers {\n return {\n endingBlock: this.endingBlock,\n producers: this.producers,\n schema: ChainSummaryProducersSchema,\n startingBlock: this.startingBlock,\n }\n }\n\n shouldContinue(): boolean {\n return true\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\n\nexport const ChainSummaryProducersSchema = asSchema('network.xyo.chain.summary.producers', true)\nexport type ChainSummaryProducersSchema = typeof ChainSummaryProducersSchema\n\nexport interface AnalyzedProducer {\n address: Address\n blocksProduced: number\n rewardsEarned: bigint\n}\n\nexport interface ChainSummaryProducersFields {\n endingBlock: number\n producers: Record<string, AnalyzedProducer>\n startingBlock: number\n}\n\nexport type ChainSummaryProducers = Payload<ChainSummaryProducersFields, ChainSummaryProducersSchema>\nexport const isChainSummaryProducers = isPayloadOfSchemaType<ChainSummaryProducers>(ChainSummaryProducersSchema)\n", "import type { Promisable } from '@ariestools/sdk'\nimport { assertEx } from '@ariestools/sdk'\nimport {\n type ChainAnalyzer, type ChainStakeIntent, type HydratedBlock,\n type Intent,\n isChainStakeIntentWithStorageMeta,\n} from '@xyo-network/xl1-sdk'\n\nimport type { ChainSummaryStakeIntent } from './ChainSummaryStakeIntent.ts'\nimport { ChainSummaryStakeIntentSchema } from './ChainSummaryStakeIntent.ts'\n\nexport class ChainStakeIntentAnalyzer implements ChainAnalyzer<ChainSummaryStakeIntent> {\n private _endingBlock: number | undefined = undefined\n private _intent: Intent\n private _intentPayloads: ChainStakeIntent[] = []\n private _startingBlock: number | undefined = undefined\n\n constructor(intent: Intent) {\n this._intent = intent\n }\n\n onBlock([block, validatedPayloads]: HydratedBlock): Promisable<boolean> {\n this._startingBlock ??= block.block\n\n // Update the ending block\n this._endingBlock = block.block\n const intents = validatedPayloads.filter(isChainStakeIntentWithStorageMeta)\n const desiredIntents = intents.filter(intent => intent.intent === this._intent)\n this._intentPayloads.push(...desiredIntents)\n return true\n }\n\n result(): ChainSummaryStakeIntent {\n assertEx(this._startingBlock !== undefined, () => 'ChainStakeIntentAnalyzer: Invalid startingBlock')\n assertEx(this._endingBlock !== undefined, () => 'ChainStakeIntentAnalyzer: Invalid endingBlock')\n return {\n endingBlock: this._endingBlock!,\n intents: this._intentPayloads,\n schema: ChainSummaryStakeIntentSchema,\n startingBlock: this._startingBlock!,\n }\n }\n\n shouldContinue(): boolean {\n return true\n }\n}\n", "import type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\nimport type { ChainStakeIntent } from '@xyo-network/xl1-sdk'\n\nexport const ChainSummaryStakeIntentSchema = asSchema('network.xyo.chain.summary.staked.intent', true)\nexport type ChainSummaryStakeIntentSchema = typeof ChainSummaryStakeIntentSchema\n\ninterface ChainSummaryStakeIntentFields {\n endingBlock: number\n intents: ChainStakeIntent[]\n startingBlock: number\n}\n\nexport type ChainSummaryStakeIntent = Payload<ChainSummaryStakeIntentFields, ChainSummaryStakeIntentSchema>\nexport const isChainSummaryStakeIntent = isPayloadOfSchemaType<ChainSummaryStakeIntent>(ChainSummaryStakeIntentSchema)\n", "import {\n type Address, type Hash, type Hex,\n} from '@ariestools/sdk'\nimport type { Payload } from '@xyo-network/sdk'\nimport { asSchema, isPayloadOfSchemaType } from '@xyo-network/sdk'\nimport type { SignedBigInt } from '@xyo-network/xl1-sdk'\n\nexport const ChainSummaryTransfersSchema = asSchema('network.xyo.chain.summary.transfers', true)\nexport type ChainSummaryTransfersSchema = typeof ChainSummaryTransfersSchema\n\nexport interface ChainSummaryTransfersFields {\n firstBlock: Hash | null\n hasMinTransfer?: Record<Address, Hex>\n lastBlock: Hash | null\n transfers: Record<Address, Record<Address, SignedBigInt>>\n}\n\nexport type ChainSummaryTransfers = Payload<ChainSummaryTransfersFields, ChainSummaryTransfersSchema>\nexport const isChainSummaryTransfers = isPayloadOfSchemaType<ChainSummaryTransfers>(ChainSummaryTransfersSchema)\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport { isDefined, toAddress } from '@ariestools/sdk'\nimport { trace, type Tracer } from '@opentelemetry/api'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n ChainAnalyzer,\n HydratedBlockWithHashMeta, SignedBigInt,\n} from '@xyo-network/xl1-sdk'\nimport {\n netTransfersForPayloads,\n parseSignedBigInt, toSignedBigInt,\n} from '@xyo-network/xl1-sdk'\n\nimport type { ChainSummaryTransfers } from './ChainSummaryTransfers.ts'\nimport { ChainSummaryTransfersSchema } from './ChainSummaryTransfers.ts'\n\nconst bigintTransfers = (transfers: Record<Address, Record<Address, SignedBigInt>>) => {\n const result: Record<string, Record<string, bigint>> = {}\n for (const [from, toMap] of Object.entries(transfers)) {\n const fromKey = String(toAddress(from))\n for (const [to, balance] of Object.entries(toMap)) {\n const toKey = String(toAddress(to))\n if (isDefined(balance)) {\n const fromTransfers = result[fromKey] ?? {}\n result[fromKey] = fromTransfers\n fromTransfers[toKey] = parseSignedBigInt(balance)\n }\n }\n }\n return result\n}\n\nexport class TransferAnalyzer implements ChainAnalyzer {\n protected _tracer: Tracer | undefined\n private _firstBlock?: Hash\n private _lastBlock?: Hash\n private _transfers: Record<string, Record<string, bigint>> = {}\n\n constructor(startingTransfers?: ChainSummaryTransfers) {\n this._transfers = startingTransfers ? bigintTransfers(startingTransfers.transfers) : {}\n }\n\n protected get tracer() {\n if (this._tracer) return this._tracer\n this._tracer = trace.getTracer('TransferAnalyzer')\n return this._tracer\n }\n\n onBlock([block, payloads]: HydratedBlockWithHashMeta): boolean {\n this._firstBlock = this._firstBlock ?? block._hash\n this._lastBlock = block._hash\n const netTransfers = netTransfersForPayloads({ singletons: {} }, payloads)\n for (const [from, toMap] of Object.entries(netTransfers)) {\n const fromKey = String(toAddress(from))\n const fromTransfers = this._transfers[fromKey] ?? {}\n this._transfers[fromKey] = fromTransfers\n for (const [to, balance] of Object.entries(toMap)) {\n const toKey = String(toAddress(to))\n fromTransfers[toKey] = (fromTransfers[toKey] ?? 0n) + balance\n }\n }\n return this.shouldContinue()\n }\n\n result() {\n const transfers: Record<string, Record<string, SignedBigInt>> = {}\n for (const [from, toMap] of Object.entries(this._transfers)) {\n const fromKey = String(toAddress(from))\n const positiveTransfers = Object.entries(toMap).filter(([, balance]) => balance > 0n)\n for (const [to, balance] of positiveTransfers) {\n const fromTransfers = transfers[fromKey] ?? {}\n transfers[fromKey] = fromTransfers\n const toKey = String(toAddress(to))\n fromTransfers[toKey] = toSignedBigInt(balance)\n }\n }\n const builder = new PayloadBuilder<ChainSummaryTransfers>({ schema: ChainSummaryTransfersSchema })\n return builder.fields({\n firstBlock: this._firstBlock ?? null,\n lastBlock: this._lastBlock ?? null,\n transfers,\n }).build()\n }\n\n shouldContinue() {\n return true\n }\n}\n"],
5
+ "mappings": ";AAiBO,IAAM,iBAAiB,CAAC,aAAa,UAAU,SAAS;AAwCxD,IAAM,sCAAsC;AAc5C,SAAS,+BAA+B,OAAuD;AACpG,SAAO,OAAQ,OAA6D,YAAY;AAC1F;AAGO,SAAS,YAAY,YAA0C;AAEpE,MAAI,CAAC,WAAW,YAAY,WAAY,QAAO;AAC/C,SAAO,WAAW,yBAAyB,WAAW,YAAY,aAAa;AACjF;;;AC9EA;AAAA,EACE;AAAA,EAAU;AAAA,EAAS;AAAA,OACd;AAOP,SAAS,oBAAoB;AAE7B,IAAM,eAAe,OAAO,OAAsB,aAAsD;AACtG,QAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,YAAY;AAChD,UAAM,QAAQ,QAAQ,KAAK;AAAA,EAC7B,CAAC,CAAC;AACF,SAAO;AACT;AAEO,IAAM,eAAe,OAC1B,SACA,UAEA,MAEA,eAA4B,MAE5B,WAAW,CAAC,OACW;AACvB,QAAM,EAAE,OAAO,IAAI;AACnB,UAAQ,IAAI,sBAAsB,YAAY;AAC9C,SAAO,SAAS,MAAM,cAAc,gBAAgB,YAAY;AAC9D,QAAI,kBAAkB;AACtB,QAAI,gBAAgB,aAAa,CAAC,KAAK,OAAO,OAAO,gBAAgB,IAAI;AACzE,QAAI,SAA2C,OAAO,SAAS,WAAW,MAAM,aAAa,SAAS,IAAI,IAAI;AAE9G,YAAQ,IAAI,uBAAuB,SAAS,CAAC,EAAE,KAAK;AACpD,QAAI,iBAAiB,QAAQ,SAAS,CAAC,EAAE,UAAU,aAAc,QAAO,CAAC;AACzE,WAAO,UAAW,gBAAgB,IAAK;AACrC,uBAAiB;AACjB,YAAM,aAAa,QAAQ,QAAQ;AACnC,wBAAkB,OAAO,CAAC,EAAE;AAC5B,UAAI;AACF,iBAAS,OAAO,CAAC,EAAE,aAAa,OAAO,OAAO,MAAM,aAAa,SAAS,OAAO,CAAC,EAAE,QAAQ;AAAA,MAC9F,SAAS,IAAI;AACX,YAAI,QAAQ,EAAE,GAAG;AACf,kBAAQ,KAAK,yBAAyB,EAAE;AAAA,QAC1C;AACA;AAAA,MACF;AACA,UAAI,SAAS,CAAC,EAAE,UAAU,aAAc;AAAA,IAC1C;AACA,QAAI,iBAAiB,QAAQ,aAAa,CAAC,MAAM,oBAAoB,GAAG;AACtE,cAAQ,KAAK,+CAA+C,eAAe,MAAM,YAAY,EAAE;AAAA,IACjG;AACA,YAAQ,IAAI,qBAAqB,eAAe;AAChD,WAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,aAAO,QAAQ,OAAO;AAAA,IACxB,CAAC;AAAA,EACH,GAAG,OAAO,GAAG,MAAM,qBAAqB;AAC1C;;;AC5DA,SAAS,WAAW,iBAAiB;AACrC,SAAS,aAA0B;AACnC,SAAS,sBAAsB;AAK/B;AAAA,EACE;AAAA,EACA;AAAA,EAAmB;AAAA,OACd;;;ACPP,SAAS,UAAU,6BAA6B;AAGzC,IAAM,6BAA6B,SAAS,sCAAsC,IAAI;AAWtF,IAAM,yBAAyB,sBAA4C,0BAA0B;;;ADF5G,IAAM,iBAAiB,CAAC,aAAqD;AAC3E,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACzD,QAAI,UAAU,OAAO,GAAG;AACtB,YAAM,cAAc,OAAO,UAAU,OAAO,CAAC;AAC7C,aAAO,WAAW,IAAI,kBAAkB,OAAO;AAAA,IACjD;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,kBAAN,MAA+C;AAAA,EAC1C;AAAA,EACF;AAAA,EACA,YAAoC,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,YAAuB,CAAC,GAAG,cAAwB,CAAC,GAAG,kBAAyC;AAC1G,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,YAAY,mBAAmB,eAAe,iBAAiB,QAAQ,IAAI,CAAC;AAAA,EACnF;AAAA,EAEA,IAAc,SAAS;AACrB,QAAI,KAAK,QAAS,QAAO,KAAK;AAC9B,SAAK,UAAU,MAAM,UAAU,iBAAiB;AAChD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ,CAAC,OAAO,QAAQ,GAAuC;AAC7D,SAAK,cAAc,KAAK,eAAe,MAAM;AAC7C,SAAK,aAAa,MAAM;AACxB,UAAM,cAAc,uBAAuB,EAAE,YAAY,CAAC,EAAE,GAAG,QAAQ;AACvE,eAAW,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,WAAW,GAAG;AAC5D,YAAM,cAAc,OAAO,UAAU,OAAO,CAAC;AAC7C,WAAK,UAAU,WAAW,KAAK,KAAK,UAAU,WAAW,KAAK,MAAM;AAAA,IACtE;AACA,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,SAAS;AACP,UAAM,WAAyC,CAAC;AAChD,UAAM,mBAAmB,OAAO,QAAQ,KAAK,SAAS,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,MAAM,UAAU,EAAE;AAC5F,eAAW,CAAC,SAAS,OAAO,KAAK,kBAAkB;AACjD,YAAM,cAAc,OAAO,UAAU,OAAO,CAAC;AAC7C,eAAS,WAAW,IAAI,eAAe,OAAO;AAAA,IAChD;AACA,UAAM,UAAU,IAAI,eAAqC,EAAE,QAAQ,2BAA2B,CAAC;AAC/F,WAAO,QAAQ,OAAO;AAAA,MACpB,YAAY,KAAK,eAAe;AAAA,MAChC,WAAW,KAAK,cAAc;AAAA,MAC9B;AAAA,IACF,CAAC,EAAE,MAAM;AAAA,EACX;AAAA,EAEA,iBAAiB;AACf,WAAO,CAAC,KAAK,sBAAsB;AAAA,EACrC;AAAA,EAEU,wBAAwB;AAChC,QAAI,KAAK,aAAa,WAAW,EAAG,QAAO;AAC3C,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,YAAM,cAAc,OAAO,KAAK,WAAW,CAAC,CAAC;AAC7C,WAAK,KAAK,UAAU,WAAW,KAAK,MAAM,KAAK,aAAa,CAAC,EAAG,QAAO;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AACF;;;AEpFA,SAAS,YAAY;AAGrB,SAAS,uBAAuB;AAQzB,IAAM,iBAAN,cAA0F,KAAc;AAAA,EACnG;AAAA;AAAA;AAAA,EAIA;AAAA,EAEV,YAAY,QAAiB;AAC3B,UAAM,MAAM;AACZ,SAAK,yBAAyB,CAAC,GAAI,OAAO,0BAA0B,CAAC,CAAE;AAAA,EACzE;AAAA,EAEA,IAAc,cAAc;AAC1B,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAc,uBAAuB;AACnC,WAAO,KAAK,wBAAwB,GAAG,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC3D;AAAA,EAEA,IAAc,gBAAgB;AAC5B,WAAO,KAAK,OAAO,iBAAiB;AAAA,EACtC;AAAA,EAEA,IAAc,cAAc;AAC1B,WAAO,gBAAgB,CAAC,KAAK,uBAAuB,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,oBAAoB,CAAC;AAAA,EACvG;AAAA,EAEA,sBAAsB,OAA4D;AAChF,SAAK,yBAAyB,CAAC,GAAG,KAAK,wBAAwB,GAAG,KAAK,EAAE,MAAM,CAAC,KAAK,aAAa;AAAA,EACpG;AACF;;;AC1CA;AAAA,EACE,aAAAA;AAAA,EAAW,iBAAAC;AAAA,EAAe,aAAAC;AAAA,OACrB;AAIP;AAAA,EACE;AAAA,EAAe;AAAA,EAAY;AAAA,EAAkB;AAAA,OACxC;AAmDA,IAAM,oBAAN,MAAM,2BAA0B,eAAwC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7E,OAAgB,kCAAkC;AAAA,EAExC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACF,sBAAsB,KAAK,IAAI;AAAA,EAEvC,YAAY,QAAiC;AAC3C,UAAM,MAAM;AACZ,SAAK,YAAY,OAAO,aAAa;AACrC,SAAK,mBAAmB,OAAO;AAC/B,SAAK,YAAY,OAAO;AACxB,SAAK,oBAAoB,OAAO;AAChC,SAAK,gBAAgB,OAAO;AAAA,EAC9B;AAAA,EAEA,IAAc,UAAU;AACtB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAc,gBAAgB;AAC5B,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,MAAM,eAA2D;AAC/D,WAAO,MAAMC,eAAc,gBAAgB,YAAY;AACrD,YAAM,oBAAoB,MAAM,KAAK,cAAc,cAAc;AACjE,YAAM,UAAU,kBAAkB,OAAO,QAAM,KAAK,UAAU,EAAE,CAAC;AACjE,YAAM,iBAAiB,MAAM,KAAK,MAAM,mBAAmB,OAAO;AAGlE,WAAK,yBAAyB,MAAM,iBAAiB,KAAK,SAAS,KAAK,aAAa,KAAK,eAAe,KAAK,sBAAsB;AACpI,YAAM,cAAc,KAAK,+BAA+B,cAAc;AACtE,YAAM,SAAS,WAAW,KAAK,SAAS,KAAK,wBAAwB,WAAW;AAChF,WAAK,4BAA4B,aAAa,OAAO,MAAM;AAC3D,aAAO,cAAc,KAAK,wBAAwB,QAAQ,EAAE,WAAW,KAAK,WAAW,eAAe,KAAK,cAAc,CAAC,KAAK,KAAK;AAAA,IACtI,GAAG,KAAK,OAAO;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAgB,MACd,KACA,SAC4C;AAC5C,QAAI,KAAK,cAAc,eAAe,KAAK,OAAO,gBAAgB,OAAW,QAAO;AACpF,UAAM,cAAc,MAAM,KAAK,OAAO,GAAG;AACzC,UAAM,KAAK,cAAc,WAAW;AACpC,QAAI,KAAK,cAAc,SAAU,QAAO;AACxC,UAAM,aAAa,IAAI,IAAI,YACxB,OAAO,gBAAc,WAAW,YAAY,cAAc,WAAW,YAAY,aAAa,IAAI,EAClG,IAAI,gBAAc,WAAW,QAAQ,CAAC;AACzC,WAAO,QAAQ,OAAO,eAAa,CAAC,WAAW,IAAI,UAAU,CAAC,EAAE,SAAS,CAAC;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAgB,OAAO,KAAwE;AAC7F,UAAM,WAAW,KAAK,OAAO;AAC7B,QAAI,aAAa,OAAW,QAAO,CAAC;AACpC,UAAM,iBAAiB,OAAO,cAA+C;AAC3E,UAAI;AACF,eAAO,MAAM,SAAS,SAAS;AAAA,MACjC,QAAQ;AACN,eAAO,EAAE,YAAY,MAAM;AAAA,MAC7B;AAAA,IACF;AACA,WAAO,MAAM,QAAQ,IAAI,IAAI,IAAI,OAAM,eAAc;AAAA,MACnD,qBAAqB,KAAK,UAAU,SAAS;AAAA,MAC7C,OAAO,UAAU,CAAC,EAAE;AAAA,MACpB,UAAU,UAAU,CAAC,EAAE;AAAA,MACvB,aAAa,MAAM,eAAe,SAAS;AAAA,MAC3C,UAAU,UAAU,CAAC,EAAE,UAAU,CAAC;AAAA,IACpC,EAAE,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,+BAA+B,gBAAsF;AAC7H,UAAM,WAAW,KAAK;AACtB,QAAI,aAAa,UAAa,eAAe,WAAW,EAAG,QAAO;AAClE,UAAM,YAAY,KAAK,uBAAuB,GAAG,EAAE,IAAI,CAAC,EAAE;AAC1D,QAAI,CAACC,WAAU,SAAS,EAAG,QAAO;AAClC,UAAM,QAAQ,eAAe,OAAO,CAAC,cAAc;AACjD,UAAI,UAAU,CAAC,EAAE,KAAK,aAAW,0BAA0B,OAAO,CAAC,EAAG,QAAO;AAC7E,YAAM,iBAAiB,UAAU,CAAC,EAAE;AAEpC,UAAI,CAACA,WAAU,cAAc,EAAG,QAAO;AACvC,aAAO,iBAAiB,aAAa;AAAA,IACvC,CAAC;AACD,QAAI,MAAM,SAAS,eAAe,QAAQ;AACxC,WAAK,QAAQ,QAAQ;AAAA,QACnB,2BAA2B,eAAe,SAAS,MAAM,MAAM,wCAC7C,QAAQ;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGU,UAAU,WAAqD;AACvE,UAAM,mBAAmB,KAAK;AAC9B,WAAOA,WAAU,gBAAgB,KAAK,iBAAiB,SAAS,IAC5D,iBAAiB,SAASC,WAAU,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,IAC9D;AAAA,EACN;AAAA;AAAA,EAGA,MAAgB,cAAc,aAAmD;AAC/E,UAAM,UAAU,KAAK,OAAO;AAE5B,QAAI,YAAY,UAAa,YAAY,WAAW,EAAG;AACvD,QAAI;AACF,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA,WAAW,YAAY,OAAO,gBAAc,YAAY,UAAU,CAAC;AAAA,QACnE,MAAM,KAAK,uBAAuB,CAAC,IAAI,CAAC,GAAG,SAAS;AAAA,MACtD,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,4BAA4B,gBAAmD,YAA0B;AAC/G,UAAM,aAAa,KAAK,QAAQ;AAChC,UAAM,WAAW;AACjB,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,QAAS,WAAW,QAAQ,KAAK,EAAE,cAAc,EAAE;AACzD,eAAW,QAAQ,IAAI;AACvB,QAAI,aAAa,KAAK,eAAe,WAAW,GAAG;AACjD,YAAM,mBAAmB;AACzB;AAAA,IACF;AACA,UAAM,qBAAqB;AAC3B,QAAI,MAAM,MAAM,mBAAmB,mBAAkB,gCAAiC;AACtF,QAAI,MAAM,MAAM,eAAe,mBAAkB,gCAAiC;AAClF,UAAM,eAAe;AACrB,SAAK,QAAQ,QAAQ;AAAA,MACnB,6EAA6E,MAAM,MAAM,gBAAgB,aACpG,eAAe,MAAM,4BACxB,eAAe,IAAI,OAAK,GAAG,EAAE,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,IAAI;AAAA,IACtE;AAAA,EACF;AACF;;;AClPA,SAAS,aAAAC,YAAW,aAAAC,kBAAiB;;;ACCrC,SAAS,YAAAC,WAAU,yBAAAC,8BAA6B;AAEzC,IAAM,8BAA8BD,UAAS,uCAAuC,IAAI;AAgBxF,IAAM,0BAA0BC,uBAA6C,2BAA2B;;;ADbxG,IAAM,yBAAN,MAA6E;AAAA,EAC1E,cAAc;AAAA,EACd,YAA8C,CAAC;AAAA,EAC/C,gBAAgB;AAAA,EAExB,QAAQ,CAAC,KAAK,GAAuC;AAEnD,QAAI,MAAM,UAAU,KAAK,YAAa,QAAO;AAG7C,SAAK,cAAc,MAAM;AACzB,UAAM,0BAA0B,MAAM,UAAU,CAAC;AAEjD,QAAI,4BAA4B,OAAW,QAAO;AAElD,UAAM,uBAAuBC,WAAU,uBAAuB;AAE9D,UAAM,cAAc,OAAO,oBAAoB;AAC/C,UAAM,mBAAiD,KAAK,UAAU,WAAW;AACjF,QAAIC,WAAU,gBAAgB,GAAG;AAC/B,uBAAiB,iBAAiB,iBAAiB,iBAAiB,MAAM;AAC1E,uBAAiB;AAAA,IACnB,OAAO;AACL,YAAM,cAAgC;AAAA,QACpC,SAAS;AAAA,QAAsB,eAAe;AAAA,QAAI,gBAAgB;AAAA,MACpE;AACA,WAAK,UAAU,WAAW,IAAI;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,SAAgC;AAC9B,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,QAAQ;AAAA,MACR,eAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,iBAA0B;AACxB,WAAO;AAAA,EACT;AACF;;;AElDA,SAAS,YAAAC,iBAAgB;AACzB;AAAA,EAGE;AAAA,OACK;;;ACLP,SAAS,YAAAC,WAAU,yBAAAC,8BAA6B;AAGzC,IAAM,gCAAgCD,UAAS,2CAA2C,IAAI;AAU9F,IAAM,4BAA4BC,uBAA+C,6BAA6B;;;ADH9G,IAAM,2BAAN,MAAiF;AAAA,EAC9E,eAAmC;AAAA,EACnC;AAAA,EACA,kBAAsC,CAAC;AAAA,EACvC,iBAAqC;AAAA,EAE7C,YAAY,QAAgB;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAQ,CAAC,OAAO,iBAAiB,GAAuC;AACtE,SAAK,mBAAmB,MAAM;AAG9B,SAAK,eAAe,MAAM;AAC1B,UAAM,UAAU,kBAAkB,OAAO,iCAAiC;AAC1E,UAAM,iBAAiB,QAAQ,OAAO,YAAU,OAAO,WAAW,KAAK,OAAO;AAC9E,SAAK,gBAAgB,KAAK,GAAG,cAAc;AAC3C,WAAO;AAAA,EACT;AAAA,EAEA,SAAkC;AAChC,IAAAC,UAAS,KAAK,mBAAmB,QAAW,MAAM,iDAAiD;AACnG,IAAAA,UAAS,KAAK,iBAAiB,QAAW,MAAM,+CAA+C;AAC/F,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,SAAS,KAAK;AAAA,MACd,QAAQ;AAAA,MACR,eAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,iBAA0B;AACxB,WAAO;AAAA,EACT;AACF;;;AE1CA,SAAS,YAAAC,WAAU,yBAAAC,8BAA6B;AAGzC,IAAM,8BAA8BD,UAAS,uCAAuC,IAAI;AAWxF,IAAM,0BAA0BC,uBAA6C,2BAA2B;;;ACjB/G,SAAS,aAAAC,YAAW,aAAAC,kBAAiB;AACrC,SAAS,SAAAC,cAA0B;AACnC,SAAS,kBAAAC,uBAAsB;AAK/B;AAAA,EACE;AAAA,EACA,qBAAAC;AAAA,EAAmB,kBAAAC;AAAA,OACd;AAKP,IAAM,kBAAkB,CAAC,cAA8D;AACrF,QAAM,SAAiD,CAAC;AACxD,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,UAAM,UAAU,OAAOC,WAAU,IAAI,CAAC;AACtC,eAAW,CAAC,IAAI,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,YAAM,QAAQ,OAAOA,WAAU,EAAE,CAAC;AAClC,UAAIC,WAAU,OAAO,GAAG;AACtB,cAAM,gBAAgB,OAAO,OAAO,KAAK,CAAC;AAC1C,eAAO,OAAO,IAAI;AAClB,sBAAc,KAAK,IAAIC,mBAAkB,OAAO;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,mBAAN,MAAgD;AAAA,EAC3C;AAAA,EACF;AAAA,EACA;AAAA,EACA,aAAqD,CAAC;AAAA,EAE9D,YAAY,mBAA2C;AACrD,SAAK,aAAa,oBAAoB,gBAAgB,kBAAkB,SAAS,IAAI,CAAC;AAAA,EACxF;AAAA,EAEA,IAAc,SAAS;AACrB,QAAI,KAAK,QAAS,QAAO,KAAK;AAC9B,SAAK,UAAUC,OAAM,UAAU,kBAAkB;AACjD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ,CAAC,OAAO,QAAQ,GAAuC;AAC7D,SAAK,cAAc,KAAK,eAAe,MAAM;AAC7C,SAAK,aAAa,MAAM;AACxB,UAAM,eAAe,wBAAwB,EAAE,YAAY,CAAC,EAAE,GAAG,QAAQ;AACzE,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACxD,YAAM,UAAU,OAAOH,WAAU,IAAI,CAAC;AACtC,YAAM,gBAAgB,KAAK,WAAW,OAAO,KAAK,CAAC;AACnD,WAAK,WAAW,OAAO,IAAI;AAC3B,iBAAW,CAAC,IAAI,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,cAAM,QAAQ,OAAOA,WAAU,EAAE,CAAC;AAClC,sBAAc,KAAK,KAAK,cAAc,KAAK,KAAK,MAAM;AAAA,MACxD;AAAA,IACF;AACA,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,SAAS;AACP,UAAM,YAA0D,CAAC;AACjE,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,UAAU,GAAG;AAC3D,YAAM,UAAU,OAAOA,WAAU,IAAI,CAAC;AACtC,YAAM,oBAAoB,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,MAAM,UAAU,EAAE;AACpF,iBAAW,CAAC,IAAI,OAAO,KAAK,mBAAmB;AAC7C,cAAM,gBAAgB,UAAU,OAAO,KAAK,CAAC;AAC7C,kBAAU,OAAO,IAAI;AACrB,cAAM,QAAQ,OAAOA,WAAU,EAAE,CAAC;AAClC,sBAAc,KAAK,IAAII,gBAAe,OAAO;AAAA,MAC/C;AAAA,IACF;AACA,UAAM,UAAU,IAAIC,gBAAsC,EAAE,QAAQ,4BAA4B,CAAC;AACjG,WAAO,QAAQ,OAAO;AAAA,MACpB,YAAY,KAAK,eAAe;AAAA,MAChC,WAAW,KAAK,cAAc;AAAA,MAC9B;AAAA,IACF,CAAC,EAAE,MAAM;AAAA,EACX;AAAA,EAEA,iBAAiB;AACf,WAAO;AAAA,EACT;AACF;",
6
6
  "names": ["isDefined", "spanRootAsync", "toAddress", "spanRootAsync", "isDefined", "toAddress", "isDefined", "toAddress", "asSchema", "isPayloadOfSchemaType", "toAddress", "isDefined", "assertEx", "asSchema", "isPayloadOfSchemaType", "assertEx", "asSchema", "isPayloadOfSchemaType", "isDefined", "toAddress", "trace", "PayloadBuilder", "parseSignedBigInt", "toSignedBigInt", "toAddress", "isDefined", "parseSignedBigInt", "trace", "toSignedBigInt", "PayloadBuilder"]
7
7
  }
@@ -24,6 +24,12 @@ export interface ChainHeadSelectorParams extends ChainFinalizerParams {
24
24
  * asked, which is what keeps a node with no stake readers running exactly as it does today.
25
25
  */
26
26
  eligibility?: ProducerEligibilityEvaluator;
27
+ /**
28
+ * Minimum epoch spacing (ms) between transaction-less heartbeat blocks this selector will
29
+ * qualify — a defense against producers heartbeating faster than the network's intended pace.
30
+ * Transaction-carrying candidates are exempt. Undefined disables the check.
31
+ */
32
+ heartbeatInterval?: number;
27
33
  mempoolViewer: MempoolViewer;
28
34
  /**
29
35
  * Minimum number of uncle candidates required before accepting one.
@@ -42,6 +48,7 @@ export declare class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorP
42
48
  protected admission: AdmissionMode;
43
49
  protected allowedProducers?: Address[];
44
50
  protected backoffMs?: number;
51
+ protected heartbeatInterval?: number;
45
52
  protected minCandidates?: number;
46
53
  private _timeSinceLastUncle;
47
54
  constructor(params: ChainHeadSelectorParams);
@@ -78,6 +85,15 @@ export declare class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorP
78
85
  * chain from finalizing.
79
86
  */
80
87
  protected assess(all: SignedHydratedBlockWithHashMeta[]): Promise<AdmissionAssessment[]>;
88
+ /**
89
+ * Defense against unwanted heartbeat rates: a transaction-less (heartbeat) candidate qualifies
90
+ * only when its signing epoch is at least heartbeatInterval after the current head's. Measured
91
+ * on chain data, so every finalizer applies the same pace deterministically regardless of wall
92
+ * clock. A producer heartbeating faster than the network's pace — misconfigured or hostile —
93
+ * cannot drive the chain's block rate: its candidates never qualify and age out of the pool,
94
+ * while transaction-carrying candidates are exempt and finalize immediately.
95
+ */
96
+ protected filterPacedHeartbeatCandidates(proposedBlocks: SignedHydratedBlockWithHashMeta[]): SignedHydratedBlockWithHashMeta[];
81
97
  /** Whether the configured allow-list admits a candidate. An empty list admits everyone. */
82
98
  protected isAllowed(candidate: SignedHydratedBlockWithHashMeta): boolean;
83
99
  /** Publishes what the two gates concluded, swallowing failures. */
@@ -1 +1 @@
1
- {"version":3,"file":"ChainHeadSelector.d.ts","sourceRoot":"","sources":["../../../../src/modules/analyze/ChainHeadSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,+BAA+B,EAC5D,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACxF,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,aAAa,EAAE,aAAa,CAAA;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAOD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5E;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,+BAA+B,QAAO;IAEtD,SAAS,CAAC,SAAS,EAAE,aAAa,CAAA;IAClC,SAAS,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IACtC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,CAAC,mBAAmB,CAAa;gBAE5B,MAAM,EAAE,uBAAuB;IAQ3C,SAAS,KAAK,OAAO;;;;;;;MAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAEK,YAAY,IAAI,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAchE;;;;;;;;;;;;;OAaG;cACa,KAAK,CACnB,GAAG,EAAE,+BAA+B,EAAE,EACtC,OAAO,EAAE,+BAA+B,EAAE,GACzC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAW7C;;;;;;OAMG;cACa,MAAM,CAAC,GAAG,EAAE,+BAA+B,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAmB9F,2FAA2F;IAC3F,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,+BAA+B,GAAG,OAAO;IAOxE,mEAAmE;cACnD,aAAa,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;CAoBpC"}
1
+ {"version":3,"file":"ChainHeadSelector.d.ts","sourceRoot":"","sources":["../../../../src/modules/analyze/ChainHeadSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,+BAA+B,EAC5D,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACxF,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,aAAa,CAAA;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAOD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5E;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,+BAA+B,QAAO;IAEtD,SAAS,CAAC,SAAS,EAAE,aAAa,CAAA;IAClC,SAAS,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IACtC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IACpC,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,CAAC,mBAAmB,CAAa;gBAE5B,MAAM,EAAE,uBAAuB;IAS3C,SAAS,KAAK,OAAO;;;;;;;MAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAEK,YAAY,IAAI,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAehE;;;;;;;;;;;;;OAaG;cACa,KAAK,CACnB,GAAG,EAAE,+BAA+B,EAAE,EACtC,OAAO,EAAE,+BAA+B,EAAE,GACzC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAW7C;;;;;;OAMG;cACa,MAAM,CAAC,GAAG,EAAE,+BAA+B,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAmB9F;;;;;;;OAOG;IACH,SAAS,CAAC,8BAA8B,CAAC,cAAc,EAAE,+BAA+B,EAAE,GAAG,+BAA+B,EAAE;IAqB9H,2FAA2F;IAC3F,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,+BAA+B,GAAG,OAAO;IAOxE,mEAAmE;cACnD,aAAa,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;CAoBpC"}
@@ -14,6 +14,11 @@ interface ProcessPendingBlocksParams {
14
14
  /** Computes producer standing, for the shadow and enforce postures. */
15
15
  eligibility?: ProducerEligibilityEvaluator;
16
16
  finalizationRunner: FinalizationRunner;
17
+ /**
18
+ * Minimum epoch spacing (ms) between transaction-less heartbeat blocks the head selector will
19
+ * qualify; transaction-carrying candidates are exempt. Undefined disables the pace check.
20
+ */
21
+ heartbeatInterval?: number;
17
22
  logger?: Logger;
18
23
  mempoolViewer: MempoolViewer;
19
24
  minCandidates?: number;
@@ -25,7 +30,7 @@ interface ProcessPendingBlocksParams {
25
30
  /** Where to publish what both admission gates concluded, in shadow posture. */
26
31
  publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>;
27
32
  }
28
- export declare function processPendingBlocks({ blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, minCandidates, deadLetterQueueRunner, observer, admission, eligibility, publishAdmissionShadow, }: ProcessPendingBlocksParams): Promise<[{
33
+ export declare function processPendingBlocks({ blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, heartbeatInterval, minCandidates, deadLetterQueueRunner, observer, admission, eligibility, publishAdmissionShadow, }: ProcessPendingBlocksParams): Promise<[{
29
34
  schema: "network.xyo.boundwitness" & {
30
35
  readonly __schema: true;
31
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"processPendingBlocks.d.ts","sourceRoot":"","sources":["../../../../../src/modules/services/implementation/processPendingBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EACV,WAAW,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAA6B,aAAa,EACrI,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACnE,MAAM,UAAU,CAAA;AAKjB,UAAU,0BAA0B;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,uEAAuE;IACvE,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAgCD,wBAAsB,oBAAoB,CAAC,EACzC,qBAAqB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EACnK,SAAS,EAAE,WAAW,EAAE,sBAAsB,GAC/C,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA2E5B"}
1
+ {"version":3,"file":"processPendingBlocks.d.ts","sourceRoot":"","sources":["../../../../../src/modules/services/implementation/processPendingBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EACV,WAAW,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAA6B,aAAa,EACrI,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACnE,MAAM,UAAU,CAAA;AAKjB,UAAU,0BAA0B;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,uEAAuE;IACvE,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,kBAAkB,EAAE,kBAAkB,CAAA;IACtC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAgCD,wBAAsB,oBAAoB,CAAC,EACzC,qBAAqB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EACtL,SAAS,EAAE,WAAW,EAAE,sBAAsB,GAC/C,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA4E5B"}
@@ -13,6 +13,13 @@ interface ExcludedTransactionEntry {
13
13
  * The default block size for a block
14
14
  */
15
15
  export declare const DEFAULT_BLOCK_SIZE = 10;
16
+ /**
17
+ * Default minimum age (ms) of the head before a producer emits a transaction-less heartbeat
18
+ * block. Five minutes keeps a quiet chain visibly alive without accumulating meaningful storage
19
+ * or block-reward drift. Finalizers use the same default as the floor for how fast they will
20
+ * finalize heartbeat blocks.
21
+ */
22
+ export declare const DEFAULT_HEARTBEAT_INTERVAL = 300000;
16
23
  /**
17
24
  * The amount of time for which a producer will restake their intent
18
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleBlockRunner.d.ts","sourceRoot":"","sources":["../../../../../../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAAQ,UAAU,EAC1B,MAAM,iBAAiB,CAAA;AAKxB,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAAE,YAAY,EAChC,MAAM,kBAAkB,CAAA;AAKzB,OAAO,KAAK,EACV,oBAAoB,EAAuB,iBAAiB,EACxC,iBAAiB,EAAE,WAAW,EAAE,qBAAqB,EACzE,gBAAgB,EAAE,uBAAuB,EACzC,qBAAqB,EACrB,kBAAkB,EAClB,oCAAoC,EAAgC,aAAa,EACjF,mCAAmC,EACnC,+BAA+B,EAClB,cAAc,EAAE,QAAQ,EACtC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,yBAAyB,EAQ1B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAKlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAA;AAK3E,uFAAuF;AACvF,UAAU,wBAAwB;IAChC,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;GAEG;AACH,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,iCAAiC,MAAM,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,4FAA4F;IAC5F,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,6BAA6B,CAAC,EAAE,iBAAiB,CAAA;IACjD,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,0BAA0B,CAAC,EAAE,oCAAoC,CAAA;CAClE;AAED,qBACa,iBAAkB,SAAQ,yBAAyB,CAAC,uBAAuB,CAAE,YAAW,WAAW;IAC9G;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,sBAAsB,QAAO;IAE7C,MAAM,CAAC,QAAQ,CAAC,eAAe,uCAAuC;IACtE,MAAM,CAAC,QAAQ,CAAC,cAAc,gBAAqB;IACnD,MAAM,CAAC,QAAQ,CAAC,YAAY,yIAO3B;IAED,MAAM,CAAC,QAAQ,CAAC,QAAQ,kBAAuB;IAE/C,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAG,MAAM,CAAS;IAEzC,OAAO,gBAAmC;IAE1C,SAAS,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,CAAA;IAClD,SAAS,CAAC,sBAAsB,CAAC,EAAE,qBAAqB,CAAA;IAMxD,SAAS,CAAC,0BAA0B,uEAA4C;IAChF,SAAS,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAC1C,SAAS,CAAC,8BAA8B,CAAC,EAAE,iBAAiB,CAAA;IAE5D,OAAO,CAAC,QAAQ,CAAC,CAAiB;IAClC,OAAO,CAAC,qBAAqB,CAAC,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAC9C,OAAO,CAAC,sBAAsB,CAAC,CAAuB;IACtD,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAC9C,OAAO,CAAC,mBAAmB,CAAC,CAAoB;IAChD,OAAO,CAAC,oBAAoB,CAAI;IAChC,0FAA0F;IAC1F,OAAO,CAAC,oBAAoB,CAAC,CAA+C;IAC5E,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,eAAe,CAAC,CAAgB;IAExC;;OAEG;IACH,MAAM,KAAK,gBAAgB,IAAI,MAAM,CAEpC;IAED;;;OAGG;IACH,MAAM,KAAK,qBAAqB,IAAI,MAAM,CAEzC;IAED;;;OAGG;IACH,MAAM,KAAK,mBAAmB,IAAI,MAAM,CAEvC;IAED,SAAS,KAAK,OAAO,oBAEpB;IAED,SAAS,KAAK,oBAAoB,yBAEjC;IAED,SAAS,KAAK,OAAO;;;;MAEpB;IAED,SAAS,KAAK,iBAAiB,sBAE9B;IAED,SAAS,KAAK,qBAAqB,0BAElC;IAED,SAAS,KAAK,kBAAkB,uBAE/B;IAED,SAAS,KAAK,iBAAiB,WAE9B;IAED,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,cAAc;;;;MAE3B;IAMD,SAAS,KAAK,6BAA6B,mPAE1C;IAED,SAAS,KAAK,aAAa,IAAI,OAAO,CAErC;IAMD,SAAS,KAAK,cAAc,IAAI,cAAc,CAE7C;IAMc,aAAa;IAwBtB,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,+BAA+B,GAAG,SAAS,CAAC;IAgBjG,gBAAgB,CAAC,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,+BAA+B,CAAC;IAClH,gBAAgB,CAAC,IAAI,EAAE,mCAAmC,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,+BAA+B,GAAG,SAAS,CAAC;cAOtH,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAiB3E;;;;OAIG;IACH,SAAS,CAAC,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC,iBAAiB,CAAC,GAAG,UAAU,CAAC,gBAAgB,GAAG,SAAS,CAAC;cAsBnG,qBAAqB,CAAC,IAAI,EAAE,YAAY,CAAC,iBAAiB,CAAC,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,KAAK,UAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2DtH,OAAO,CAAC,kBAAkB;YASZ,mBAAmB;IAyBjC;;;;;;;;OAQG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;YASd,cAAc;YAsDd,mBAAmB;IAUjC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,4BAA4B;IAMpC;;;;;;;;;;;;;OAaG;YACW,wBAAwB;YAOxB,oBAAoB;YAkBpB,4BAA4B;IAiC1C;;;;;;;;;;;;OAYG;YACW,iBAAiB;YASjB,yBAAyB;CAoExC"}
1
+ {"version":3,"file":"SimpleBlockRunner.d.ts","sourceRoot":"","sources":["../../../../../../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts"],"names":[],"mappings":"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"}
@@ -168,6 +168,7 @@ async function processPendingBlocks({
168
168
  finalizationRunner,
169
169
  allowedProducers,
170
170
  backoffMs,
171
+ heartbeatInterval,
171
172
  minCandidates,
172
173
  deadLetterQueueRunner,
173
174
  observer,
@@ -185,6 +186,7 @@ async function processPendingBlocks({
185
186
  windowedFinalizedChain: [currentBlock],
186
187
  allowedProducers,
187
188
  backoffMs,
189
+ heartbeatInterval,
188
190
  minCandidates,
189
191
  admission,
190
192
  eligibility,
@@ -450,6 +452,7 @@ function producerTuningFromConfig(config) {
450
452
 
451
453
  // src/modules/services/simple/block/runner/SimpleBlockRunner.ts
452
454
  var DEFAULT_BLOCK_SIZE = 10;
455
+ var DEFAULT_HEARTBEAT_INTERVAL = 3e5;
453
456
  var XYO_PRODUCER_REDECLARATION_DURATION = 100;
454
457
  var XYO_PRODUCER_REDECLARATION_WINDOW = 100;
455
458
  var SimpleBlockRunner = class extends AbstractCreatableProvider4 {
@@ -516,7 +519,7 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider4 {
516
519
  return this._finalizationViewer;
517
520
  }
518
521
  get heartbeatInterval() {
519
- return this.params.heartbeatInterval ?? this.producerTuning.heartbeatInterval ?? 36e5;
522
+ return this.params.heartbeatInterval ?? this.producerTuning.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;
520
523
  }
521
524
  get mempoolViewer() {
522
525
  return this._mempoolViewer;
@@ -950,6 +953,7 @@ export {
950
953
  BaseElectionService,
951
954
  BaseNetworkStakeStepRewardService,
952
955
  DEFAULT_BLOCK_SIZE,
956
+ DEFAULT_HEARTBEAT_INTERVAL,
953
957
  EvmBlockRewardViewer,
954
958
  SimpleBlockRunner,
955
959
  ValidatorMoniker,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/modules/services/BlockReward/EvmBlockRewardViewer.ts", "../../src/modules/services/ChainValidator/XyoValidator.ts", "../../src/modules/services/Election/BaseElectionService.ts", "../../src/modules/services/implementation/head/createBootstrapHead.ts", "../../src/modules/services/implementation/processPendingBlocks.ts", "../../src/modules/services/NetworkStakeStepReward/BaseNetworkStakeStepRewardService.ts", "../../src/modules/services/simple/block/runner/selectSupersededCandidate.ts", "../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts", "../../src/modules/services/simple/block/runner/generateTransactionFeeTransfers.ts", "../../src/modules/services/simple/block/runner/identifyOffendingTransactions.ts", "../../src/modules/services/simple/block/runner/producerTuning.ts", "../../src/modules/services/StepStake/BaseStepStakeService.ts"],
4
- "sourcesContent": ["export { EvmBlockRewardViewer } from '@xyo-network/xl1-sdk'\n", "import type { Promisable } from '@ariestools/sdk'\nimport type {\n BlockBoundWitness,\n BlockViewer, HydratedBlockStateValidationFunction,\n SignedHydratedTransactionWithStorageMeta,\n} from '@xyo-network/xl1-sdk'\nimport {\n AbstractCreatableProvider, BlockViewerMoniker, creatableProvider,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BaseServiceParams } from '../model/index.ts'\nimport type { Validator } from './model/index.ts'\n\nexport interface XyoValidatorParams extends BaseServiceParams {\n // account: AccountInstance\n // blockRewardService: BlockRewardService\n blockViewer?: BlockViewer\n // chainId: ChainId\n // electionService: ElectionService\n // pendingBundledTransactionsArchivist: ArchivistInstance\n // stakeIntentService: StakeIntentService\n validateHydratedBlockState: HydratedBlockStateValidationFunction\n}\n\nexport const ValidatorMoniker = 'Validator'\n\n@creatableProvider()\nexport class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParams> extends AbstractCreatableProvider<TParams> implements Validator {\n static readonly connectionTypes = [] as const\n static readonly defaultMoniker = ValidatorMoniker\n static readonly dependencies = [BlockViewerMoniker]\n static readonly monikers = [ValidatorMoniker]\n static readonly surface = 'node' as const\n moniker = XyoValidator.defaultMoniker\n private _blockViewer?: BlockViewer\n // get address() {\n // return this.account.address\n // }\n\n // protected get account() {\n // return assertEx(this.params.account, () => 'account is required')\n // }\n\n protected get blockViewer() {\n return this._blockViewer!\n }\n\n // protected get chainInfo() {\n // return assertEx(this.params.chainId, () => 'chainInfo is required')\n // }\n\n // protected get electionService() {\n // return assertEx(this.params.electionService, () => 'electionService is required')\n // }\n\n // protected get pendingBundledTransactionsArchivist() {\n // return assertEx(this.params.pendingBundledTransactionsArchivist, () => 'pendingBundledTransactions is required')\n // }\n\n // protected get blockRewardService() {\n // return assertEx(this.params.blockRewardService, () => 'blockRewardService is required')\n // }\n\n override async createHandler() {\n await super.createHandler()\n this._blockViewer = await this.locator.getInstance(BlockViewerMoniker)\n }\n\n validatePendingBlock(_block: BlockBoundWitness): Promisable<Error[]> {\n return [] // await validateBlockProtocol(block, this.chainInfo)\n }\n\n // TODO: Move to validator and inherit this class from validator\n async validatePendingTransaction(hydratedTransaction: SignedHydratedTransactionWithStorageMeta): Promise<boolean> {\n const [tx] = hydratedTransaction\n // Ensure not confirmed already (replay attack)\n if ((await this.blockViewer.blockByHash(tx._hash)) !== undefined) return false\n // TODO: Ensure transaction is valid (double spend, has voucher, has required stake, etc.)\n // TODO: Ensure validator stake is valid\n return true\n }\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport { assertEx } from '@ariestools/sdk'\nimport type { WithHashMeta, XyoAddress } from '@xyo-network/sdk'\nimport {\n AbstractCreatableProvider,\n type BlockBoundWitness,\n type BlockViewer,\n type ChainStakeViewer, creatableProvider,\n type ElectionService, type StakeIntentService,\n} from '@xyo-network/xl1-sdk'\n\nimport { hexToLast4BytesInt, shuffleWithSeed } from '#utils'\n\nimport type { BaseServiceParams } from '../model/index.ts'\n\nexport interface BaseElectionServicesParams extends BaseServiceParams {\n blockViewer?: BlockViewer\n chainStakeViewer?: ChainStakeViewer\n stakeIntentService?: StakeIntentService\n}\n\n@creatableProvider()\nexport class BaseElectionService extends AbstractCreatableProvider<BaseElectionServicesParams> implements ElectionService {\n static readonly connectionTypes = [] as const\n static readonly defaultMoniker = 'Election'\n static readonly dependencies = []\n static readonly monikers = ['Election']\n moniker = BaseElectionService.defaultMoniker\n get blockViewer() {\n return assertEx(this.params.blockViewer, () => 'No block viewer')\n }\n\n get chainStakeViewer() {\n return assertEx(this.params.chainStakeViewer, () => 'No chain stake viewer')\n }\n\n get stakeIntentService() {\n return assertEx(this.params.stakeIntentService, () => 'No staked intent service')\n }\n\n async getCreatorCommitteeForNextBlock(current: WithHashMeta<BlockBoundWitness>): Promise<XyoAddress[]> {\n return await this.spanAsync('getCreatorCommitteeForNextBlock', async () => {\n const nextBlock = current.block + 1\n const candidates = await this.stakeIntentService.getDeclaredCandidatesForBlock(nextBlock, 'producer')\n const previousBlockHash = current._hash\n return this.generateCreatorCommittee(candidates, previousBlockHash)\n }, this.context)\n }\n\n protected generateCreatorCommittee(candidates: XyoAddress[], previousBlockHash: Hash, maxSize = 3): XyoAddress[] {\n const creators = new Set<XyoAddress>(candidates)\n const seed = hexToLast4BytesInt(previousBlockHash)\n const creatorArray = shuffleWithSeed(creators, seed)\n return creatorArray.slice(0, maxSize)\n }\n}\n", "import { toAddress } from '@ariestools/sdk'\nimport type { AccountInstance, XyoAddress } from '@xyo-network/sdk'\nimport type {\n AttoXL1, ChainId, SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { createDeclarationIntent } from '@xyo-network/xl1-sdk'\n\nimport { buildNextBlock, createGenesisBlock } from '#protocol'\n\nexport const createBootstrapHead = async (\n account: AccountInstance,\n chainId: ChainId,\n genesisBlockRewardAmount: AttoXL1,\n genesisBlockRewardAddress: XyoAddress,\n): Promise<SignedHydratedBlockWithHashMeta[]> => {\n const chain: SignedHydratedBlockWithHashMeta[] = []\n\n // Create genesis block\n const genesisBlock = await createGenesisBlock(account, chainId, genesisBlockRewardAmount, genesisBlockRewardAddress)\n chain.push(genesisBlock)\n\n // Create producer declaration block\n const producerDeclarationPayload = createDeclarationIntent(\n toAddress(account.address),\n 'producer',\n genesisBlock[0].block,\n genesisBlock[0].block + 10_000,\n )\n const producerDeclarationBlock = await buildNextBlock(\n genesisBlock[0],\n [],\n [producerDeclarationPayload],\n [account],\n )\n chain.push(producerDeclarationBlock)\n return chain\n}\n", "import type { Address, Logger } from '@ariestools/sdk'\nimport { assertEx, isDefined } from '@ariestools/sdk'\nimport type { AccountInstance } from '@xyo-network/sdk'\nimport type {\n BaseContext, BlockValidationViewer, BlockViewer, DeadLetterQueueRunner, FinalizationRunner, HydratedBlockWithHashMeta, MempoolViewer,\n} from '@xyo-network/xl1-sdk'\nimport {\n BlockRejectionSchema, buildSignedBlockRejection, isSignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\n\nimport type {\n AdmissionMode, AdmissionShadowReport, ProducerEligibilityEvaluator,\n} from '#analyze'\nimport { ChainHeadSelector } from '#analyze'\n\n// type FinalizedBlockAttributes = { producer: Address }\n\ninterface ProcessPendingBlocksParams {\n /** How candidates are admitted; defaults to the allow-list the chain runs on today. */\n admission?: AdmissionMode\n allowedProducers?: Address[]\n backoffMs?: number\n blockValidationViewer: BlockValidationViewer\n blockViewer: BlockViewer\n context: BaseContext\n deadLetterQueueRunner?: DeadLetterQueueRunner\n /** Computes producer standing, for the shadow and enforce postures. */\n eligibility?: ProducerEligibilityEvaluator\n finalizationRunner: FinalizationRunner\n logger?: Logger\n mempoolViewer: MempoolViewer\n minCandidates?: number\n /**\n * Account this node observes with. When supplied, rejection records name it as the rejector and\n * carry its signature, which is what makes them attributable evidence rather than a local note.\n */\n observer?: AccountInstance\n /** Where to publish what both admission gates concluded, in shadow posture. */\n publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>\n}\n\nfunction hasMessage(value: unknown): value is { message: unknown } {\n return typeof value === 'object' && value !== null && 'message' in value\n}\n\n/**\n * Records a block that failed validation.\n *\n * With an observer account the record names and is signed by this node, which is what turns a\n * local diagnostic into evidence someone else can check; without one it keeps the legacy\n * unsigned form.\n */\nasync function reportRejectedBlock(\n deadLetterQueueRunner: DeadLetterQueueRunner,\n block: HydratedBlockWithHashMeta,\n result: unknown,\n observer?: AccountInstance,\n): Promise<void> {\n const errors = Array.isArray(result)\n ? (result as unknown[]).map(error => ({\n hash: block[0]._hash, name: 'BlockValidationError', message: String(hasMessage(error) ? error.message : error),\n }))\n : [{ hash: block[0]._hash, name: 'BlockValidationError' }]\n const rejection = {\n schema: BlockRejectionSchema, block, errors, rejector: observer?.address ?? 'validator',\n }\n const signed = observer === undefined ? undefined : await buildSignedBlockRejection(rejection, observer)\n await deadLetterQueueRunner.rejectBlock(rejection, signed)\n}\n\n// eslint-disable-next-line complexity\nexport async function processPendingBlocks({\n blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, minCandidates, deadLetterQueueRunner, observer,\n admission, eligibility, publishAdmissionShadow,\n}: ProcessPendingBlocksParams) {\n const start = Date.now()\n\n const currentBlock = await blockViewer.currentBlock()\n\n const headSelector = new ChainHeadSelector({\n context,\n logger,\n mempoolViewer,\n blockViewer,\n windowedFinalizedChain: [currentBlock],\n allowedProducers,\n backoffMs,\n minCandidates,\n admission,\n eligibility,\n publishAdmissionShadow,\n })\n\n // Use the head selector to find the best head or fallback to the starting head\n const bestHeadChain = await headSelector.findBestHead()\n\n // If we found a head\n if (isDefined(bestHeadChain) && bestHeadChain.length > 0) {\n const oldHeadBlock = currentBlock[0]\n const newHydratedHeadBlock = assertEx(bestHeadChain.at(-1), () => 'Missing best head block [processPendingBlocks]')\n const newHeadBlock = newHydratedHeadBlock[0]\n // let finalizedBlocksAttributes: FinalizedBlockAttributes[] = []\n\n // Synchronize the best head with the outArchivist all the way\n // back to the last finalized block\n\n logger?.debug('Validating new HeadBlock head from (block) ', oldHeadBlock?.block, 'to', newHeadBlock.block)\n logger?.debug('Validating new HeadBlock head from (hash) ', oldHeadBlock?._hash, 'to', newHeadBlock._hash)\n\n if (newHeadBlock._hash === oldHeadBlock?._hash) {\n logger?.debug('No new blocks found', oldHeadBlock?.block, 'to', newHeadBlock.block)\n return\n }\n\n // Store the items to be committed in the correct order\n const candidateBlocks = bestHeadChain.filter((b) => {\n return isDefined(oldHeadBlock) ? b[0].block > oldHeadBlock.block : true\n })\n\n // Validate candidate blocks before finalizing\n const validationResults = await Promise.all(candidateBlocks.map(candidateBlock => Promise.resolve(blockValidationViewer.validateBlocks([candidateBlock], { value: true, state: true }))))\n const blocksToFinalize: typeof candidateBlocks = []\n for (const [i, block] of candidateBlocks.entries()) {\n const result = validationResults[i][0]\n if (isSignedHydratedBlockWithHashMeta(result)) {\n blocksToFinalize.push(block)\n } else {\n logger?.error('Block validation failed', block[0].block, block[0]._hash, JSON.stringify(result, null, 2))\n if (deadLetterQueueRunner) await reportRejectedBlock(deadLetterQueueRunner, block, result, observer)\n }\n }\n\n logger?.info('Validated new HeadBlock head from (block) in', `${Date.now() - start}ms`, newHeadBlock.block, 'to', oldHeadBlock?.block)\n logger?.info('Validated new HeadBlock head from (hash) in', `${Date.now() - start}ms`, newHeadBlock._hash, 'to', oldHeadBlock?._hash)\n\n if (blocksToFinalize.length > 0) {\n await finalizationRunner.finalizeBlocks(blocksToFinalize)\n }\n\n // Prevent us from rechecking the same head\n await headSelector.finalizeChainFragment(blocksToFinalize)\n\n // this._startingHead = newHydratedHeadBlock\n\n // Return the finalized payloads\n return blocksToFinalize\n }\n // If no head was found, return an empty array\n logger?.info('No head found to validate', currentBlock?.[0]._hash)\n}\n", "import type { Address, Promisable } from '@ariestools/sdk'\nimport type { ReadArchivist } from '@xyo-network/sdk'\nimport type {\n AttoXL1,\n NetworkStakeStepRewardService,\n StepIdentity,\n StepIdentityString,\n} from '@xyo-network/xl1-sdk'\nimport {\n AbstractCreatableProvider,\n creatableProvider, NetworkStakeStepRewardViewerMoniker,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BaseServiceParams } from '../model/index.ts'\n\nexport interface BaseNetworkStakeStepRewardServiceParams extends BaseServiceParams {\n chainArchivist: ReadArchivist\n}\n\n@creatableProvider()\nexport class BaseNetworkStakeStepRewardService extends\n AbstractCreatableProvider<BaseNetworkStakeStepRewardServiceParams> implements NetworkStakeStepRewardService {\n static readonly connectionTypes = [] as const\n static readonly defaultMoniker = NetworkStakeStepRewardViewerMoniker\n static readonly dependencies = []\n static readonly monikers = [NetworkStakeStepRewardViewerMoniker]\n override moniker = BaseNetworkStakeStepRewardService.defaultMoniker\n\n networkStakeStepRewardAddressHistory(_address: Address): Promisable<Record<Address, AttoXL1>> {\n throw new Error('Method [networkStakeStepRewardAddressHistory] not implemented.')\n }\n\n networkStakeStepRewardAddressReward(_context: StepIdentity, _address: Address): Promisable<Record<Address, AttoXL1>> {\n throw new Error('Method [networkStakeStepRewardAddressReward] not implemented.')\n }\n\n networkStakeStepRewardAddressShare(_context: StepIdentity, _address: Address): Promisable<[bigint, bigint]> {\n throw new Error('Method [networkStakeStepRewardAddressShare] not implemented.')\n }\n\n networkStakeStepRewardClaimedByAddress(_address: Address): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardClaimedByAddress] not implemented.')\n }\n\n networkStakeStepRewardForPosition(_position: number, _range: [number, number]): Promisable<[AttoXL1, AttoXL1]> {\n throw new Error('Method [networkStakeStepRewardForPosition] not implemented.')\n }\n\n networkStakeStepRewardForStep(_context: StepIdentity): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardForStep] not implemented.')\n }\n\n networkStakeStepRewardForStepForPosition(_context: StepIdentity, _position: number): Promisable<[AttoXL1, AttoXL1]> {\n throw new Error('Method [networkStakeStepRewardForStepForPosition] not implemented.')\n }\n\n networkStakeStepRewardPoolRewards(_context: StepIdentity): Promisable<Record<Address, AttoXL1>> {\n throw new Error('Method [networkStakeStepRewardPoolRewards] not implemented.')\n }\n\n networkStakeStepRewardPoolShares(_context: StepIdentity): Promisable<Record<Address, bigint>> {\n throw new Error('Method [networkStakeStepRewardPoolShares] not implemented.')\n }\n\n networkStakeStepRewardPositionWeight(_context: StepIdentity, _position: number): Promisable<bigint> {\n throw new Error('Method [networkStakeStepRewardPositionWeight] not implemented.')\n }\n\n networkStakeStepRewardPotentialPositionLoss(_context: StepIdentity, _position: number): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardPotentialPositionLoss] not implemented.')\n }\n\n networkStakeStepRewardRandomizer(_context: StepIdentity): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardRandomizer] not implemented.')\n }\n\n networkStakeStepRewardStakerCount(_context: StepIdentity): Promisable<number> {\n throw new Error('Method [networkStakeStepRewardStakerCount] not implemented.')\n }\n\n networkStakeStepRewardUnclaimedByAddress(_address: Address): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardUnclaimedByAddress] not implemented.')\n }\n\n networkStakeStepRewardWeightForAddress(_context: StepIdentity, _address: Address): Promisable<bigint> {\n throw new Error('Method [networkStakeStepRewardWeightForAddress] not implemented.')\n }\n\n networkStakeStepRewardsForPosition(_position: number, _range: [number, number]): Promisable<Record<StepIdentityString, [AttoXL1, AttoXL1]>> {\n throw new Error('Method [networkStakeStepRewardsForPosition] not implemented.')\n }\n\n networkStakeStepRewardsForRange(_range: [number, number]): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardsForRange] not implemented.')\n }\n\n networkStakeStepRewardsForStepLevel(_stepLevel: number, _range: [number, number]): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardsForStepLevel] not implemented.')\n }\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport { isDefined } from '@ariestools/sdk'\nimport type { WithHashMeta, XyoAddress } from '@xyo-network/sdk'\nimport type { BlockBoundWitness } from '@xyo-network/xl1-sdk'\n\n/**\n * Which of a producer's own pending candidates a new proposal at this height supersedes.\n *\n * Matching on the parent as well as the height is the guard that matters. Two candidates at one\n * height built on different parents are not a re-proposal, they are competing branches, and\n * stamping a link across them would assert a supersession that never happened \u2014 turning an\n * honest producer's block into evidence against it.\n *\n * When several of its own candidates are already in the pool, the tip of the supersedes chain is\n * the one to point at: the tip is the candidate nothing else has replaced, so a third proposal\n * links to the second rather than reaching back past it and leaving the second orphaned.\n * @param candidates Pending candidates visible to this producer\n * @param address The producer's own signing address\n * @param block The height being proposed\n * @param previous The parent this proposal builds on\n * @returns The signed data hash to supersede, or undefined when there is nothing to link\n */\nexport function selectSupersededCandidate(\n candidates: WithHashMeta<BlockBoundWitness>[],\n address: XyoAddress,\n block: number,\n previous: Hash,\n): Hash | undefined {\n const own = candidates.filter(candidate => candidate.block === block\n && candidate.previous === previous\n && candidate.addresses.includes(address))\n if (own.length === 0) return undefined\n const superseded = new Set(own.map(candidate => candidate.supersedes).filter(isDefined))\n return (own.find(candidate => !superseded.has(candidate._dataHash)) ?? own[0])._dataHash\n}\n", "import type {\n Address, Hash, Promisable,\n} from '@ariestools/sdk'\nimport {\n asAddress,\n assertEx, hexToBigInt, isDefined, toAddress,\n} from '@ariestools/sdk'\nimport type {\n AccountInstance,\n ArchivistInstance, WithHashMeta, XyoAddress,\n} from '@xyo-network/sdk'\nimport {\n MemoryArchivist,\n PayloadBuilder,\n} from '@xyo-network/sdk'\nimport type {\n AccountBalanceViewer, AllowedBlockPayload, BlockBoundWitness,\n BlockNumberPayload, BlockRewardViewer, BlockRunner, BlockValidationViewer, ChainId, ChainParamsViewer,\n ChainStakeIntent, CreatableProviderParams,\n DeadLetterQueueRunner,\n FinalizationViewer,\n HydratedBlockStateValidationFunction, HydratedBlockValidationError, MempoolViewer,\n SignedBlockBoundWitnessWithHashMeta,\n SignedHydratedBlockWithHashMeta, SignedHydratedTransactionWithHashMeta,\n TimePayload, TimeSyncViewer, Transfer,\n} from '@xyo-network/xl1-sdk'\nimport {\n AbstractCreatableProvider, AccountBalanceViewerMoniker, asBlockBoundWitness, AttoXL1,\n BlockNumberSchema, BlockRejectionSchema, BlockRewardViewerMoniker, BlockRunnerMoniker,\n BlockValidationViewerMoniker, ChainParamsViewerMoniker, connectArchivist, creatableProvider, createDeclarationIntent,\n DeadLetterQueueRunnerMoniker, defaultRewardRatio,\n FinalizationViewerMoniker, isRuleActiveAt, isSignedHydratedBlockWithHashMeta, isTransferPayload, MempoolViewerMoniker,\n REJECTED_TRANSACTIONS_ARCHIVIST_ROLE,\n TimeSyncViewerMoniker,\n TransactionRejectionSchema, XYO_STEP_REWARD_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BlockRewardDiviner } from '#modules'\nimport { FixedPercentageBlockRewardDiviner, FixedPercentageBlockRewardDivinerConfigSchema } from '#modules'\nimport { buildNextBlock } from '#protocol'\n\nimport { generateTransactionFeeTransfers } from './generateTransactionFeeTransfers.ts'\nimport type { OffendingTxReason } from './identifyOffendingTransactions.ts'\nimport { identifyOffendingTransactions } from './identifyOffendingTransactions.ts'\nimport { producerTuningFromConfig } from './producerTuning.ts'\nimport { selectSupersededCandidate } from './selectSupersededCandidate.ts'\n\n/** Why and at which build height a transaction was excluded from future candidates. */\ninterface ExcludedTransactionEntry {\n excludedAtBlock: number\n reason: OffendingTxReason\n}\n\n/**\n * The default block size for a block\n */\nexport const DEFAULT_BLOCK_SIZE = 10\n\n/**\n * The amount of time for which a producer will restake their intent\n */\nexport const XYO_PRODUCER_REDECLARATION_DURATION = 100\n\n/**\n * The number of blocks within which a producer will redeclare\n * their intent to produce blocks\n */\nexport const XYO_PRODUCER_REDECLARATION_WINDOW = 100\n\nexport interface SimpleBlockRunnerParams extends CreatableProviderParams {\n /** Explicit signing account (deprecated path) \u2014 defaults to the context signer registry. */\n account?: AccountInstance\n disableIntentRedeclaration?: boolean\n heartbeatInterval?: number\n rejectedTransactionsArchivist?: ArchivistInstance\n /** Defaults to `config.rewardAddress` (producer config), then the signing account's address. */\n rewardAddress?: Address\n /**\n * When `true` (default), `filterByFunded` enforces the same cumulative-outflow\n * vs balance rule the post-submit block validator uses\n * (`base + priority + gasLimit + transfer amounts`). Setting this to `false`\n * is only appropriate for unit-style tests that exercise block-production\n * mechanics with synthetic unfunded senders and don't model balances.\n */\n validateBalances?: boolean\n validateHydratedBlockState?: HydratedBlockStateValidationFunction\n}\n\n@creatableProvider()\nexport class SimpleBlockRunner extends AbstractCreatableProvider<SimpleBlockRunnerParams> implements BlockRunner {\n /**\n * Minimum time between build attempts after a fully-rejected build (validation exhausted with\n * no attributable transaction to exclude). Such a build fails identically until external state\n * changes, so retrying at the production tick rate only churns build \u2192 validate \u2192 DLQ.\n */\n static readonly RejectedBuildBackoffMs = 1000\n\n static readonly connectionTypes = ['lmdb', 'mongo', 'memory'] as const\n static readonly defaultMoniker = BlockRunnerMoniker\n static readonly dependencies = [\n AccountBalanceViewerMoniker,\n BlockRewardViewerMoniker,\n BlockValidationViewerMoniker,\n FinalizationViewerMoniker,\n MempoolViewerMoniker,\n TimeSyncViewerMoniker,\n ]\n\n static readonly monikers = [BlockRunnerMoniker]\n\n static readonly surface = 'node' as const\n\n moniker = SimpleBlockRunner.defaultMoniker\n\n protected _blockRewardDiviner?: BlockRewardDiviner\n protected _deadLetterQueueRunner?: DeadLetterQueueRunner\n // Reason-scoped: deterministic ('tx-invalid') exclusions last the process lifetime, while\n // head-relative ('block-balance') exclusions evict once the head advances past the height they\n // were recorded at \u2014 a sender underfunded at head H may be funded at H+k, and permanent\n // exclusion would censor them. TODO(producer-exclusion-set): 'tx-invalid' entries are still\n // uncapped; add FIFO eviction if memory grows in long-running producers.\n protected _excludedTransactionHashes = new Map<Hash, ExcludedTransactionEntry>()\n protected _lastRedeclarationBlock?: number\n protected _rejectedTransactionsArchivist?: ArchivistInstance\n\n private _account?: AccountInstance\n private _accountBalanceViewer?: AccountBalanceViewer\n private _address?: Address\n private _blockRewardViewer?: BlockRewardViewer\n private _blockValidationViewer?: BlockValidationViewer\n private _chainParamsViewer?: ChainParamsViewer\n private _finalizationViewer?: FinalizationViewer\n private _lastRejectedBuildAt = 0\n /** Cache of the last candidate this runner signed; the mempool is the source of truth. */\n private _lastSignedCandidate?: { block: number; hash: Hash; previous: Hash }\n private _mempoolViewer?: MempoolViewer\n private _rewardAddress?: Address\n private _timeSyncViewer?: TimeSyncViewer\n\n /**\n * The default block size for a block\n */\n static get DefaultBlockSize(): number {\n return DEFAULT_BLOCK_SIZE\n }\n\n /**\n * The amount of time for which the producer will redeclare\n * their intent to continue producing blocks\n */\n static get RedeclarationDuration(): number {\n return XYO_PRODUCER_REDECLARATION_DURATION\n }\n\n /**\n * The number of blocks within which the producer will redeclare\n * their intent to continue producing blocks\n */\n static get RedeclarationWindow(): number {\n return XYO_PRODUCER_REDECLARATION_WINDOW\n }\n\n protected get account() {\n return this._account!\n }\n\n protected get accountBalanceViewer() {\n return this._accountBalanceViewer!\n }\n\n protected get address() {\n return this._address!\n }\n\n protected get blockRewardViewer() {\n return this._blockRewardViewer!\n }\n\n protected get blockValidationViewer() {\n return this._blockValidationViewer!\n }\n\n protected get finalizationViewer() {\n return this._finalizationViewer!\n }\n\n protected get heartbeatInterval() {\n return this.params.heartbeatInterval ?? this.producerTuning.heartbeatInterval ?? 3_600_000\n }\n\n protected get mempoolViewer() {\n return this._mempoolViewer!\n }\n\n protected get producerTuning() {\n return producerTuningFromConfig(this.config)\n }\n\n // protected get pendingTransactionsService() {\n // return assertEx(this.params.pendingTransactionsService, () => 'Missing pendingTransactionsService')\n // }\n\n protected get rejectedTransactionsArchivist() {\n return this._rejectedTransactionsArchivist!\n }\n\n protected get rewardAddress(): Address {\n return this._rewardAddress!\n }\n\n // protected get stakeIntentService(): StakeIntentService {\n // return assertEx(this.params.stakeIntentService, () => 'No StakeIntentService provided')\n // }\n\n protected get timeSyncViewer(): TimeSyncViewer {\n return this._timeSyncViewer!\n }\n\n // protected get validateHydratedBlockState() {\n // return assertEx(this.params.validateHydratedBlockState, () => 'validateHydratedBlockState is required')\n // }\n\n override async createHandler() {\n const boundConnection = this.boundConnection\n this._rejectedTransactionsArchivist = this.params.rejectedTransactionsArchivist\n ?? (boundConnection\n ? await connectArchivist(boundConnection, { name: REJECTED_TRANSACTIONS_ARCHIVIST_ROLE })\n : await MemoryArchivist.create())\n this._account = assertEx(\n this.params.account ?? this.contextAccount,\n () => 'Account is required \u2014 inject params.account or register a context signer',\n )\n this._address = toAddress(this.account.address)\n this._accountBalanceViewer = await this.locateAndCreate<AccountBalanceViewer>(AccountBalanceViewerMoniker)\n this._blockRewardViewer = await this.locateAndCreate<BlockRewardViewer>(BlockRewardViewerMoniker)\n this._blockValidationViewer = await this.locator.getInstance<BlockValidationViewer>(BlockValidationViewerMoniker)\n this._finalizationViewer = await this.locateAndCreate<FinalizationViewer>(FinalizationViewerMoniker)\n this._mempoolViewer = await this.locateAndCreate<MempoolViewer>(MempoolViewerMoniker)\n this._rewardAddress = asAddress(this.params.rewardAddress ?? this.producerTuning.rewardAddress ?? this.account.address, true)\n this._timeSyncViewer = await this.locateAndCreate<TimeSyncViewer>(TimeSyncViewerMoniker)\n this._deadLetterQueueRunner = await this.locator.tryGetInstance<DeadLetterQueueRunner>(DeadLetterQueueRunnerMoniker)\n // soft: a chain with no register never stamps supersedes, which is what keeps this release\n // emission-identical to the one before it until an activation height says otherwise\n this._chainParamsViewer = await this.locator.tryGetInstance<ChainParamsViewer>(ChainParamsViewerMoniker)\n }\n\n async next(head: WithHashMeta<BlockBoundWitness>): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n // If the block is for another chain, ignore\n // if (head.chain !== this.chainId) return\n // const leadersStart = Date.now()\n // const leaders = await this.electionService.getCreatorCommitteeForNextBlock(head)\n // const leadersDuration = Date.now() - leadersStart\n // if (leadersDuration > 100) {\n // this.logger?.warn(`[Slow] Fetched leaders in ${leadersDuration}ms: ${leaders.map(l => l.slice(0, 6)).join(', ')}`)\n // }\n // TODO: Should we propose block if creator committee is empty?\n // TODO: Handle the case where we're not the 1st leader but they're not responding\n // at a higher level than here as that's a network issue\n // if (!leaders.includes(this.address)) return\n return await this.proposeNextValidBlock(head)\n }\n\n async produceNextBlock(head: SignedBlockBoundWitnessWithHashMeta, force: true): Promise<SignedHydratedBlockWithHashMeta>\n async produceNextBlock(head: SignedBlockBoundWitnessWithHashMeta, force?: false): Promise<SignedHydratedBlockWithHashMeta | undefined>\n async produceNextBlock(head: SignedBlockBoundWitnessWithHashMeta, force?: boolean): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n // assertEx(head.chain === this.chainId, () => 'Block chain ID does not match')\n const result = await this.proposeNextValidBlock(head)\n return force === true ? assertEx(result, () => 'Failed to produce next block') : result\n }\n\n protected async getBlockRewardTransfers(block: number): Promise<Transfer[]> {\n this._blockRewardDiviner ??= await FixedPercentageBlockRewardDiviner.create({\n account: 'random',\n blockRewardViewer: this.blockRewardViewer,\n config: {\n rewardAddress: this.rewardAddress,\n rewardPercentageRatio: defaultRewardRatio,\n schema: FixedPercentageBlockRewardDivinerConfigSchema,\n },\n })\n\n const blockIdBuilder = new PayloadBuilder<BlockNumberPayload>({ schema: BlockNumberSchema })\n const blockId = blockIdBuilder.fields({ block }).build()\n const rewards = await this._blockRewardDiviner.divine([blockId])\n return rewards as Transfer[]\n }\n\n /**\n * Handles the producer redeclaration logic\n * @param head The current head block\n * @returns chain stake intent for the producer redeclaration, or undefined if no redeclaration is needed\n */\n protected getProducerRedeclaration(head: WithHashMeta<BlockBoundWitness>): Promisable<ChainStakeIntent | undefined> {\n if ((this.params.disableIntentRedeclaration ?? this.producerTuning.disableIntentRedeclaration) === true) return\n const currentBlock = head.block\n // Only redeclare when the previous declaration has expired\n if (isDefined(this._lastRedeclarationBlock)) {\n const lastDeclarationExpiry = this._lastRedeclarationBlock + SimpleBlockRunner.RedeclarationDuration\n if (currentBlock < lastDeclarationExpiry) return\n }\n this._lastRedeclarationBlock = currentBlock\n return createDeclarationIntent(this.address, 'producer', currentBlock, currentBlock + SimpleBlockRunner.RedeclarationDuration)\n }\n\n // `validateBalances` resolves from (a) the explicit method argument when\n // passed, (b) the constructor `params.validateBalances`, or (c) `true`.\n // True is the safe default: `filterByFunded` then enforces the same\n // cumulative-outflow rule the post-submit block validator uses\n // (`base + priority + gasLimit + transfer amounts`). With the old default\n // of `false`, a tx whose declared gasLimit exceeded the sender's balance\n // would pass the producer's filter, get submitted, and then land in\n // `rejected_blocks` \u2014 silently wedging the chain because the producer's\n // `_lastProducedBlock` cache muted retries. Reproduced in the\n // api-local-mongodb-beta test rig.\n protected async proposeNextValidBlock(head: WithHashMeta<BlockBoundWitness>, validateBalances?: boolean, force = false) {\n const shouldValidateBalances = validateBalances ?? this.params.validateBalances ?? true\n return await this.spanAsync('proposeNextValidBlock', async () => {\n try {\n // A build the validator fully rejected (no attributable transaction to exclude) will\n // fail identically until external state changes \u2014 new transactions, head movement, or a\n // mempool window sync. Without a floor between attempts, a production tick of 50ms churns\n // build \u2192 validate \u2192 DLQ at 20Hz. Explicitly forced builds bypass the floor; the 30s\n // stale-head resubmission arrives long after it has expired either way.\n if (this.isWithinRejectedBuildBackoff(force)) return\n const { block: previousBlock } = assertEx(asBlockBoundWitness(head), () => 'Invalid head block')\n const nextBlock = previousBlock + 1\n const chainId = await this.finalizationViewer.chainId()\n const pendingTransactionsRaw = await this.mempoolViewer.pendingTransactions({ limit: SimpleBlockRunner.DefaultBlockSize })\n this.evictStaleExclusions(previousBlock)\n const pendingTransactions = pendingTransactionsRaw.filter(tx => !this._excludedTransactionHashes.has(tx[0]._hash))\n const nextBlockTransactions = await this.rejectWrongChainTransactions(pendingTransactions, chainId)\n\n this.logger?.log(`Pending Tx Count ${nextBlockTransactions.length}`)\n\n const nonTxPayloads: AllowedBlockPayload[] = []\n\n // Calculate the optional producer redeclaration and add it if necessary\n const producerRedeclarationPayload = await this.getProducerRedeclaration(head)\n if (producerRedeclarationPayload) nonTxPayloads.push(producerRedeclarationPayload)\n\n // If there are no transactions, no payloads and no heartbeat required, we don't need to create a block\n if (nextBlockTransactions.length === 0 && !this.heartbeatRequired(head) && !force) return\n\n // Calculate the optional block reward transfer and add if necessary\n const rewardTransferPayloads = await this.getBlockRewardTransfers(nextBlock)\n nonTxPayloads.push(...rewardTransferPayloads)\n\n const transactionTransfers = await generateTransactionFeeTransfers(this.address, nextBlockTransactions)\n const timePayload = await this.generateTimePayload()\n\n const [initialFundedTransactions, initialFundedTransfers]\n = await this.filterByFunded(head, nextBlockTransactions, transactionTransfers, shouldValidateBalances)\n\n const stepRewardBalances = await this.accountBalanceViewer.accountBalances([XYO_STEP_REWARD_ADDRESS])\n const stepRewardPoolBalance = (stepRewardBalances as Record<string, AttoXL1>)[String(XYO_STEP_REWARD_ADDRESS)]\n\n const { block: proposedBlock, errors: proposedErrors } = await this.runBuildValidateRetryLoop({\n head,\n chainId,\n stepRewardPoolBalance,\n nonTxPayloads,\n timePayload,\n initialFundedTransactions,\n initialFundedTransfers,\n })\n return await this.commitProposedBlock(proposedBlock, proposedErrors)\n } catch (error) {\n this.logger?.error(`Error proposing next valid block: ${(error as Error).message}`)\n throw error\n }\n }, this.context)\n }\n\n private addTransferOutflow(outflow: bigint, payload: Transfer): bigint {\n let result = outflow\n for (const [to, amount] of Object.entries(payload.transfers)) {\n if (to === payload.from) continue\n result += hexToBigInt((amount ?? '00'))\n }\n return result\n }\n\n private async commitProposedBlock(\n proposedBlock: SignedHydratedBlockWithHashMeta | undefined,\n proposedErrors: HydratedBlockValidationError[],\n ): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n // The type guard alone is not a validity check \u2014 every built block is structurally a\n // signed hydrated block, including one the retry loop exhausted on. Only a block the\n // loop returned WITHOUT errors passed validation; anything else must not be published.\n if (proposedErrors.length === 0 && isSignedHydratedBlockWithHashMeta(proposedBlock)) {\n this._lastRejectedBuildAt = 0\n // Submission is the producer's responsibility (`ProducerActor.produceBlock`)\n // \u2014 SimpleBlockRunner just builds and validates. Previously this site\n // also called `mempoolRunner.submitBlocks`, double-submitting the\n // same block. The second submit at the producer always failed with\n // \"archivist accepted 0 of 1\" because the inner one had already\n // landed. Removing the inner submit eliminates that false positive\n // and means SimpleBlockRunner no longer needs a MempoolRunner\n // dependency at all.\n return proposedBlock\n }\n if (proposedBlock !== undefined) {\n this._lastRejectedBuildAt = Date.now()\n await this.rejectExhaustedBlock(proposedBlock, proposedErrors)\n }\n }\n\n /**\n * Compute the cumulative outflow a single tx would charge to its `from`\n * address, using the same rule as `BlockCumulativeBalanceValidator`:\n * `outflow = base + priority + gasLimit + sum(transfer amounts to addresses\n * other than from)`. Mirroring the validator exactly here ensures the\n * producer doesn't include a tx that the post-submit block validator will\n * reject, which would otherwise wedge the chain because the producer's\n * `_lastProducedBlock` cache mutes retries.\n */\n private computeTransactionOutflow(tx: SignedHydratedTransactionWithHashMeta): bigint {\n const [bw, payloads] = tx\n const {\n base, gasLimit, priority,\n } = bw.fees\n let outflow = hexToBigInt(base) + hexToBigInt(priority) + hexToBigInt(gasLimit)\n const txPayloadHashes = new Set(bw.payload_hashes)\n for (const payload of payloads) {\n if (!txPayloadHashes.has(payload._hash)) continue\n if (!isTransferPayload(payload)) continue\n if (payload.from !== bw.from) continue\n outflow = this.addTransferOutflow(outflow, payload)\n }\n return outflow\n }\n\n /**\n * Drops head-relative ('block-balance') exclusions once the head has advanced past the height\n * they were recorded at \u2014 the sender's funding is re-evaluated by filterByFunded at the new\n * head. Deterministic ('tx-invalid') exclusions are kept for the process lifetime.\n */\n private evictStaleExclusions(headBlock: number): void {\n for (const [hash, entry] of this._excludedTransactionHashes) {\n if (entry.reason === 'block-balance' && headBlock > entry.excludedAtBlock) {\n this._excludedTransactionHashes.delete(hash)\n }\n }\n }\n\n // remove unfunded transactions and block transfers\n private async filterByFunded(\n head: WithHashMeta<BlockBoundWitness>,\n txs: SignedHydratedTransactionWithHashMeta[],\n transfers: Transfer[],\n validateBalances = false,\n ): Promise<[SignedHydratedTransactionWithHashMeta[], Transfer[]]> {\n const fundedTransfers: Transfer[] = []\n const fundedTransactions: SignedHydratedTransactionWithHashMeta[] = []\n // Outflow already committed to this block per sender, plus a per-sender\n // balance cache (balances are read at the fixed parent `head`). Each tx is\n // gated against the sender's REMAINING balance, not the full balance in\n // isolation. Checking each tx independently (the previous behavior) lets two\n // individually-valid transfers from the same sender \u2014 a double-spend across\n // transactions, each \u2264 balance but jointly > balance \u2014 both pass. The block\n // then carries a cumulative outflow the post-submit validator rejects, and\n // the producer wedges (its `_lastProducedBlock` cache mutes retries).\n // Sequential, cumulative gating includes only the first transfer that fits\n // and drops the rest; the dropped tx stays pending and is pruned once the\n // included one lands and the sender can no longer cover it.\n const committedOutflow = new Map<XyoAddress, bigint>()\n const balanceCache = new Map<XyoAddress, bigint>()\n for (const tx of txs) {\n const transfer: Transfer | undefined = transfers.find(candidate => candidate.from === tx[0].from)\n if (!transfer) continue\n if (!validateBalances) {\n fundedTransfers.push(transfer)\n fundedTransactions.push(tx)\n continue\n }\n const { from } = transfer\n let balance = balanceCache.get(from)\n if (balance === undefined) {\n const accountBalances = await this.accountBalanceViewer.accountBalances([from])\n balance = (accountBalances as Record<string, bigint>)[String(from)] ?? AttoXL1(0n)\n balanceCache.set(from, balance)\n }\n // Mirror the post-submit block validator's cumulative-outflow rule\n // (base + priority + gasLimit + transfer amounts) against the running\n // total for this sender, so the producer never includes a tx the\n // validator will reject.\n const projectedOutflow = (committedOutflow.get(from) ?? 0n) + this.computeTransactionOutflow(tx)\n if (balance >= projectedOutflow) {\n committedOutflow.set(from, projectedOutflow)\n fundedTransfers.push(transfer)\n fundedTransactions.push(tx)\n } else {\n this.logger?.debug(\n `filterByFunded: dropping tx ${tx[0]._hash} from ${from} \u2014 cumulative outflow ${projectedOutflow} > balance ${balance}`,\n )\n }\n }\n return [fundedTransactions, fundedTransfers]\n }\n\n private async generateTimePayload() {\n const timeStart = Date.now()\n const timePayload = await this.timeSyncViewer.currentTimePayload()\n const timeDuration = Date.now() - timeStart\n if (timeDuration > 100) {\n this.logger?.warn(`[Slow] Generated time payload in ${timeDuration}ms`)\n }\n return timePayload\n }\n\n /**\n * Check if a heartbeat block is required based on network activity.\n * @param head The current head block\n * @returns True if a heartbeat is required, false otherwise\n */\n private heartbeatRequired(head: WithHashMeta<BlockBoundWitness>): boolean {\n const epoch = head.$epoch\n if (isDefined(epoch) && Date.now() - epoch > this.heartbeatInterval) {\n return true\n }\n return false\n }\n\n private isWithinRejectedBuildBackoff(force: boolean): boolean {\n if (force || Date.now() - this._lastRejectedBuildAt >= SimpleBlockRunner.RejectedBuildBackoffMs) return false\n this.logger?.debug('Skipping block production during rejected-build backoff')\n return true\n }\n\n /**\n * The hash of this producer's own earlier candidate at the same height and parent, if any.\n *\n * The parent is part of the match on purpose. Two candidates at one height built on different\n * parents are not a re-proposal, they are different branches, and linking across them would\n * assert a supersession that never happened.\n *\n * Memory is only a cache. A restart wipes it while the pool still holds the prior candidate, so\n * the pool is consulted whenever memory misses. Following the chain to its tip keeps a third\n * proposal pointing at the second rather than back at the first.\n * @param block The height being proposed\n * @param previous The parent this proposal builds on\n * @returns The prior candidate's signed data hash, or undefined when there is none\n */\n private async previousOwnCandidateHash(block: number, previous: Hash): Promise<Hash | undefined> {\n const cached = this._lastSignedCandidate\n if (cached?.block === block && cached.previous === previous) return cached.hash\n const candidates = (await this.mempoolViewer.pendingBlocks()).map(([candidate]) => candidate)\n return selectSupersededCandidate(candidates, this.address, block, previous)\n }\n\n private async rejectExhaustedBlock(\n block: SignedHydratedBlockWithHashMeta,\n errors: HydratedBlockValidationError[],\n ): Promise<void> {\n this.logger?.warn(`Validation of produced block failed: ${errors.at(0)?.message}`)\n if (this._deadLetterQueueRunner) {\n const rejectionErrors = errors.map(e => ({\n hash: block[0]._hash, name: 'BlockValidationError', message: String(e.message ?? e),\n }))\n await this._deadLetterQueueRunner.rejectBlock({\n schema: BlockRejectionSchema, block, errors: rejectionErrors, rejector: 'producer',\n })\n } else {\n await this.rejectedTransactionsArchivist.insert(block[1])\n }\n }\n\n // Partition pending transactions by chain-ID match; route mismatches to the transaction DLQ.\n private async rejectWrongChainTransactions(\n transactions: SignedHydratedTransactionWithHashMeta[],\n chainId: ChainId,\n ): Promise<SignedHydratedTransactionWithHashMeta[]> {\n const localChain = chainId.toLowerCase()\n const matched: SignedHydratedTransactionWithHashMeta[] = []\n const mismatched: SignedHydratedTransactionWithHashMeta[] = []\n for (const tx of transactions) {\n if (tx[0].chain.toLowerCase() === localChain) {\n matched.push(tx)\n } else {\n mismatched.push(tx)\n }\n }\n if (mismatched.length > 0) {\n this.logger?.warn(`Rejecting ${mismatched.length} transaction(s) targeting non-local chain`)\n const dlq = this._deadLetterQueueRunner\n await (dlq\n ? Promise.all(mismatched.map(tx => dlq.rejectTransaction({\n schema: TransactionRejectionSchema,\n transaction: tx,\n errors: [{\n hash: tx[0]._hash,\n name: 'TransactionChainMismatch',\n message: `Transaction chain ${tx[0].chain} does not match local chain ${localChain}`,\n }],\n rejector: 'producer',\n })))\n : this.rejectedTransactionsArchivist.insert(mismatched.map(tx => tx[0])))\n }\n return matched\n }\n\n /**\n * The candidate this proposal supersedes, or undefined when nothing should be stamped.\n *\n * Identity is the signed data hash rather than the storage hash, because that is what an\n * observer recomputes when deciding whether two candidates are the same block \u2014 client meta\n * such as `$epoch` must not be able to make one candidate look like two.\n *\n * With no register wired, or with the field unactivated, this never stamps. That is what keeps\n * a producer running this build emission-identical to one running the release before it, which\n * the rollout depends on: stamping before the fleet has upgraded would partition validation.\n * @param head The block being built on\n * @returns The superseded candidate's hash, or undefined\n */\n private async resolveSupersedes(head: WithHashMeta<BlockBoundWitness>): Promise<Hash | undefined> {\n const viewer = this._chainParamsViewer\n if (viewer === undefined) return undefined\n const params = await viewer.tryCurrentParams()\n const block = head.block + 1\n if (params === undefined || !isRuleActiveAt(params, 'supersedes-field', block)) return undefined\n return await this.previousOwnCandidateHash(block, head._hash)\n }\n\n private async runBuildValidateRetryLoop(args: {\n chainId: ChainId\n head: WithHashMeta<BlockBoundWitness>\n initialFundedTransactions: SignedHydratedTransactionWithHashMeta[]\n initialFundedTransfers: Transfer[]\n nonTxPayloads: AllowedBlockPayload[]\n stepRewardPoolBalance: AttoXL1\n timePayload: TimePayload\n }): Promise<{\n block: SignedHydratedBlockWithHashMeta | undefined\n errors: HydratedBlockValidationError[]\n }> {\n const {\n chainId, head, initialFundedTransactions, initialFundedTransfers,\n nonTxPayloads, stepRewardPoolBalance, timePayload,\n } = args\n const supersedes = await this.resolveSupersedes(head)\n const maxAttempts = Math.max(1, initialFundedTransactions.length)\n let candidateTransactions = initialFundedTransactions\n let candidateTransfers = initialFundedTransfers\n let lastBlock: SignedHydratedBlockWithHashMeta | undefined\n let lastErrors: HydratedBlockValidationError[] = []\n\n for (let attempt = 0; attempt <= maxAttempts; attempt++) {\n const blockPayloads = [...nonTxPayloads, ...candidateTransfers, timePayload]\n this.logger?.info(`Building block ${head.block + 1}${attempt > 0 ? ` (retry ${attempt})` : ''}`)\n lastBlock = await buildNextBlock(\n head,\n candidateTransactions,\n blockPayloads,\n [this.account],\n XYO_STEP_REWARD_ADDRESS,\n stepRewardPoolBalance,\n undefined,\n chainId,\n supersedes,\n )\n // Run the same value+state validation the finalizer and mempool sweep will apply. A\n // `{head}`-only config selects no validators at all, which made this retry loop dead code:\n // an invalid candidate was published anyway, silently rejected downstream, and the producer\n // muted until its stale-head resubmission threshold.\n const validated = await this.blockValidationViewer.validateBlock(lastBlock, {\n value: true, state: true, head: head._hash,\n })\n if (isSignedHydratedBlockWithHashMeta(validated)) {\n // recorded only for a candidate that actually stands, so a later proposal never claims to\n // supersede one that was built, rejected, and never seen by anyone\n this._lastSignedCandidate = {\n block: validated[0].block, hash: validated[0]._dataHash, previous: head._hash,\n }\n return { block: validated, errors: [] }\n }\n lastErrors = validated\n if (attempt === maxAttempts) break\n const { offendingHashes, reason } = await identifyOffendingTransactions({ candidateTransactions, errors: validated })\n if (offendingHashes.length === 0 || reason === 'unknown') break\n for (const offendingHash of offendingHashes) {\n this._excludedTransactionHashes.set(offendingHash, { excludedAtBlock: head.block, reason })\n }\n const offendingSet = new Set<Hash>(offendingHashes)\n candidateTransactions = candidateTransactions.filter(tx => !offendingSet.has(tx[0]._hash))\n const remainingFromAddresses = new Set<XyoAddress>(candidateTransactions.map(tx => tx[0].from))\n const feeTransfers = await generateTransactionFeeTransfers(this.address, candidateTransactions)\n candidateTransfers = feeTransfers.filter(t => remainingFromAddresses.has(t.from))\n this.logger?.warn(`Block validation failed (attempt ${attempt + 1}); excluded ${offendingHashes.length} tx(s), retrying`)\n }\n return { block: lastBlock, errors: lastErrors }\n }\n}\n", "import { assertEx, hexFromBigInt } from '@ariestools/sdk'\nimport type { XyoAddress } from '@xyo-network/sdk'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n SignedHydratedTransaction,\n Transfer,\n XL1,\n} from '@xyo-network/xl1-sdk'\nimport {\n HydratedTransactionWrapper,\n transactionRequiredGas, TransferSchema, XYO_ZERO_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nexport async function generateTransactionFeeTransfers(address: XyoAddress, transactions: SignedHydratedTransaction[]): Promise<Transfer[]> {\n const txs = await Promise.all(transactions.map(async (tx) => {\n return HydratedTransactionWrapper.parse([await PayloadBuilder.addStorageMeta(tx[0]), await PayloadBuilder.addStorageMeta(tx[1])])\n }))\n\n // merge transactions with the same from address\n const txBaseFeeCosts: Record<XyoAddress, bigint> = {}\n for (const tx of txs) {\n txBaseFeeCosts[tx.boundWitness.from] = (txBaseFeeCosts[tx.boundWitness.from] ?? 0n)\n + tx.fees.base\n }\n\n const txGasCosts: Record<XyoAddress, bigint> = {}\n for (const tx of txs) {\n const requiredGas = transactionRequiredGas(tx.data)\n const totalGasCost = requiredGas * tx.fees.gasPrice\n txGasCosts[tx.boundWitness.from] = (txBaseFeeCosts[tx.boundWitness.from] ?? 0n)\n + totalGasCost\n }\n\n // generate actual Transfer Payloads & burn the base fee\n const payloads = (Object.entries(txBaseFeeCosts) as [XyoAddress, XL1][]).map(([from, amount]) => {\n const payload: Transfer = {\n schema: TransferSchema,\n epoch: Date.now(),\n from,\n transfers: Object.fromEntries([[String(XYO_ZERO_ADDRESS), hexFromBigInt(amount)]]),\n }\n return payload\n })\n\n // transfer gas cost to producer\n for (const [from, amount] of Object.entries(txGasCosts)) {\n // every gas from should also be a base fee from\n const fromPayload = assertEx(payloads.find(p => p.from === from), () => 'from payload not found')\n fromPayload.transfers[address] = hexFromBigInt(amount)\n }\n\n return payloads\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport type { HydratedBlockValidationError, SignedHydratedTransactionWithHashMeta } from '@xyo-network/xl1-sdk'\nimport {\n HydratedTransactionWrapper,\n netBalancesForPayloads,\n transactionRequiredGas,\n} from '@xyo-network/xl1-sdk'\n\nexport type OffendingTxReason = 'block-balance' | 'tx-invalid' | 'unknown'\n\nexport interface OffendingTxResult {\n offendingHashes: Hash[]\n reason: OffendingTxReason\n}\n\ninterface TxScore {\n cost: bigint\n gasPrice: bigint\n}\n\nasync function scoreTransaction(tx: SignedHydratedTransactionWithHashMeta): Promise<TxScore> {\n const wrapper = await HydratedTransactionWrapper.parse(tx)\n const from = wrapper.boundWitness.from\n const gasPrice = wrapper.fees.gasPrice\n const gasCost = transactionRequiredGas(tx) * gasPrice\n const baseCost = wrapper.fees.base\n const netBalances = netBalancesForPayloads({ singletons: {} }, tx[1])\n const fromNet = netBalances[from] ?? 0n\n const transferOut = fromNet < 0n ? -fromNet : 0n\n return { cost: gasCost + baseCost + transferOut, gasPrice }\n}\n\nexport async function identifyOffendingTransactions(args: {\n candidateTransactions: SignedHydratedTransactionWithHashMeta[]\n errors: HydratedBlockValidationError[]\n}): Promise<OffendingTxResult> {\n const { errors, candidateTransactions } = args\n const candidateHashes = new Set<Hash>(candidateTransactions.map(tx => tx[0]._hash))\n\n const txInvalidHashes = new Set<Hash>()\n for (const error of errors) {\n if (candidateHashes.has(error.hash)) txInvalidHashes.add(error.hash)\n const cause = error.cause as undefined | { hash?: Hash }\n if (cause?.hash && candidateHashes.has(cause.hash)) txInvalidHashes.add(cause.hash)\n }\n if (txInvalidHashes.size > 0) {\n return { offendingHashes: [...txInvalidHashes], reason: 'tx-invalid' }\n }\n\n const balanceOffenderHashes = new Set<Hash>()\n for (const error of errors) {\n const offendingHashes = (error as { offendingTransactionHashes?: Hash[] }).offendingTransactionHashes ?? []\n for (const hash of offendingHashes) {\n if (candidateHashes.has(hash)) balanceOffenderHashes.add(hash)\n }\n }\n if (balanceOffenderHashes.size === 0) {\n return { offendingHashes: [], reason: 'unknown' }\n }\n\n const offenders = candidateTransactions.filter(tx => balanceOffenderHashes.has(tx[0]._hash))\n const scored = await Promise.all(offenders.map(async tx => ({ tx, ...(await scoreTransaction(tx)) })))\n scored.sort((a, b) => {\n if (a.cost !== b.cost) return a.cost < b.cost ? 1 : -1\n if (a.gasPrice !== b.gasPrice) return a.gasPrice < b.gasPrice ? -1 : 1\n return a.tx[0]._hash < b.tx[0]._hash ? -1 : 1\n })\n return { offendingHashes: [scored[0].tx[0]._hash], reason: 'block-balance' }\n}\n", "import { z } from 'zod'\n\n/**\n * Producer tuning read from the materialized provider config's `options`\n * (`providerBindings.BlockRunner.options` \u2014 orchestration lifts the producer\n * actor slice there at config load).\n */\nexport const ProducerTuningOptionsZod = z.object({\n disableIntentRedeclaration: z.coerce.boolean().optional(),\n heartbeatInterval: z.coerce.number().optional(),\n rewardAddress: z.string().optional(),\n})\n\n/** Producer tuning fields resolved from provider options. */\nexport type ProducerTuningFields = z.infer<typeof ProducerTuningOptionsZod>\n\n/** Producer tuning from the materialized provider config. */\nexport function producerTuningFromConfig(config: unknown): ProducerTuningFields {\n const options = (config as { options?: Record<string, unknown> }).options ?? {}\n const parsed = ProducerTuningOptionsZod.safeParse(options)\n return parsed.success ? parsed.data : {}\n}\n", "import type { Promisable } from '@ariestools/sdk'\nimport type { ReadArchivist, XyoAddress } from '@xyo-network/sdk'\nimport type { StepIdentity, StepStakeViewer } from '@xyo-network/xl1-sdk'\nimport { AbstractCreatableProvider, StepStakeViewerMoniker } from '@xyo-network/xl1-sdk'\n\nimport type { BaseServiceParams } from '../model/index.ts'\n\nexport interface BaseStepStakeServiceParams extends BaseServiceParams {\n chainArchivist: ReadArchivist\n}\n\nexport abstract class AbstractStepStakeService extends AbstractCreatableProvider<BaseStepStakeServiceParams> implements StepStakeViewer {\n static readonly defaultMoniker = StepStakeViewerMoniker\n static readonly monikers = [StepStakeViewerMoniker]\n override moniker = AbstractStepStakeService.defaultMoniker\n\n stepStake(_step: StepIdentity): Promisable<Record<XyoAddress, bigint>> {\n throw new Error('Method [stepStake] not implemented.')\n }\n\n stepStakeForAddress(_address: XyoAddress, _step: StepIdentity): Promisable<bigint> {\n throw new Error('Method [stepStakeForAddress] not implemented.')\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { EvmBlockRewardViewer } from '@xyo-network/xl1-sdk'\n", "import type { Promisable } from '@ariestools/sdk'\nimport type {\n BlockBoundWitness,\n BlockViewer, HydratedBlockStateValidationFunction,\n SignedHydratedTransactionWithStorageMeta,\n} from '@xyo-network/xl1-sdk'\nimport {\n AbstractCreatableProvider, BlockViewerMoniker, creatableProvider,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BaseServiceParams } from '../model/index.ts'\nimport type { Validator } from './model/index.ts'\n\nexport interface XyoValidatorParams extends BaseServiceParams {\n // account: AccountInstance\n // blockRewardService: BlockRewardService\n blockViewer?: BlockViewer\n // chainId: ChainId\n // electionService: ElectionService\n // pendingBundledTransactionsArchivist: ArchivistInstance\n // stakeIntentService: StakeIntentService\n validateHydratedBlockState: HydratedBlockStateValidationFunction\n}\n\nexport const ValidatorMoniker = 'Validator'\n\n@creatableProvider()\nexport class XyoValidator<TParams extends XyoValidatorParams = XyoValidatorParams> extends AbstractCreatableProvider<TParams> implements Validator {\n static readonly connectionTypes = [] as const\n static readonly defaultMoniker = ValidatorMoniker\n static readonly dependencies = [BlockViewerMoniker]\n static readonly monikers = [ValidatorMoniker]\n static readonly surface = 'node' as const\n moniker = XyoValidator.defaultMoniker\n private _blockViewer?: BlockViewer\n // get address() {\n // return this.account.address\n // }\n\n // protected get account() {\n // return assertEx(this.params.account, () => 'account is required')\n // }\n\n protected get blockViewer() {\n return this._blockViewer!\n }\n\n // protected get chainInfo() {\n // return assertEx(this.params.chainId, () => 'chainInfo is required')\n // }\n\n // protected get electionService() {\n // return assertEx(this.params.electionService, () => 'electionService is required')\n // }\n\n // protected get pendingBundledTransactionsArchivist() {\n // return assertEx(this.params.pendingBundledTransactionsArchivist, () => 'pendingBundledTransactions is required')\n // }\n\n // protected get blockRewardService() {\n // return assertEx(this.params.blockRewardService, () => 'blockRewardService is required')\n // }\n\n override async createHandler() {\n await super.createHandler()\n this._blockViewer = await this.locator.getInstance(BlockViewerMoniker)\n }\n\n validatePendingBlock(_block: BlockBoundWitness): Promisable<Error[]> {\n return [] // await validateBlockProtocol(block, this.chainInfo)\n }\n\n // TODO: Move to validator and inherit this class from validator\n async validatePendingTransaction(hydratedTransaction: SignedHydratedTransactionWithStorageMeta): Promise<boolean> {\n const [tx] = hydratedTransaction\n // Ensure not confirmed already (replay attack)\n if ((await this.blockViewer.blockByHash(tx._hash)) !== undefined) return false\n // TODO: Ensure transaction is valid (double spend, has voucher, has required stake, etc.)\n // TODO: Ensure validator stake is valid\n return true\n }\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport { assertEx } from '@ariestools/sdk'\nimport type { WithHashMeta, XyoAddress } from '@xyo-network/sdk'\nimport {\n AbstractCreatableProvider,\n type BlockBoundWitness,\n type BlockViewer,\n type ChainStakeViewer, creatableProvider,\n type ElectionService, type StakeIntentService,\n} from '@xyo-network/xl1-sdk'\n\nimport { hexToLast4BytesInt, shuffleWithSeed } from '#utils'\n\nimport type { BaseServiceParams } from '../model/index.ts'\n\nexport interface BaseElectionServicesParams extends BaseServiceParams {\n blockViewer?: BlockViewer\n chainStakeViewer?: ChainStakeViewer\n stakeIntentService?: StakeIntentService\n}\n\n@creatableProvider()\nexport class BaseElectionService extends AbstractCreatableProvider<BaseElectionServicesParams> implements ElectionService {\n static readonly connectionTypes = [] as const\n static readonly defaultMoniker = 'Election'\n static readonly dependencies = []\n static readonly monikers = ['Election']\n moniker = BaseElectionService.defaultMoniker\n get blockViewer() {\n return assertEx(this.params.blockViewer, () => 'No block viewer')\n }\n\n get chainStakeViewer() {\n return assertEx(this.params.chainStakeViewer, () => 'No chain stake viewer')\n }\n\n get stakeIntentService() {\n return assertEx(this.params.stakeIntentService, () => 'No staked intent service')\n }\n\n async getCreatorCommitteeForNextBlock(current: WithHashMeta<BlockBoundWitness>): Promise<XyoAddress[]> {\n return await this.spanAsync('getCreatorCommitteeForNextBlock', async () => {\n const nextBlock = current.block + 1\n const candidates = await this.stakeIntentService.getDeclaredCandidatesForBlock(nextBlock, 'producer')\n const previousBlockHash = current._hash\n return this.generateCreatorCommittee(candidates, previousBlockHash)\n }, this.context)\n }\n\n protected generateCreatorCommittee(candidates: XyoAddress[], previousBlockHash: Hash, maxSize = 3): XyoAddress[] {\n const creators = new Set<XyoAddress>(candidates)\n const seed = hexToLast4BytesInt(previousBlockHash)\n const creatorArray = shuffleWithSeed(creators, seed)\n return creatorArray.slice(0, maxSize)\n }\n}\n", "import { toAddress } from '@ariestools/sdk'\nimport type { AccountInstance, XyoAddress } from '@xyo-network/sdk'\nimport type {\n AttoXL1, ChainId, SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { createDeclarationIntent } from '@xyo-network/xl1-sdk'\n\nimport { buildNextBlock, createGenesisBlock } from '#protocol'\n\nexport const createBootstrapHead = async (\n account: AccountInstance,\n chainId: ChainId,\n genesisBlockRewardAmount: AttoXL1,\n genesisBlockRewardAddress: XyoAddress,\n): Promise<SignedHydratedBlockWithHashMeta[]> => {\n const chain: SignedHydratedBlockWithHashMeta[] = []\n\n // Create genesis block\n const genesisBlock = await createGenesisBlock(account, chainId, genesisBlockRewardAmount, genesisBlockRewardAddress)\n chain.push(genesisBlock)\n\n // Create producer declaration block\n const producerDeclarationPayload = createDeclarationIntent(\n toAddress(account.address),\n 'producer',\n genesisBlock[0].block,\n genesisBlock[0].block + 10_000,\n )\n const producerDeclarationBlock = await buildNextBlock(\n genesisBlock[0],\n [],\n [producerDeclarationPayload],\n [account],\n )\n chain.push(producerDeclarationBlock)\n return chain\n}\n", "import type { Address, Logger } from '@ariestools/sdk'\nimport { assertEx, isDefined } from '@ariestools/sdk'\nimport type { AccountInstance } from '@xyo-network/sdk'\nimport type {\n BaseContext, BlockValidationViewer, BlockViewer, DeadLetterQueueRunner, FinalizationRunner, HydratedBlockWithHashMeta, MempoolViewer,\n} from '@xyo-network/xl1-sdk'\nimport {\n BlockRejectionSchema, buildSignedBlockRejection, isSignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\n\nimport type {\n AdmissionMode, AdmissionShadowReport, ProducerEligibilityEvaluator,\n} from '#analyze'\nimport { ChainHeadSelector } from '#analyze'\n\n// type FinalizedBlockAttributes = { producer: Address }\n\ninterface ProcessPendingBlocksParams {\n /** How candidates are admitted; defaults to the allow-list the chain runs on today. */\n admission?: AdmissionMode\n allowedProducers?: Address[]\n backoffMs?: number\n blockValidationViewer: BlockValidationViewer\n blockViewer: BlockViewer\n context: BaseContext\n deadLetterQueueRunner?: DeadLetterQueueRunner\n /** Computes producer standing, for the shadow and enforce postures. */\n eligibility?: ProducerEligibilityEvaluator\n finalizationRunner: FinalizationRunner\n /**\n * Minimum epoch spacing (ms) between transaction-less heartbeat blocks the head selector will\n * qualify; transaction-carrying candidates are exempt. Undefined disables the pace check.\n */\n heartbeatInterval?: number\n logger?: Logger\n mempoolViewer: MempoolViewer\n minCandidates?: number\n /**\n * Account this node observes with. When supplied, rejection records name it as the rejector and\n * carry its signature, which is what makes them attributable evidence rather than a local note.\n */\n observer?: AccountInstance\n /** Where to publish what both admission gates concluded, in shadow posture. */\n publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>\n}\n\nfunction hasMessage(value: unknown): value is { message: unknown } {\n return typeof value === 'object' && value !== null && 'message' in value\n}\n\n/**\n * Records a block that failed validation.\n *\n * With an observer account the record names and is signed by this node, which is what turns a\n * local diagnostic into evidence someone else can check; without one it keeps the legacy\n * unsigned form.\n */\nasync function reportRejectedBlock(\n deadLetterQueueRunner: DeadLetterQueueRunner,\n block: HydratedBlockWithHashMeta,\n result: unknown,\n observer?: AccountInstance,\n): Promise<void> {\n const errors = Array.isArray(result)\n ? (result as unknown[]).map(error => ({\n hash: block[0]._hash, name: 'BlockValidationError', message: String(hasMessage(error) ? error.message : error),\n }))\n : [{ hash: block[0]._hash, name: 'BlockValidationError' }]\n const rejection = {\n schema: BlockRejectionSchema, block, errors, rejector: observer?.address ?? 'validator',\n }\n const signed = observer === undefined ? undefined : await buildSignedBlockRejection(rejection, observer)\n await deadLetterQueueRunner.rejectBlock(rejection, signed)\n}\n\n// eslint-disable-next-line complexity\nexport async function processPendingBlocks({\n blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, heartbeatInterval, minCandidates, deadLetterQueueRunner, observer,\n admission, eligibility, publishAdmissionShadow,\n}: ProcessPendingBlocksParams) {\n const start = Date.now()\n\n const currentBlock = await blockViewer.currentBlock()\n\n const headSelector = new ChainHeadSelector({\n context,\n logger,\n mempoolViewer,\n blockViewer,\n windowedFinalizedChain: [currentBlock],\n allowedProducers,\n backoffMs,\n heartbeatInterval,\n minCandidates,\n admission,\n eligibility,\n publishAdmissionShadow,\n })\n\n // Use the head selector to find the best head or fallback to the starting head\n const bestHeadChain = await headSelector.findBestHead()\n\n // If we found a head\n if (isDefined(bestHeadChain) && bestHeadChain.length > 0) {\n const oldHeadBlock = currentBlock[0]\n const newHydratedHeadBlock = assertEx(bestHeadChain.at(-1), () => 'Missing best head block [processPendingBlocks]')\n const newHeadBlock = newHydratedHeadBlock[0]\n // let finalizedBlocksAttributes: FinalizedBlockAttributes[] = []\n\n // Synchronize the best head with the outArchivist all the way\n // back to the last finalized block\n\n logger?.debug('Validating new HeadBlock head from (block) ', oldHeadBlock?.block, 'to', newHeadBlock.block)\n logger?.debug('Validating new HeadBlock head from (hash) ', oldHeadBlock?._hash, 'to', newHeadBlock._hash)\n\n if (newHeadBlock._hash === oldHeadBlock?._hash) {\n logger?.debug('No new blocks found', oldHeadBlock?.block, 'to', newHeadBlock.block)\n return\n }\n\n // Store the items to be committed in the correct order\n const candidateBlocks = bestHeadChain.filter((b) => {\n return isDefined(oldHeadBlock) ? b[0].block > oldHeadBlock.block : true\n })\n\n // Validate candidate blocks before finalizing\n const validationResults = await Promise.all(candidateBlocks.map(candidateBlock => Promise.resolve(blockValidationViewer.validateBlocks([candidateBlock], { value: true, state: true }))))\n const blocksToFinalize: typeof candidateBlocks = []\n for (const [i, block] of candidateBlocks.entries()) {\n const result = validationResults[i][0]\n if (isSignedHydratedBlockWithHashMeta(result)) {\n blocksToFinalize.push(block)\n } else {\n logger?.error('Block validation failed', block[0].block, block[0]._hash, JSON.stringify(result, null, 2))\n if (deadLetterQueueRunner) await reportRejectedBlock(deadLetterQueueRunner, block, result, observer)\n }\n }\n\n logger?.info('Validated new HeadBlock head from (block) in', `${Date.now() - start}ms`, newHeadBlock.block, 'to', oldHeadBlock?.block)\n logger?.info('Validated new HeadBlock head from (hash) in', `${Date.now() - start}ms`, newHeadBlock._hash, 'to', oldHeadBlock?._hash)\n\n if (blocksToFinalize.length > 0) {\n await finalizationRunner.finalizeBlocks(blocksToFinalize)\n }\n\n // Prevent us from rechecking the same head\n await headSelector.finalizeChainFragment(blocksToFinalize)\n\n // this._startingHead = newHydratedHeadBlock\n\n // Return the finalized payloads\n return blocksToFinalize\n }\n // If no head was found, return an empty array\n logger?.info('No head found to validate', currentBlock?.[0]._hash)\n}\n", "import type { Address, Promisable } from '@ariestools/sdk'\nimport type { ReadArchivist } from '@xyo-network/sdk'\nimport type {\n AttoXL1,\n NetworkStakeStepRewardService,\n StepIdentity,\n StepIdentityString,\n} from '@xyo-network/xl1-sdk'\nimport {\n AbstractCreatableProvider,\n creatableProvider, NetworkStakeStepRewardViewerMoniker,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BaseServiceParams } from '../model/index.ts'\n\nexport interface BaseNetworkStakeStepRewardServiceParams extends BaseServiceParams {\n chainArchivist: ReadArchivist\n}\n\n@creatableProvider()\nexport class BaseNetworkStakeStepRewardService extends\n AbstractCreatableProvider<BaseNetworkStakeStepRewardServiceParams> implements NetworkStakeStepRewardService {\n static readonly connectionTypes = [] as const\n static readonly defaultMoniker = NetworkStakeStepRewardViewerMoniker\n static readonly dependencies = []\n static readonly monikers = [NetworkStakeStepRewardViewerMoniker]\n override moniker = BaseNetworkStakeStepRewardService.defaultMoniker\n\n networkStakeStepRewardAddressHistory(_address: Address): Promisable<Record<Address, AttoXL1>> {\n throw new Error('Method [networkStakeStepRewardAddressHistory] not implemented.')\n }\n\n networkStakeStepRewardAddressReward(_context: StepIdentity, _address: Address): Promisable<Record<Address, AttoXL1>> {\n throw new Error('Method [networkStakeStepRewardAddressReward] not implemented.')\n }\n\n networkStakeStepRewardAddressShare(_context: StepIdentity, _address: Address): Promisable<[bigint, bigint]> {\n throw new Error('Method [networkStakeStepRewardAddressShare] not implemented.')\n }\n\n networkStakeStepRewardClaimedByAddress(_address: Address): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardClaimedByAddress] not implemented.')\n }\n\n networkStakeStepRewardForPosition(_position: number, _range: [number, number]): Promisable<[AttoXL1, AttoXL1]> {\n throw new Error('Method [networkStakeStepRewardForPosition] not implemented.')\n }\n\n networkStakeStepRewardForStep(_context: StepIdentity): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardForStep] not implemented.')\n }\n\n networkStakeStepRewardForStepForPosition(_context: StepIdentity, _position: number): Promisable<[AttoXL1, AttoXL1]> {\n throw new Error('Method [networkStakeStepRewardForStepForPosition] not implemented.')\n }\n\n networkStakeStepRewardPoolRewards(_context: StepIdentity): Promisable<Record<Address, AttoXL1>> {\n throw new Error('Method [networkStakeStepRewardPoolRewards] not implemented.')\n }\n\n networkStakeStepRewardPoolShares(_context: StepIdentity): Promisable<Record<Address, bigint>> {\n throw new Error('Method [networkStakeStepRewardPoolShares] not implemented.')\n }\n\n networkStakeStepRewardPositionWeight(_context: StepIdentity, _position: number): Promisable<bigint> {\n throw new Error('Method [networkStakeStepRewardPositionWeight] not implemented.')\n }\n\n networkStakeStepRewardPotentialPositionLoss(_context: StepIdentity, _position: number): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardPotentialPositionLoss] not implemented.')\n }\n\n networkStakeStepRewardRandomizer(_context: StepIdentity): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardRandomizer] not implemented.')\n }\n\n networkStakeStepRewardStakerCount(_context: StepIdentity): Promisable<number> {\n throw new Error('Method [networkStakeStepRewardStakerCount] not implemented.')\n }\n\n networkStakeStepRewardUnclaimedByAddress(_address: Address): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardUnclaimedByAddress] not implemented.')\n }\n\n networkStakeStepRewardWeightForAddress(_context: StepIdentity, _address: Address): Promisable<bigint> {\n throw new Error('Method [networkStakeStepRewardWeightForAddress] not implemented.')\n }\n\n networkStakeStepRewardsForPosition(_position: number, _range: [number, number]): Promisable<Record<StepIdentityString, [AttoXL1, AttoXL1]>> {\n throw new Error('Method [networkStakeStepRewardsForPosition] not implemented.')\n }\n\n networkStakeStepRewardsForRange(_range: [number, number]): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardsForRange] not implemented.')\n }\n\n networkStakeStepRewardsForStepLevel(_stepLevel: number, _range: [number, number]): Promisable<AttoXL1> {\n throw new Error('Method [networkStakeStepRewardsForStepLevel] not implemented.')\n }\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport { isDefined } from '@ariestools/sdk'\nimport type { WithHashMeta, XyoAddress } from '@xyo-network/sdk'\nimport type { BlockBoundWitness } from '@xyo-network/xl1-sdk'\n\n/**\n * Which of a producer's own pending candidates a new proposal at this height supersedes.\n *\n * Matching on the parent as well as the height is the guard that matters. Two candidates at one\n * height built on different parents are not a re-proposal, they are competing branches, and\n * stamping a link across them would assert a supersession that never happened \u2014 turning an\n * honest producer's block into evidence against it.\n *\n * When several of its own candidates are already in the pool, the tip of the supersedes chain is\n * the one to point at: the tip is the candidate nothing else has replaced, so a third proposal\n * links to the second rather than reaching back past it and leaving the second orphaned.\n * @param candidates Pending candidates visible to this producer\n * @param address The producer's own signing address\n * @param block The height being proposed\n * @param previous The parent this proposal builds on\n * @returns The signed data hash to supersede, or undefined when there is nothing to link\n */\nexport function selectSupersededCandidate(\n candidates: WithHashMeta<BlockBoundWitness>[],\n address: XyoAddress,\n block: number,\n previous: Hash,\n): Hash | undefined {\n const own = candidates.filter(candidate => candidate.block === block\n && candidate.previous === previous\n && candidate.addresses.includes(address))\n if (own.length === 0) return undefined\n const superseded = new Set(own.map(candidate => candidate.supersedes).filter(isDefined))\n return (own.find(candidate => !superseded.has(candidate._dataHash)) ?? own[0])._dataHash\n}\n", "import type {\n Address, Hash, Promisable,\n} from '@ariestools/sdk'\nimport {\n asAddress,\n assertEx, hexToBigInt, isDefined, toAddress,\n} from '@ariestools/sdk'\nimport type {\n AccountInstance,\n ArchivistInstance, WithHashMeta, XyoAddress,\n} from '@xyo-network/sdk'\nimport {\n MemoryArchivist,\n PayloadBuilder,\n} from '@xyo-network/sdk'\nimport type {\n AccountBalanceViewer, AllowedBlockPayload, BlockBoundWitness,\n BlockNumberPayload, BlockRewardViewer, BlockRunner, BlockValidationViewer, ChainId, ChainParamsViewer,\n ChainStakeIntent, CreatableProviderParams,\n DeadLetterQueueRunner,\n FinalizationViewer,\n HydratedBlockStateValidationFunction, HydratedBlockValidationError, MempoolViewer,\n SignedBlockBoundWitnessWithHashMeta,\n SignedHydratedBlockWithHashMeta, SignedHydratedTransactionWithHashMeta,\n TimePayload, TimeSyncViewer, Transfer,\n} from '@xyo-network/xl1-sdk'\nimport {\n AbstractCreatableProvider, AccountBalanceViewerMoniker, asBlockBoundWitness, AttoXL1,\n BlockNumberSchema, BlockRejectionSchema, BlockRewardViewerMoniker, BlockRunnerMoniker,\n BlockValidationViewerMoniker, ChainParamsViewerMoniker, connectArchivist, creatableProvider, createDeclarationIntent,\n DeadLetterQueueRunnerMoniker, defaultRewardRatio,\n FinalizationViewerMoniker, isRuleActiveAt, isSignedHydratedBlockWithHashMeta, isTransferPayload, MempoolViewerMoniker,\n REJECTED_TRANSACTIONS_ARCHIVIST_ROLE,\n TimeSyncViewerMoniker,\n TransactionRejectionSchema, XYO_STEP_REWARD_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BlockRewardDiviner } from '#modules'\nimport { FixedPercentageBlockRewardDiviner, FixedPercentageBlockRewardDivinerConfigSchema } from '#modules'\nimport { buildNextBlock } from '#protocol'\n\nimport { generateTransactionFeeTransfers } from './generateTransactionFeeTransfers.ts'\nimport type { OffendingTxReason } from './identifyOffendingTransactions.ts'\nimport { identifyOffendingTransactions } from './identifyOffendingTransactions.ts'\nimport { producerTuningFromConfig } from './producerTuning.ts'\nimport { selectSupersededCandidate } from './selectSupersededCandidate.ts'\n\n/** Why and at which build height a transaction was excluded from future candidates. */\ninterface ExcludedTransactionEntry {\n excludedAtBlock: number\n reason: OffendingTxReason\n}\n\n/**\n * The default block size for a block\n */\nexport const DEFAULT_BLOCK_SIZE = 10\n\n/**\n * Default minimum age (ms) of the head before a producer emits a transaction-less heartbeat\n * block. Five minutes keeps a quiet chain visibly alive without accumulating meaningful storage\n * or block-reward drift. Finalizers use the same default as the floor for how fast they will\n * finalize heartbeat blocks.\n */\nexport const DEFAULT_HEARTBEAT_INTERVAL = 300_000\n\n/**\n * The amount of time for which a producer will restake their intent\n */\nexport const XYO_PRODUCER_REDECLARATION_DURATION = 100\n\n/**\n * The number of blocks within which a producer will redeclare\n * their intent to produce blocks\n */\nexport const XYO_PRODUCER_REDECLARATION_WINDOW = 100\n\nexport interface SimpleBlockRunnerParams extends CreatableProviderParams {\n /** Explicit signing account (deprecated path) \u2014 defaults to the context signer registry. */\n account?: AccountInstance\n disableIntentRedeclaration?: boolean\n heartbeatInterval?: number\n rejectedTransactionsArchivist?: ArchivistInstance\n /** Defaults to `config.rewardAddress` (producer config), then the signing account's address. */\n rewardAddress?: Address\n /**\n * When `true` (default), `filterByFunded` enforces the same cumulative-outflow\n * vs balance rule the post-submit block validator uses\n * (`base + priority + gasLimit + transfer amounts`). Setting this to `false`\n * is only appropriate for unit-style tests that exercise block-production\n * mechanics with synthetic unfunded senders and don't model balances.\n */\n validateBalances?: boolean\n validateHydratedBlockState?: HydratedBlockStateValidationFunction\n}\n\n@creatableProvider()\nexport class SimpleBlockRunner extends AbstractCreatableProvider<SimpleBlockRunnerParams> implements BlockRunner {\n /**\n * Minimum time between build attempts after a fully-rejected build (validation exhausted with\n * no attributable transaction to exclude). Such a build fails identically until external state\n * changes, so retrying at the production tick rate only churns build \u2192 validate \u2192 DLQ.\n */\n static readonly RejectedBuildBackoffMs = 1000\n\n static readonly connectionTypes = ['lmdb', 'mongo', 'memory'] as const\n static readonly defaultMoniker = BlockRunnerMoniker\n static readonly dependencies = [\n AccountBalanceViewerMoniker,\n BlockRewardViewerMoniker,\n BlockValidationViewerMoniker,\n FinalizationViewerMoniker,\n MempoolViewerMoniker,\n TimeSyncViewerMoniker,\n ]\n\n static readonly monikers = [BlockRunnerMoniker]\n\n static readonly surface = 'node' as const\n\n moniker = SimpleBlockRunner.defaultMoniker\n\n protected _blockRewardDiviner?: BlockRewardDiviner\n protected _deadLetterQueueRunner?: DeadLetterQueueRunner\n // Reason-scoped: deterministic ('tx-invalid') exclusions last the process lifetime, while\n // head-relative ('block-balance') exclusions evict once the head advances past the height they\n // were recorded at \u2014 a sender underfunded at head H may be funded at H+k, and permanent\n // exclusion would censor them. TODO(producer-exclusion-set): 'tx-invalid' entries are still\n // uncapped; add FIFO eviction if memory grows in long-running producers.\n protected _excludedTransactionHashes = new Map<Hash, ExcludedTransactionEntry>()\n protected _lastRedeclarationBlock?: number\n protected _rejectedTransactionsArchivist?: ArchivistInstance\n\n private _account?: AccountInstance\n private _accountBalanceViewer?: AccountBalanceViewer\n private _address?: Address\n private _blockRewardViewer?: BlockRewardViewer\n private _blockValidationViewer?: BlockValidationViewer\n private _chainParamsViewer?: ChainParamsViewer\n private _finalizationViewer?: FinalizationViewer\n private _lastRejectedBuildAt = 0\n /** Cache of the last candidate this runner signed; the mempool is the source of truth. */\n private _lastSignedCandidate?: { block: number; hash: Hash; previous: Hash }\n private _mempoolViewer?: MempoolViewer\n private _rewardAddress?: Address\n private _timeSyncViewer?: TimeSyncViewer\n\n /**\n * The default block size for a block\n */\n static get DefaultBlockSize(): number {\n return DEFAULT_BLOCK_SIZE\n }\n\n /**\n * The amount of time for which the producer will redeclare\n * their intent to continue producing blocks\n */\n static get RedeclarationDuration(): number {\n return XYO_PRODUCER_REDECLARATION_DURATION\n }\n\n /**\n * The number of blocks within which the producer will redeclare\n * their intent to continue producing blocks\n */\n static get RedeclarationWindow(): number {\n return XYO_PRODUCER_REDECLARATION_WINDOW\n }\n\n protected get account() {\n return this._account!\n }\n\n protected get accountBalanceViewer() {\n return this._accountBalanceViewer!\n }\n\n protected get address() {\n return this._address!\n }\n\n protected get blockRewardViewer() {\n return this._blockRewardViewer!\n }\n\n protected get blockValidationViewer() {\n return this._blockValidationViewer!\n }\n\n protected get finalizationViewer() {\n return this._finalizationViewer!\n }\n\n protected get heartbeatInterval() {\n return this.params.heartbeatInterval ?? this.producerTuning.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL\n }\n\n protected get mempoolViewer() {\n return this._mempoolViewer!\n }\n\n protected get producerTuning() {\n return producerTuningFromConfig(this.config)\n }\n\n // protected get pendingTransactionsService() {\n // return assertEx(this.params.pendingTransactionsService, () => 'Missing pendingTransactionsService')\n // }\n\n protected get rejectedTransactionsArchivist() {\n return this._rejectedTransactionsArchivist!\n }\n\n protected get rewardAddress(): Address {\n return this._rewardAddress!\n }\n\n // protected get stakeIntentService(): StakeIntentService {\n // return assertEx(this.params.stakeIntentService, () => 'No StakeIntentService provided')\n // }\n\n protected get timeSyncViewer(): TimeSyncViewer {\n return this._timeSyncViewer!\n }\n\n // protected get validateHydratedBlockState() {\n // return assertEx(this.params.validateHydratedBlockState, () => 'validateHydratedBlockState is required')\n // }\n\n override async createHandler() {\n const boundConnection = this.boundConnection\n this._rejectedTransactionsArchivist = this.params.rejectedTransactionsArchivist\n ?? (boundConnection\n ? await connectArchivist(boundConnection, { name: REJECTED_TRANSACTIONS_ARCHIVIST_ROLE })\n : await MemoryArchivist.create())\n this._account = assertEx(\n this.params.account ?? this.contextAccount,\n () => 'Account is required \u2014 inject params.account or register a context signer',\n )\n this._address = toAddress(this.account.address)\n this._accountBalanceViewer = await this.locateAndCreate<AccountBalanceViewer>(AccountBalanceViewerMoniker)\n this._blockRewardViewer = await this.locateAndCreate<BlockRewardViewer>(BlockRewardViewerMoniker)\n this._blockValidationViewer = await this.locator.getInstance<BlockValidationViewer>(BlockValidationViewerMoniker)\n this._finalizationViewer = await this.locateAndCreate<FinalizationViewer>(FinalizationViewerMoniker)\n this._mempoolViewer = await this.locateAndCreate<MempoolViewer>(MempoolViewerMoniker)\n this._rewardAddress = asAddress(this.params.rewardAddress ?? this.producerTuning.rewardAddress ?? this.account.address, true)\n this._timeSyncViewer = await this.locateAndCreate<TimeSyncViewer>(TimeSyncViewerMoniker)\n this._deadLetterQueueRunner = await this.locator.tryGetInstance<DeadLetterQueueRunner>(DeadLetterQueueRunnerMoniker)\n // soft: a chain with no register never stamps supersedes, which is what keeps this release\n // emission-identical to the one before it until an activation height says otherwise\n this._chainParamsViewer = await this.locator.tryGetInstance<ChainParamsViewer>(ChainParamsViewerMoniker)\n }\n\n async next(head: WithHashMeta<BlockBoundWitness>): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n // If the block is for another chain, ignore\n // if (head.chain !== this.chainId) return\n // const leadersStart = Date.now()\n // const leaders = await this.electionService.getCreatorCommitteeForNextBlock(head)\n // const leadersDuration = Date.now() - leadersStart\n // if (leadersDuration > 100) {\n // this.logger?.warn(`[Slow] Fetched leaders in ${leadersDuration}ms: ${leaders.map(l => l.slice(0, 6)).join(', ')}`)\n // }\n // TODO: Should we propose block if creator committee is empty?\n // TODO: Handle the case where we're not the 1st leader but they're not responding\n // at a higher level than here as that's a network issue\n // if (!leaders.includes(this.address)) return\n return await this.proposeNextValidBlock(head)\n }\n\n async produceNextBlock(head: SignedBlockBoundWitnessWithHashMeta, force: true): Promise<SignedHydratedBlockWithHashMeta>\n async produceNextBlock(head: SignedBlockBoundWitnessWithHashMeta, force?: false): Promise<SignedHydratedBlockWithHashMeta | undefined>\n async produceNextBlock(head: SignedBlockBoundWitnessWithHashMeta, force?: boolean): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n // assertEx(head.chain === this.chainId, () => 'Block chain ID does not match')\n const result = await this.proposeNextValidBlock(head)\n return force === true ? assertEx(result, () => 'Failed to produce next block') : result\n }\n\n protected async getBlockRewardTransfers(block: number): Promise<Transfer[]> {\n this._blockRewardDiviner ??= await FixedPercentageBlockRewardDiviner.create({\n account: 'random',\n blockRewardViewer: this.blockRewardViewer,\n config: {\n rewardAddress: this.rewardAddress,\n rewardPercentageRatio: defaultRewardRatio,\n schema: FixedPercentageBlockRewardDivinerConfigSchema,\n },\n })\n\n const blockIdBuilder = new PayloadBuilder<BlockNumberPayload>({ schema: BlockNumberSchema })\n const blockId = blockIdBuilder.fields({ block }).build()\n const rewards = await this._blockRewardDiviner.divine([blockId])\n return rewards as Transfer[]\n }\n\n /**\n * Handles the producer redeclaration logic\n * @param head The current head block\n * @returns chain stake intent for the producer redeclaration, or undefined if no redeclaration is needed\n */\n protected getProducerRedeclaration(head: WithHashMeta<BlockBoundWitness>): Promisable<ChainStakeIntent | undefined> {\n if ((this.params.disableIntentRedeclaration ?? this.producerTuning.disableIntentRedeclaration) === true) return\n const currentBlock = head.block\n // Only redeclare when the previous declaration has expired\n if (isDefined(this._lastRedeclarationBlock)) {\n const lastDeclarationExpiry = this._lastRedeclarationBlock + SimpleBlockRunner.RedeclarationDuration\n if (currentBlock < lastDeclarationExpiry) return\n }\n this._lastRedeclarationBlock = currentBlock\n return createDeclarationIntent(this.address, 'producer', currentBlock, currentBlock + SimpleBlockRunner.RedeclarationDuration)\n }\n\n // `validateBalances` resolves from (a) the explicit method argument when\n // passed, (b) the constructor `params.validateBalances`, or (c) `true`.\n // True is the safe default: `filterByFunded` then enforces the same\n // cumulative-outflow rule the post-submit block validator uses\n // (`base + priority + gasLimit + transfer amounts`). With the old default\n // of `false`, a tx whose declared gasLimit exceeded the sender's balance\n // would pass the producer's filter, get submitted, and then land in\n // `rejected_blocks` \u2014 silently wedging the chain because the producer's\n // `_lastProducedBlock` cache muted retries. Reproduced in the\n // api-local-mongodb-beta test rig.\n protected async proposeNextValidBlock(head: WithHashMeta<BlockBoundWitness>, validateBalances?: boolean, force = false) {\n const shouldValidateBalances = validateBalances ?? this.params.validateBalances ?? true\n return await this.spanAsync('proposeNextValidBlock', async () => {\n try {\n // A build the validator fully rejected (no attributable transaction to exclude) will\n // fail identically until external state changes \u2014 new transactions, head movement, or a\n // mempool window sync. Without a floor between attempts, a production tick of 50ms churns\n // build \u2192 validate \u2192 DLQ at 20Hz. Explicitly forced builds bypass the floor; the 30s\n // stale-head resubmission arrives long after it has expired either way.\n if (this.isWithinRejectedBuildBackoff(force)) return\n const { block: previousBlock } = assertEx(asBlockBoundWitness(head), () => 'Invalid head block')\n const nextBlock = previousBlock + 1\n const chainId = await this.finalizationViewer.chainId()\n const pendingTransactionsRaw = await this.mempoolViewer.pendingTransactions({ limit: SimpleBlockRunner.DefaultBlockSize })\n this.evictStaleExclusions(previousBlock)\n const pendingTransactions = pendingTransactionsRaw.filter(tx => !this._excludedTransactionHashes.has(tx[0]._hash))\n const nextBlockTransactions = await this.rejectWrongChainTransactions(pendingTransactions, chainId)\n\n this.logger?.log(`Pending Tx Count ${nextBlockTransactions.length}`)\n\n const nonTxPayloads: AllowedBlockPayload[] = []\n\n // Calculate the optional producer redeclaration and add it if necessary\n const producerRedeclarationPayload = await this.getProducerRedeclaration(head)\n if (producerRedeclarationPayload) nonTxPayloads.push(producerRedeclarationPayload)\n\n // If there are no transactions, no payloads and no heartbeat required, we don't need to create a block\n if (nextBlockTransactions.length === 0 && !this.heartbeatRequired(head) && !force) return\n\n // Calculate the optional block reward transfer and add if necessary\n const rewardTransferPayloads = await this.getBlockRewardTransfers(nextBlock)\n nonTxPayloads.push(...rewardTransferPayloads)\n\n const transactionTransfers = await generateTransactionFeeTransfers(this.address, nextBlockTransactions)\n const timePayload = await this.generateTimePayload()\n\n const [initialFundedTransactions, initialFundedTransfers]\n = await this.filterByFunded(head, nextBlockTransactions, transactionTransfers, shouldValidateBalances)\n\n const stepRewardBalances = await this.accountBalanceViewer.accountBalances([XYO_STEP_REWARD_ADDRESS])\n const stepRewardPoolBalance = (stepRewardBalances as Record<string, AttoXL1>)[String(XYO_STEP_REWARD_ADDRESS)]\n\n const { block: proposedBlock, errors: proposedErrors } = await this.runBuildValidateRetryLoop({\n head,\n chainId,\n stepRewardPoolBalance,\n nonTxPayloads,\n timePayload,\n initialFundedTransactions,\n initialFundedTransfers,\n })\n return await this.commitProposedBlock(proposedBlock, proposedErrors)\n } catch (error) {\n this.logger?.error(`Error proposing next valid block: ${(error as Error).message}`)\n throw error\n }\n }, this.context)\n }\n\n private addTransferOutflow(outflow: bigint, payload: Transfer): bigint {\n let result = outflow\n for (const [to, amount] of Object.entries(payload.transfers)) {\n if (to === payload.from) continue\n result += hexToBigInt((amount ?? '00'))\n }\n return result\n }\n\n private async commitProposedBlock(\n proposedBlock: SignedHydratedBlockWithHashMeta | undefined,\n proposedErrors: HydratedBlockValidationError[],\n ): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n // The type guard alone is not a validity check \u2014 every built block is structurally a\n // signed hydrated block, including one the retry loop exhausted on. Only a block the\n // loop returned WITHOUT errors passed validation; anything else must not be published.\n if (proposedErrors.length === 0 && isSignedHydratedBlockWithHashMeta(proposedBlock)) {\n this._lastRejectedBuildAt = 0\n // Submission is the producer's responsibility (`ProducerActor.produceBlock`)\n // \u2014 SimpleBlockRunner just builds and validates. Previously this site\n // also called `mempoolRunner.submitBlocks`, double-submitting the\n // same block. The second submit at the producer always failed with\n // \"archivist accepted 0 of 1\" because the inner one had already\n // landed. Removing the inner submit eliminates that false positive\n // and means SimpleBlockRunner no longer needs a MempoolRunner\n // dependency at all.\n return proposedBlock\n }\n if (proposedBlock !== undefined) {\n this._lastRejectedBuildAt = Date.now()\n await this.rejectExhaustedBlock(proposedBlock, proposedErrors)\n }\n }\n\n /**\n * Compute the cumulative outflow a single tx would charge to its `from`\n * address, using the same rule as `BlockCumulativeBalanceValidator`:\n * `outflow = base + priority + gasLimit + sum(transfer amounts to addresses\n * other than from)`. Mirroring the validator exactly here ensures the\n * producer doesn't include a tx that the post-submit block validator will\n * reject, which would otherwise wedge the chain because the producer's\n * `_lastProducedBlock` cache mutes retries.\n */\n private computeTransactionOutflow(tx: SignedHydratedTransactionWithHashMeta): bigint {\n const [bw, payloads] = tx\n const {\n base, gasLimit, priority,\n } = bw.fees\n let outflow = hexToBigInt(base) + hexToBigInt(priority) + hexToBigInt(gasLimit)\n const txPayloadHashes = new Set(bw.payload_hashes)\n for (const payload of payloads) {\n if (!txPayloadHashes.has(payload._hash)) continue\n if (!isTransferPayload(payload)) continue\n if (payload.from !== bw.from) continue\n outflow = this.addTransferOutflow(outflow, payload)\n }\n return outflow\n }\n\n /**\n * Drops head-relative ('block-balance') exclusions once the head has advanced past the height\n * they were recorded at \u2014 the sender's funding is re-evaluated by filterByFunded at the new\n * head. Deterministic ('tx-invalid') exclusions are kept for the process lifetime.\n */\n private evictStaleExclusions(headBlock: number): void {\n for (const [hash, entry] of this._excludedTransactionHashes) {\n if (entry.reason === 'block-balance' && headBlock > entry.excludedAtBlock) {\n this._excludedTransactionHashes.delete(hash)\n }\n }\n }\n\n // remove unfunded transactions and block transfers\n private async filterByFunded(\n head: WithHashMeta<BlockBoundWitness>,\n txs: SignedHydratedTransactionWithHashMeta[],\n transfers: Transfer[],\n validateBalances = false,\n ): Promise<[SignedHydratedTransactionWithHashMeta[], Transfer[]]> {\n const fundedTransfers: Transfer[] = []\n const fundedTransactions: SignedHydratedTransactionWithHashMeta[] = []\n // Outflow already committed to this block per sender, plus a per-sender\n // balance cache (balances are read at the fixed parent `head`). Each tx is\n // gated against the sender's REMAINING balance, not the full balance in\n // isolation. Checking each tx independently (the previous behavior) lets two\n // individually-valid transfers from the same sender \u2014 a double-spend across\n // transactions, each \u2264 balance but jointly > balance \u2014 both pass. The block\n // then carries a cumulative outflow the post-submit validator rejects, and\n // the producer wedges (its `_lastProducedBlock` cache mutes retries).\n // Sequential, cumulative gating includes only the first transfer that fits\n // and drops the rest; the dropped tx stays pending and is pruned once the\n // included one lands and the sender can no longer cover it.\n const committedOutflow = new Map<XyoAddress, bigint>()\n const balanceCache = new Map<XyoAddress, bigint>()\n for (const tx of txs) {\n const transfer: Transfer | undefined = transfers.find(candidate => candidate.from === tx[0].from)\n if (!transfer) continue\n if (!validateBalances) {\n fundedTransfers.push(transfer)\n fundedTransactions.push(tx)\n continue\n }\n const { from } = transfer\n let balance = balanceCache.get(from)\n if (balance === undefined) {\n const accountBalances = await this.accountBalanceViewer.accountBalances([from])\n balance = (accountBalances as Record<string, bigint>)[String(from)] ?? AttoXL1(0n)\n balanceCache.set(from, balance)\n }\n // Mirror the post-submit block validator's cumulative-outflow rule\n // (base + priority + gasLimit + transfer amounts) against the running\n // total for this sender, so the producer never includes a tx the\n // validator will reject.\n const projectedOutflow = (committedOutflow.get(from) ?? 0n) + this.computeTransactionOutflow(tx)\n if (balance >= projectedOutflow) {\n committedOutflow.set(from, projectedOutflow)\n fundedTransfers.push(transfer)\n fundedTransactions.push(tx)\n } else {\n this.logger?.debug(\n `filterByFunded: dropping tx ${tx[0]._hash} from ${from} \u2014 cumulative outflow ${projectedOutflow} > balance ${balance}`,\n )\n }\n }\n return [fundedTransactions, fundedTransfers]\n }\n\n private async generateTimePayload() {\n const timeStart = Date.now()\n const timePayload = await this.timeSyncViewer.currentTimePayload()\n const timeDuration = Date.now() - timeStart\n if (timeDuration > 100) {\n this.logger?.warn(`[Slow] Generated time payload in ${timeDuration}ms`)\n }\n return timePayload\n }\n\n /**\n * Check if a heartbeat block is required based on network activity.\n * @param head The current head block\n * @returns True if a heartbeat is required, false otherwise\n */\n private heartbeatRequired(head: WithHashMeta<BlockBoundWitness>): boolean {\n const epoch = head.$epoch\n if (isDefined(epoch) && Date.now() - epoch > this.heartbeatInterval) {\n return true\n }\n return false\n }\n\n private isWithinRejectedBuildBackoff(force: boolean): boolean {\n if (force || Date.now() - this._lastRejectedBuildAt >= SimpleBlockRunner.RejectedBuildBackoffMs) return false\n this.logger?.debug('Skipping block production during rejected-build backoff')\n return true\n }\n\n /**\n * The hash of this producer's own earlier candidate at the same height and parent, if any.\n *\n * The parent is part of the match on purpose. Two candidates at one height built on different\n * parents are not a re-proposal, they are different branches, and linking across them would\n * assert a supersession that never happened.\n *\n * Memory is only a cache. A restart wipes it while the pool still holds the prior candidate, so\n * the pool is consulted whenever memory misses. Following the chain to its tip keeps a third\n * proposal pointing at the second rather than back at the first.\n * @param block The height being proposed\n * @param previous The parent this proposal builds on\n * @returns The prior candidate's signed data hash, or undefined when there is none\n */\n private async previousOwnCandidateHash(block: number, previous: Hash): Promise<Hash | undefined> {\n const cached = this._lastSignedCandidate\n if (cached?.block === block && cached.previous === previous) return cached.hash\n const candidates = (await this.mempoolViewer.pendingBlocks()).map(([candidate]) => candidate)\n return selectSupersededCandidate(candidates, this.address, block, previous)\n }\n\n private async rejectExhaustedBlock(\n block: SignedHydratedBlockWithHashMeta,\n errors: HydratedBlockValidationError[],\n ): Promise<void> {\n this.logger?.warn(`Validation of produced block failed: ${errors.at(0)?.message}`)\n if (this._deadLetterQueueRunner) {\n const rejectionErrors = errors.map(e => ({\n hash: block[0]._hash, name: 'BlockValidationError', message: String(e.message ?? e),\n }))\n await this._deadLetterQueueRunner.rejectBlock({\n schema: BlockRejectionSchema, block, errors: rejectionErrors, rejector: 'producer',\n })\n } else {\n await this.rejectedTransactionsArchivist.insert(block[1])\n }\n }\n\n // Partition pending transactions by chain-ID match; route mismatches to the transaction DLQ.\n private async rejectWrongChainTransactions(\n transactions: SignedHydratedTransactionWithHashMeta[],\n chainId: ChainId,\n ): Promise<SignedHydratedTransactionWithHashMeta[]> {\n const localChain = chainId.toLowerCase()\n const matched: SignedHydratedTransactionWithHashMeta[] = []\n const mismatched: SignedHydratedTransactionWithHashMeta[] = []\n for (const tx of transactions) {\n if (tx[0].chain.toLowerCase() === localChain) {\n matched.push(tx)\n } else {\n mismatched.push(tx)\n }\n }\n if (mismatched.length > 0) {\n this.logger?.warn(`Rejecting ${mismatched.length} transaction(s) targeting non-local chain`)\n const dlq = this._deadLetterQueueRunner\n await (dlq\n ? Promise.all(mismatched.map(tx => dlq.rejectTransaction({\n schema: TransactionRejectionSchema,\n transaction: tx,\n errors: [{\n hash: tx[0]._hash,\n name: 'TransactionChainMismatch',\n message: `Transaction chain ${tx[0].chain} does not match local chain ${localChain}`,\n }],\n rejector: 'producer',\n })))\n : this.rejectedTransactionsArchivist.insert(mismatched.map(tx => tx[0])))\n }\n return matched\n }\n\n /**\n * The candidate this proposal supersedes, or undefined when nothing should be stamped.\n *\n * Identity is the signed data hash rather than the storage hash, because that is what an\n * observer recomputes when deciding whether two candidates are the same block \u2014 client meta\n * such as `$epoch` must not be able to make one candidate look like two.\n *\n * With no register wired, or with the field unactivated, this never stamps. That is what keeps\n * a producer running this build emission-identical to one running the release before it, which\n * the rollout depends on: stamping before the fleet has upgraded would partition validation.\n * @param head The block being built on\n * @returns The superseded candidate's hash, or undefined\n */\n private async resolveSupersedes(head: WithHashMeta<BlockBoundWitness>): Promise<Hash | undefined> {\n const viewer = this._chainParamsViewer\n if (viewer === undefined) return undefined\n const params = await viewer.tryCurrentParams()\n const block = head.block + 1\n if (params === undefined || !isRuleActiveAt(params, 'supersedes-field', block)) return undefined\n return await this.previousOwnCandidateHash(block, head._hash)\n }\n\n private async runBuildValidateRetryLoop(args: {\n chainId: ChainId\n head: WithHashMeta<BlockBoundWitness>\n initialFundedTransactions: SignedHydratedTransactionWithHashMeta[]\n initialFundedTransfers: Transfer[]\n nonTxPayloads: AllowedBlockPayload[]\n stepRewardPoolBalance: AttoXL1\n timePayload: TimePayload\n }): Promise<{\n block: SignedHydratedBlockWithHashMeta | undefined\n errors: HydratedBlockValidationError[]\n }> {\n const {\n chainId, head, initialFundedTransactions, initialFundedTransfers,\n nonTxPayloads, stepRewardPoolBalance, timePayload,\n } = args\n const supersedes = await this.resolveSupersedes(head)\n const maxAttempts = Math.max(1, initialFundedTransactions.length)\n let candidateTransactions = initialFundedTransactions\n let candidateTransfers = initialFundedTransfers\n let lastBlock: SignedHydratedBlockWithHashMeta | undefined\n let lastErrors: HydratedBlockValidationError[] = []\n\n for (let attempt = 0; attempt <= maxAttempts; attempt++) {\n const blockPayloads = [...nonTxPayloads, ...candidateTransfers, timePayload]\n this.logger?.info(`Building block ${head.block + 1}${attempt > 0 ? ` (retry ${attempt})` : ''}`)\n lastBlock = await buildNextBlock(\n head,\n candidateTransactions,\n blockPayloads,\n [this.account],\n XYO_STEP_REWARD_ADDRESS,\n stepRewardPoolBalance,\n undefined,\n chainId,\n supersedes,\n )\n // Run the same value+state validation the finalizer and mempool sweep will apply. A\n // `{head}`-only config selects no validators at all, which made this retry loop dead code:\n // an invalid candidate was published anyway, silently rejected downstream, and the producer\n // muted until its stale-head resubmission threshold.\n const validated = await this.blockValidationViewer.validateBlock(lastBlock, {\n value: true, state: true, head: head._hash,\n })\n if (isSignedHydratedBlockWithHashMeta(validated)) {\n // recorded only for a candidate that actually stands, so a later proposal never claims to\n // supersede one that was built, rejected, and never seen by anyone\n this._lastSignedCandidate = {\n block: validated[0].block, hash: validated[0]._dataHash, previous: head._hash,\n }\n return { block: validated, errors: [] }\n }\n lastErrors = validated\n if (attempt === maxAttempts) break\n const { offendingHashes, reason } = await identifyOffendingTransactions({ candidateTransactions, errors: validated })\n if (offendingHashes.length === 0 || reason === 'unknown') break\n for (const offendingHash of offendingHashes) {\n this._excludedTransactionHashes.set(offendingHash, { excludedAtBlock: head.block, reason })\n }\n const offendingSet = new Set<Hash>(offendingHashes)\n candidateTransactions = candidateTransactions.filter(tx => !offendingSet.has(tx[0]._hash))\n const remainingFromAddresses = new Set<XyoAddress>(candidateTransactions.map(tx => tx[0].from))\n const feeTransfers = await generateTransactionFeeTransfers(this.address, candidateTransactions)\n candidateTransfers = feeTransfers.filter(t => remainingFromAddresses.has(t.from))\n this.logger?.warn(`Block validation failed (attempt ${attempt + 1}); excluded ${offendingHashes.length} tx(s), retrying`)\n }\n return { block: lastBlock, errors: lastErrors }\n }\n}\n", "import { assertEx, hexFromBigInt } from '@ariestools/sdk'\nimport type { XyoAddress } from '@xyo-network/sdk'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n SignedHydratedTransaction,\n Transfer,\n XL1,\n} from '@xyo-network/xl1-sdk'\nimport {\n HydratedTransactionWrapper,\n transactionRequiredGas, TransferSchema, XYO_ZERO_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nexport async function generateTransactionFeeTransfers(address: XyoAddress, transactions: SignedHydratedTransaction[]): Promise<Transfer[]> {\n const txs = await Promise.all(transactions.map(async (tx) => {\n return HydratedTransactionWrapper.parse([await PayloadBuilder.addStorageMeta(tx[0]), await PayloadBuilder.addStorageMeta(tx[1])])\n }))\n\n // merge transactions with the same from address\n const txBaseFeeCosts: Record<XyoAddress, bigint> = {}\n for (const tx of txs) {\n txBaseFeeCosts[tx.boundWitness.from] = (txBaseFeeCosts[tx.boundWitness.from] ?? 0n)\n + tx.fees.base\n }\n\n const txGasCosts: Record<XyoAddress, bigint> = {}\n for (const tx of txs) {\n const requiredGas = transactionRequiredGas(tx.data)\n const totalGasCost = requiredGas * tx.fees.gasPrice\n txGasCosts[tx.boundWitness.from] = (txBaseFeeCosts[tx.boundWitness.from] ?? 0n)\n + totalGasCost\n }\n\n // generate actual Transfer Payloads & burn the base fee\n const payloads = (Object.entries(txBaseFeeCosts) as [XyoAddress, XL1][]).map(([from, amount]) => {\n const payload: Transfer = {\n schema: TransferSchema,\n epoch: Date.now(),\n from,\n transfers: Object.fromEntries([[String(XYO_ZERO_ADDRESS), hexFromBigInt(amount)]]),\n }\n return payload\n })\n\n // transfer gas cost to producer\n for (const [from, amount] of Object.entries(txGasCosts)) {\n // every gas from should also be a base fee from\n const fromPayload = assertEx(payloads.find(p => p.from === from), () => 'from payload not found')\n fromPayload.transfers[address] = hexFromBigInt(amount)\n }\n\n return payloads\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport type { HydratedBlockValidationError, SignedHydratedTransactionWithHashMeta } from '@xyo-network/xl1-sdk'\nimport {\n HydratedTransactionWrapper,\n netBalancesForPayloads,\n transactionRequiredGas,\n} from '@xyo-network/xl1-sdk'\n\nexport type OffendingTxReason = 'block-balance' | 'tx-invalid' | 'unknown'\n\nexport interface OffendingTxResult {\n offendingHashes: Hash[]\n reason: OffendingTxReason\n}\n\ninterface TxScore {\n cost: bigint\n gasPrice: bigint\n}\n\nasync function scoreTransaction(tx: SignedHydratedTransactionWithHashMeta): Promise<TxScore> {\n const wrapper = await HydratedTransactionWrapper.parse(tx)\n const from = wrapper.boundWitness.from\n const gasPrice = wrapper.fees.gasPrice\n const gasCost = transactionRequiredGas(tx) * gasPrice\n const baseCost = wrapper.fees.base\n const netBalances = netBalancesForPayloads({ singletons: {} }, tx[1])\n const fromNet = netBalances[from] ?? 0n\n const transferOut = fromNet < 0n ? -fromNet : 0n\n return { cost: gasCost + baseCost + transferOut, gasPrice }\n}\n\nexport async function identifyOffendingTransactions(args: {\n candidateTransactions: SignedHydratedTransactionWithHashMeta[]\n errors: HydratedBlockValidationError[]\n}): Promise<OffendingTxResult> {\n const { errors, candidateTransactions } = args\n const candidateHashes = new Set<Hash>(candidateTransactions.map(tx => tx[0]._hash))\n\n const txInvalidHashes = new Set<Hash>()\n for (const error of errors) {\n if (candidateHashes.has(error.hash)) txInvalidHashes.add(error.hash)\n const cause = error.cause as undefined | { hash?: Hash }\n if (cause?.hash && candidateHashes.has(cause.hash)) txInvalidHashes.add(cause.hash)\n }\n if (txInvalidHashes.size > 0) {\n return { offendingHashes: [...txInvalidHashes], reason: 'tx-invalid' }\n }\n\n const balanceOffenderHashes = new Set<Hash>()\n for (const error of errors) {\n const offendingHashes = (error as { offendingTransactionHashes?: Hash[] }).offendingTransactionHashes ?? []\n for (const hash of offendingHashes) {\n if (candidateHashes.has(hash)) balanceOffenderHashes.add(hash)\n }\n }\n if (balanceOffenderHashes.size === 0) {\n return { offendingHashes: [], reason: 'unknown' }\n }\n\n const offenders = candidateTransactions.filter(tx => balanceOffenderHashes.has(tx[0]._hash))\n const scored = await Promise.all(offenders.map(async tx => ({ tx, ...(await scoreTransaction(tx)) })))\n scored.sort((a, b) => {\n if (a.cost !== b.cost) return a.cost < b.cost ? 1 : -1\n if (a.gasPrice !== b.gasPrice) return a.gasPrice < b.gasPrice ? -1 : 1\n return a.tx[0]._hash < b.tx[0]._hash ? -1 : 1\n })\n return { offendingHashes: [scored[0].tx[0]._hash], reason: 'block-balance' }\n}\n", "import { z } from 'zod'\n\n/**\n * Producer tuning read from the materialized provider config's `options`\n * (`providerBindings.BlockRunner.options` \u2014 orchestration lifts the producer\n * actor slice there at config load).\n */\nexport const ProducerTuningOptionsZod = z.object({\n disableIntentRedeclaration: z.coerce.boolean().optional(),\n heartbeatInterval: z.coerce.number().optional(),\n rewardAddress: z.string().optional(),\n})\n\n/** Producer tuning fields resolved from provider options. */\nexport type ProducerTuningFields = z.infer<typeof ProducerTuningOptionsZod>\n\n/** Producer tuning from the materialized provider config. */\nexport function producerTuningFromConfig(config: unknown): ProducerTuningFields {\n const options = (config as { options?: Record<string, unknown> }).options ?? {}\n const parsed = ProducerTuningOptionsZod.safeParse(options)\n return parsed.success ? parsed.data : {}\n}\n", "import type { Promisable } from '@ariestools/sdk'\nimport type { ReadArchivist, XyoAddress } from '@xyo-network/sdk'\nimport type { StepIdentity, StepStakeViewer } from '@xyo-network/xl1-sdk'\nimport { AbstractCreatableProvider, StepStakeViewerMoniker } from '@xyo-network/xl1-sdk'\n\nimport type { BaseServiceParams } from '../model/index.ts'\n\nexport interface BaseStepStakeServiceParams extends BaseServiceParams {\n chainArchivist: ReadArchivist\n}\n\nexport abstract class AbstractStepStakeService extends AbstractCreatableProvider<BaseStepStakeServiceParams> implements StepStakeViewer {\n static readonly defaultMoniker = StepStakeViewerMoniker\n static readonly monikers = [StepStakeViewerMoniker]\n override moniker = AbstractStepStakeService.defaultMoniker\n\n stepStake(_step: StepIdentity): Promisable<Record<XyoAddress, bigint>> {\n throw new Error('Method [stepStake] not implemented.')\n }\n\n stepStakeForAddress(_address: XyoAddress, _step: StepIdentity): Promisable<bigint> {\n throw new Error('Method [stepStakeForAddress] not implemented.')\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["AbstractCreatableProvider", "creatableProvider", "AbstractCreatableProvider", "creatableProvider", "assertEx", "AbstractCreatableProvider", "creatableProvider", "AbstractCreatableProvider", "creatableProvider", "isDefined", "assertEx", "isDefined", "toAddress", "PayloadBuilder", "AbstractCreatableProvider", "BlockRejectionSchema", "creatableProvider", "createDeclarationIntent", "isSignedHydratedBlockWithHashMeta", "buildNextBlock", "assertEx", "HydratedTransactionWrapper", "transactionRequiredGas", "AbstractCreatableProvider", "assertEx", "toAddress", "PayloadBuilder", "isDefined", "createDeclarationIntent", "isSignedHydratedBlockWithHashMeta", "BlockRejectionSchema", "buildNextBlock", "creatableProvider", "AbstractCreatableProvider"]
7
7
  }
@@ -24,6 +24,12 @@ export interface ChainHeadSelectorParams extends ChainFinalizerParams {
24
24
  * asked, which is what keeps a node with no stake readers running exactly as it does today.
25
25
  */
26
26
  eligibility?: ProducerEligibilityEvaluator;
27
+ /**
28
+ * Minimum epoch spacing (ms) between transaction-less heartbeat blocks this selector will
29
+ * qualify — a defense against producers heartbeating faster than the network's intended pace.
30
+ * Transaction-carrying candidates are exempt. Undefined disables the check.
31
+ */
32
+ heartbeatInterval?: number;
27
33
  mempoolViewer: MempoolViewer;
28
34
  /**
29
35
  * Minimum number of uncle candidates required before accepting one.
@@ -42,6 +48,7 @@ export declare class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorP
42
48
  protected admission: AdmissionMode;
43
49
  protected allowedProducers?: Address[];
44
50
  protected backoffMs?: number;
51
+ protected heartbeatInterval?: number;
45
52
  protected minCandidates?: number;
46
53
  private _timeSinceLastUncle;
47
54
  constructor(params: ChainHeadSelectorParams);
@@ -78,6 +85,15 @@ export declare class ChainHeadSelector extends ChainFinalizer<ChainHeadSelectorP
78
85
  * chain from finalizing.
79
86
  */
80
87
  protected assess(all: SignedHydratedBlockWithHashMeta[]): Promise<AdmissionAssessment[]>;
88
+ /**
89
+ * Defense against unwanted heartbeat rates: a transaction-less (heartbeat) candidate qualifies
90
+ * only when its signing epoch is at least heartbeatInterval after the current head's. Measured
91
+ * on chain data, so every finalizer applies the same pace deterministically regardless of wall
92
+ * clock. A producer heartbeating faster than the network's pace — misconfigured or hostile —
93
+ * cannot drive the chain's block rate: its candidates never qualify and age out of the pool,
94
+ * while transaction-carrying candidates are exempt and finalize immediately.
95
+ */
96
+ protected filterPacedHeartbeatCandidates(proposedBlocks: SignedHydratedBlockWithHashMeta[]): SignedHydratedBlockWithHashMeta[];
81
97
  /** Whether the configured allow-list admits a candidate. An empty list admits everyone. */
82
98
  protected isAllowed(candidate: SignedHydratedBlockWithHashMeta): boolean;
83
99
  /** Publishes what the two gates concluded, swallowing failures. */
@@ -1 +1 @@
1
- {"version":3,"file":"ChainHeadSelector.d.ts","sourceRoot":"","sources":["../../../../src/modules/analyze/ChainHeadSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,+BAA+B,EAC5D,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACxF,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,aAAa,EAAE,aAAa,CAAA;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAOD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5E;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,+BAA+B,QAAO;IAEtD,SAAS,CAAC,SAAS,EAAE,aAAa,CAAA;IAClC,SAAS,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IACtC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,CAAC,mBAAmB,CAAa;gBAE5B,MAAM,EAAE,uBAAuB;IAQ3C,SAAS,KAAK,OAAO;;;;;;;MAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAEK,YAAY,IAAI,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAchE;;;;;;;;;;;;;OAaG;cACa,KAAK,CACnB,GAAG,EAAE,+BAA+B,EAAE,EACtC,OAAO,EAAE,+BAA+B,EAAE,GACzC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAW7C;;;;;;OAMG;cACa,MAAM,CAAC,GAAG,EAAE,+BAA+B,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAmB9F,2FAA2F;IAC3F,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,+BAA+B,GAAG,OAAO;IAOxE,mEAAmE;cACnD,aAAa,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;CAoBpC"}
1
+ {"version":3,"file":"ChainHeadSelector.d.ts","sourceRoot":"","sources":["../../../../src/modules/analyze/ChainHeadSelector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EACV,WAAW,EAAE,aAAa,EAAE,+BAA+B,EAC5D,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACxF,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,aAAa,CAAA;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAOD,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5E;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,+BAA+B,QAAO;IAEtD,SAAS,CAAC,SAAS,EAAE,aAAa,CAAA;IAClC,SAAS,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IACtC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IACpC,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAChC,OAAO,CAAC,mBAAmB,CAAa;gBAE5B,MAAM,EAAE,uBAAuB;IAS3C,SAAS,KAAK,OAAO;;;;;;;MAEpB;IAED,SAAS,KAAK,aAAa,kBAE1B;IAEK,YAAY,IAAI,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAehE;;;;;;;;;;;;;OAaG;cACa,KAAK,CACnB,GAAG,EAAE,+BAA+B,EAAE,EACtC,OAAO,EAAE,+BAA+B,EAAE,GACzC,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAW7C;;;;;;OAMG;cACa,MAAM,CAAC,GAAG,EAAE,+BAA+B,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAmB9F;;;;;;;OAOG;IACH,SAAS,CAAC,8BAA8B,CAAC,cAAc,EAAE,+BAA+B,EAAE,GAAG,+BAA+B,EAAE;IAqB9H,2FAA2F;IAC3F,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,+BAA+B,GAAG,OAAO;IAOxE,mEAAmE;cACnD,aAAa,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehF;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;CAoBpC"}
@@ -14,6 +14,11 @@ interface ProcessPendingBlocksParams {
14
14
  /** Computes producer standing, for the shadow and enforce postures. */
15
15
  eligibility?: ProducerEligibilityEvaluator;
16
16
  finalizationRunner: FinalizationRunner;
17
+ /**
18
+ * Minimum epoch spacing (ms) between transaction-less heartbeat blocks the head selector will
19
+ * qualify; transaction-carrying candidates are exempt. Undefined disables the pace check.
20
+ */
21
+ heartbeatInterval?: number;
17
22
  logger?: Logger;
18
23
  mempoolViewer: MempoolViewer;
19
24
  minCandidates?: number;
@@ -25,7 +30,7 @@ interface ProcessPendingBlocksParams {
25
30
  /** Where to publish what both admission gates concluded, in shadow posture. */
26
31
  publishAdmissionShadow?: (report: AdmissionShadowReport) => Promise<void>;
27
32
  }
28
- export declare function processPendingBlocks({ blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, minCandidates, deadLetterQueueRunner, observer, admission, eligibility, publishAdmissionShadow, }: ProcessPendingBlocksParams): Promise<[{
33
+ export declare function processPendingBlocks({ blockValidationViewer, blockViewer, context, logger, mempoolViewer, finalizationRunner, allowedProducers, backoffMs, heartbeatInterval, minCandidates, deadLetterQueueRunner, observer, admission, eligibility, publishAdmissionShadow, }: ProcessPendingBlocksParams): Promise<[{
29
34
  schema: "network.xyo.boundwitness" & {
30
35
  readonly __schema: true;
31
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"processPendingBlocks.d.ts","sourceRoot":"","sources":["../../../../../src/modules/services/implementation/processPendingBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EACV,WAAW,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAA6B,aAAa,EACrI,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACnE,MAAM,UAAU,CAAA;AAKjB,UAAU,0BAA0B;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,uEAAuE;IACvE,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAgCD,wBAAsB,oBAAoB,CAAC,EACzC,qBAAqB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EACnK,SAAS,EAAE,WAAW,EAAE,sBAAsB,GAC/C,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA2E5B"}
1
+ {"version":3,"file":"processPendingBlocks.d.ts","sourceRoot":"","sources":["../../../../../src/modules/services/implementation/processPendingBlocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EACV,WAAW,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAA6B,aAAa,EACrI,MAAM,sBAAsB,CAAA;AAK7B,OAAO,KAAK,EACV,aAAa,EAAE,qBAAqB,EAAE,4BAA4B,EACnE,MAAM,UAAU,CAAA;AAKjB,UAAU,0BAA0B;IAClC,uFAAuF;IACvF,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,uEAAuE;IACvE,WAAW,CAAC,EAAE,4BAA4B,CAAA;IAC1C,kBAAkB,EAAE,kBAAkB,CAAA;IACtC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAgCD,wBAAsB,oBAAoB,CAAC,EACzC,qBAAqB,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EACtL,SAAS,EAAE,WAAW,EAAE,sBAAsB,GAC/C,EAAE,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA4E5B"}
@@ -13,6 +13,13 @@ interface ExcludedTransactionEntry {
13
13
  * The default block size for a block
14
14
  */
15
15
  export declare const DEFAULT_BLOCK_SIZE = 10;
16
+ /**
17
+ * Default minimum age (ms) of the head before a producer emits a transaction-less heartbeat
18
+ * block. Five minutes keeps a quiet chain visibly alive without accumulating meaningful storage
19
+ * or block-reward drift. Finalizers use the same default as the floor for how fast they will
20
+ * finalize heartbeat blocks.
21
+ */
22
+ export declare const DEFAULT_HEARTBEAT_INTERVAL = 300000;
16
23
  /**
17
24
  * The amount of time for which a producer will restake their intent
18
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleBlockRunner.d.ts","sourceRoot":"","sources":["../../../../../../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SimpleBlockRunner.d.ts","sourceRoot":"","sources":["../../../../../../../src/modules/services/simple/block/runner/SimpleBlockRunner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json.schemastore.org/package.json",
3
3
  "name": "@xyo-network/chain-sdk",
4
- "version": "5.2.0",
4
+ "version": "5.2.1",
5
5
  "description": "XYO Layer One SDK",
6
6
  "homepage": "https://xylabs.com",
7
7
  "bugs": {