@xyo-network/chain-sdk 5.3.0 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/modules/analyze/ChainHeadSelector.d.ts +47 -8
- package/dist/browser/modules/analyze/ChainHeadSelector.d.ts.map +1 -1
- package/dist/browser/modules/analyze/blockTime.d.ts +92 -0
- package/dist/browser/modules/analyze/blockTime.d.ts.map +1 -0
- package/dist/browser/modules/analyze/index.d.ts +1 -0
- package/dist/browser/modules/analyze/index.d.ts.map +1 -1
- package/dist/browser/modules/modules/diviners/index.d.ts +0 -1
- package/dist/browser/modules/modules/diviners/index.d.ts.map +1 -1
- package/dist/browser/modules/protocol/block/buildBlock.d.ts.map +1 -1
- package/dist/browser/modules/protocol/block/createProducerChainStakeIntentTransaction.d.ts +15 -2
- package/dist/browser/modules/protocol/block/createProducerChainStakeIntentTransaction.d.ts.map +1 -1
- package/dist/browser/modules/services/implementation/processPendingBlocks.d.ts +10 -3
- package/dist/browser/modules/services/implementation/processPendingBlocks.d.ts.map +1 -1
- package/dist/browser/modules/services/simple/block/runner/SimpleBlockRunner.d.ts +22 -1
- package/dist/browser/modules/services/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
- package/dist/browser/modules/validation/block/validators/index.d.ts +0 -1
- package/dist/browser/modules/validation/block/validators/index.d.ts.map +1 -1
- package/dist/browser/modules/validation/elevatedPayload/payloads/validateClaimInBlock.d.ts.map +1 -1
- package/dist/browser/modules/wrappers/block/HydratedBlock.d.ts.map +1 -1
- package/dist/neutral/analyze.mjs +166 -10
- package/dist/neutral/analyze.mjs.map +3 -3
- package/dist/neutral/modules/analyze/ChainHeadSelector.d.ts +47 -8
- package/dist/neutral/modules/analyze/ChainHeadSelector.d.ts.map +1 -1
- package/dist/neutral/modules/analyze/blockTime.d.ts +92 -0
- package/dist/neutral/modules/analyze/blockTime.d.ts.map +1 -0
- package/dist/neutral/modules/analyze/index.d.ts +1 -0
- package/dist/neutral/modules/analyze/index.d.ts.map +1 -1
- package/dist/neutral/modules/modules/diviners/index.d.ts +0 -1
- package/dist/neutral/modules/modules/diviners/index.d.ts.map +1 -1
- package/dist/neutral/modules/protocol/block/buildBlock.d.ts.map +1 -1
- package/dist/neutral/modules/protocol/block/createProducerChainStakeIntentTransaction.d.ts +15 -2
- package/dist/neutral/modules/protocol/block/createProducerChainStakeIntentTransaction.d.ts.map +1 -1
- package/dist/neutral/modules/services/implementation/processPendingBlocks.d.ts +10 -3
- package/dist/neutral/modules/services/implementation/processPendingBlocks.d.ts.map +1 -1
- package/dist/neutral/modules/services/simple/block/runner/SimpleBlockRunner.d.ts +22 -1
- package/dist/neutral/modules/services/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
- package/dist/neutral/modules/validation/block/validators/index.d.ts +0 -1
- package/dist/neutral/modules/validation/block/validators/index.d.ts.map +1 -1
- package/dist/neutral/modules/validation/elevatedPayload/payloads/validateClaimInBlock.d.ts.map +1 -1
- package/dist/neutral/modules/wrappers/block/HydratedBlock.d.ts.map +1 -1
- package/dist/neutral/modules.mjs +25 -100
- package/dist/neutral/modules.mjs.map +4 -4
- package/dist/neutral/protocol.mjs +1 -1
- package/dist/neutral/protocol.mjs.map +2 -2
- package/dist/neutral/services.mjs +40 -9
- package/dist/neutral/services.mjs.map +2 -2
- package/dist/neutral/validation.mjs +84 -106
- package/dist/neutral/validation.mjs.map +4 -4
- package/dist/neutral/wrappers.mjs +2 -1
- package/dist/neutral/wrappers.mjs.map +2 -2
- package/dist/node/modules/analyze/ChainHeadSelector.d.ts +47 -8
- package/dist/node/modules/analyze/ChainHeadSelector.d.ts.map +1 -1
- package/dist/node/modules/analyze/blockTime.d.ts +92 -0
- package/dist/node/modules/analyze/blockTime.d.ts.map +1 -0
- package/dist/node/modules/analyze/index.d.ts +1 -0
- package/dist/node/modules/analyze/index.d.ts.map +1 -1
- package/dist/node/modules/modules/diviners/index.d.ts +0 -1
- package/dist/node/modules/modules/diviners/index.d.ts.map +1 -1
- package/dist/node/modules/protocol/block/buildBlock.d.ts.map +1 -1
- package/dist/node/modules/protocol/block/createProducerChainStakeIntentTransaction.d.ts +15 -2
- package/dist/node/modules/protocol/block/createProducerChainStakeIntentTransaction.d.ts.map +1 -1
- package/dist/node/modules/services/implementation/processPendingBlocks.d.ts +10 -3
- package/dist/node/modules/services/implementation/processPendingBlocks.d.ts.map +1 -1
- package/dist/node/modules/services/simple/block/runner/SimpleBlockRunner.d.ts +22 -1
- package/dist/node/modules/services/simple/block/runner/SimpleBlockRunner.d.ts.map +1 -1
- package/dist/node/modules/validation/block/validators/index.d.ts +0 -1
- package/dist/node/modules/validation/block/validators/index.d.ts.map +1 -1
- package/dist/node/modules/validation/elevatedPayload/payloads/validateClaimInBlock.d.ts.map +1 -1
- package/dist/node/modules/wrappers/block/HydratedBlock.d.ts.map +1 -1
- package/package.json +24 -25
- package/dist/browser/modules/modules/diviners/BlockValidationDiviner.d.ts +0 -38
- package/dist/browser/modules/modules/diviners/BlockValidationDiviner.d.ts.map +0 -1
- package/dist/browser/modules/validation/block/validators/JsonSchema.d.ts +0 -4
- package/dist/browser/modules/validation/block/validators/JsonSchema.d.ts.map +0 -1
- package/dist/neutral/modules/modules/diviners/BlockValidationDiviner.d.ts +0 -38
- package/dist/neutral/modules/modules/diviners/BlockValidationDiviner.d.ts.map +0 -1
- package/dist/neutral/modules/validation/block/validators/JsonSchema.d.ts +0 -4
- package/dist/neutral/modules/validation/block/validators/JsonSchema.d.ts.map +0 -1
- package/dist/node/modules/modules/diviners/BlockValidationDiviner.d.ts +0 -38
- package/dist/node/modules/modules/diviners/BlockValidationDiviner.d.ts.map +0 -1
- package/dist/node/modules/validation/block/validators/JsonSchema.d.ts +0 -4
- package/dist/node/modules/validation/block/validators/JsonSchema.d.ts.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/modules/modules/diviners/BlockReward/Abstract/Config.ts", "../../src/modules/modules/diviners/BlockReward/Abstract/Diviner.ts", "../../src/modules/modules/diviners/BlockReward/Abstract/Payload.ts", "../../src/modules/modules/diviners/BlockReward/FixedPercentage/Config.ts", "../../src/modules/modules/diviners/BlockReward/FixedPercentage/Diviner.ts", "../../src/modules/modules/diviners/
|
|
4
|
-
"sourcesContent": ["import { asSchema, type DivinerConfig } from '@xyo-network/sdk'\n\nexport const BlockRewardDivinerConfigSchema = asSchema('network.xyo.diviner.chain.block.reward.config', true)\nexport type BlockRewardDivinerConfigSchema = typeof BlockRewardDivinerConfigSchema\n\n/**\n * The configuration for the Total Diviner\n */\nexport type BlockRewardDivinerConfig = DivinerConfig<{}, BlockRewardDivinerConfigSchema>\n", "import type {\n DivinerInstance, DivinerModuleEventData, Schema,\n} from '@xyo-network/sdk'\nimport { AbstractDiviner } from '@xyo-network/sdk'\nimport type { BlockNumberPayload, Transfer } from '@xyo-network/xl1-sdk'\n\nimport { BlockRewardDivinerConfigSchema } from './Config.ts'\nimport type { BlockRewardDivinerParams } from './Params.ts'\n\nexport type BlockRewardDivinerInputType = BlockNumberPayload\nexport type BlockRewardDivinerOutputType = Transfer\n\nexport abstract class BlockRewardDiviner<\n TParams extends BlockRewardDivinerParams = BlockRewardDivinerParams,\n TIn extends BlockRewardDivinerInputType = BlockRewardDivinerInputType,\n TOut extends BlockRewardDivinerOutputType = BlockRewardDivinerOutputType,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas: Schema[] = [BlockRewardDivinerConfigSchema]\n}\n", "import { AsObjectFactory } from '@ariestools/sdk'\nimport type { PayloadWithSources, WithSources } from '@xyo-network/sdk'\nimport {\n asSchema,\n isPayloadOfSchemaType,\n isPayloadOfSchemaTypeWithSources,\n} from '@xyo-network/sdk'\n\nexport const BlockRewardSchema = asSchema('network.xyo.block.reward', true)\nexport type BlockRewardSchema = typeof BlockRewardSchema\n\nexport interface BlockRewardFields {\n /**\n * The amount of the reward\n */\n amount: number\n\n /**\n * The currency of the reward\n */\n currency: string\n}\n\n/**\n * The result of a BlockReward\n */\nexport type BlockReward = PayloadWithSources<BlockRewardFields, BlockRewardSchema>\n\n/**\n * Identity function for determining if an object is an BlockReward\n */\nexport const isBlockReward = isPayloadOfSchemaType<BlockReward>(BlockRewardSchema)\nexport const asBlockReward = AsObjectFactory.create<BlockReward>(isBlockReward)\nexport const asOptionalBlockReward = AsObjectFactory.createOptional<BlockReward>(isBlockReward)\n\n/**\n * Identity function for determining if an object is an BlockReward with sources\n */\nexport const isBlockRewardWithSources = isPayloadOfSchemaTypeWithSources<BlockReward>(BlockRewardSchema)\nexport const asBlockRewardWithSources = AsObjectFactory.create<WithSources<BlockReward>>(isBlockRewardWithSources)\nexport const asOptionalBlockRewardWithSources = AsObjectFactory.createOptional<WithSources<BlockReward>>(isBlockRewardWithSources)\n", "import { asSchema, type DivinerConfig } from '@xyo-network/sdk'\n\nexport const FixedPercentageBlockRewardDivinerConfigSchema = asSchema('network.xyo.diviner.chain.block.reward.fixed.percent.config', true)\nexport type FixedPercentageBlockRewardDivinerConfigSchema = typeof FixedPercentageBlockRewardDivinerConfigSchema\n\n/**\n * The configuration for the FixedPercentageBlockReward Diviner\n */\nexport type FixedPercentageBlockRewardDivinerConfig = DivinerConfig<\n {\n /**\n * The address to send the producer reward to\n */\n rewardAddress?: string\n /**\n * The decimal percentage of the maximum block reward to allocate to the reward address\n */\n rewardPercentageRatio?: number\n },\n FixedPercentageBlockRewardDivinerConfigSchema\n>\n", "import type { Address } from '@ariestools/sdk'\nimport {\n asAddress, assertEx, exists, filterAs,\n isDefined,\n toHex,\n} from '@ariestools/sdk'\nimport type { DivinerInstance, DivinerModuleEventData } from '@xyo-network/sdk'\nimport { creatableModule, PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n BlockRewardViewer,\n Transfer,\n} from '@xyo-network/xl1-sdk'\nimport {\n asBlockNumberPayload, TransferSchema, XYO_STEP_REWARD_ADDRESS, XYO_ZERO_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BlockRewardDivinerInputType, BlockRewardDivinerOutputType } from '../Abstract/index.ts'\nimport { BlockRewardDiviner, BlockRewardDivinerConfigSchema } from '../Abstract/index.ts'\nimport { FixedPercentageBlockRewardDivinerConfigSchema } from './Config.ts'\nimport type { FixedPercentageBlockRewardDivinerParams } from './Params.ts'\n\n@creatableModule()\nexport class FixedPercentageBlockRewardDiviner<\n TParams extends FixedPercentageBlockRewardDivinerParams = FixedPercentageBlockRewardDivinerParams,\n TIn extends BlockRewardDivinerInputType = BlockRewardDivinerInputType,\n TOut extends BlockRewardDivinerOutputType = BlockRewardDivinerOutputType,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends BlockRewardDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas = [BlockRewardDivinerConfigSchema, FixedPercentageBlockRewardDivinerConfigSchema]\n static override readonly defaultConfigSchema = FixedPercentageBlockRewardDivinerConfigSchema\n\n protected _fixedPercentageDenominator: bigint | undefined\n protected _fixedPercentageNumerator: bigint | undefined\n protected _percentageScale: number | undefined\n\n protected get blockRewardViewer(): BlockRewardViewer {\n return assertEx(this.params.blockRewardViewer, () => 'blockRewardViewer is required')\n }\n\n protected get fixedPercentageDenominator(): bigint {\n if (isDefined(this._fixedPercentageDenominator)) {\n return this._fixedPercentageDenominator\n }\n this._fixedPercentageDenominator = BigInt(this.percentageScaleNumeric)\n return this._fixedPercentageDenominator\n }\n\n protected get fixedPercentageNumerator(): bigint {\n if (isDefined(this._fixedPercentageNumerator)) {\n return this._fixedPercentageNumerator\n }\n this._fixedPercentageNumerator = BigInt(Math.round(this.rewardPercentageRatio * this.percentageScaleNumeric))\n return this._fixedPercentageNumerator\n }\n\n protected get percentageScaleNumeric(): number {\n if (isDefined(this._percentageScale)) {\n return this._percentageScale\n }\n this._percentageScale = 10 ** countDecimalPlaces(this.rewardPercentageRatio)\n return this._percentageScale\n }\n\n protected get rewardAddress(): Address {\n return assertEx(asAddress(this.config.rewardAddress), () => 'rewardAddress is required')\n }\n\n protected get rewardPercentageRatio(): number {\n assertEx(this.config.rewardPercentageRatio !== undefined, () => 'rewardPercentageRatio is required')\n return this.config.rewardPercentageRatio!\n }\n\n protected async divineHandler(payloads: TIn[] = []): Promise<TOut[]> {\n const blocks = filterAs(payloads, asBlockNumberPayload)\n const rewardGroups = await Promise.all(blocks.map(async (block) => {\n const blockNumber = block.block\n const reward = await this.blockRewardViewer.allowedRewardForBlock(blockNumber)\n const producerReward = reward * this.fixedPercentageNumerator / this.fixedPercentageDenominator\n const stepReward = reward - producerReward\n assertEx(producerReward >= 0n, () => 'producerReward must be greater than or equal to 0')\n const transfers = Object.fromEntries([\n [String(this.rewardAddress), toHex(producerReward)],\n [String(XYO_STEP_REWARD_ADDRESS), toHex(stepReward)],\n ])\n const transferBuilder = new PayloadBuilder<Transfer>({ schema: TransferSchema })\n const transfer: Transfer = transferBuilder.fields({\n epoch: Date.now(), from: XYO_ZERO_ADDRESS, transfers,\n }).build()\n return [transfer]\n }))\n const rewards = rewardGroups.flat()\n return rewards.filter(exists) as TOut[]\n }\n}\n\n/**\n * Given a number, count the number of decimal places\n * @param num A JavaScript number\n * @returns The number of decimal places\n */\nconst countDecimalPlaces = (num: number): number => {\n if (!Number.isFinite(num)) {\n throw new TypeError('Input must be a finite number')\n }\n const numStr = num.toString()\n const decimalIndex = numStr.indexOf('.')\n return decimalIndex === -1 ? 0 : numStr.length - decimalIndex - 1\n}\n", "import type { Address } from '@ariestools/sdk'\nimport {\n assertEx, exists, isString,\n} from '@ariestools/sdk'\nimport type {\n AnyConfigSchema, ArchivistInstance, DivinerConfig,\n DivinerInstance, DivinerModuleEventData, DivinerParams, ModuleIdentifier,\n Payload,\n} from '@xyo-network/sdk'\nimport {\n AbstractDiviner, asArchivistInstance, asSchema, creatableModule,\n PayloadBuilder,\n} from '@xyo-network/sdk'\nimport type {\n BaseContext, BlockBoundWitness, ChainId,\n} from '@xyo-network/xl1-sdk'\nimport { asBlockBoundWitness, hydrateBlock } from '@xyo-network/xl1-sdk'\n\nimport { BlockJsonSchemaValidator, validateHydratedBlock } from '#validation'\n\n// TODO: Use Chain Information Structure\n\nexport const BlockValidationDivinerConfigSchema = asSchema('network.xyo.diviner.chain.block.validation.config', true)\nexport type BlockValidationDivinerConfigSchema = typeof BlockValidationDivinerConfigSchema\n\nexport type BlockValidationDivinerConfig = DivinerConfig<{\n chainId?: ChainId\n inArchivist?: ModuleIdentifier\n outArchivist?: ModuleIdentifier\n sharedSigner?: Address\n}, BlockValidationDivinerConfigSchema>\n\nexport type BlockValidationDivinerParams = DivinerParams<AnyConfigSchema<BlockValidationDivinerConfig>> & {\n context: BaseContext\n}\n\n@creatableModule()\nexport class BlockValidationDiviner<\n TParams extends BlockValidationDivinerParams = BlockValidationDivinerParams,\n TIn extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, BlockBoundWitness>, TIn, BlockBoundWitness> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, BlockBoundWitness>,\n TIn,\n BlockBoundWitness\n >,\n> extends AbstractDiviner<TParams, TIn, BlockBoundWitness, TEventData> {\n static override readonly configSchemas = [...super.configSchemas, BlockValidationDivinerConfigSchema]\n static override readonly targetSchema = BlockValidationDivinerConfigSchema\n\n private _inArchivist: ArchivistInstance | undefined\n private _outArchivist: ArchivistInstance | undefined\n\n get chainId() {\n return assertEx(this.config.chainId, () => 'Missing chainId')\n }\n\n get context() {\n return assertEx(this.params.context, () => 'Missing context')\n }\n\n async resolveInArchivist() {\n const resolvedModule = assertEx(\n await this.resolve(assertEx(this.config.inArchivist, () => 'Missing inArchivist')),\n () => `Unable to resolve inArchivist [${this.config.inArchivist}]`,\n )\n const resolvedArchivist = assertEx(asArchivistInstance(resolvedModule), () => 'Invalid inArchivist resolved')\n this._inArchivist = resolvedArchivist\n return this._inArchivist\n }\n\n async resolveOutArchivist() {\n const resolvedModule = assertEx(\n await this.resolve(assertEx(this.config.outArchivist, () => 'Missing outArchivist')),\n () => `Unable to resolve outArchivist [${this.config.outArchivist}]`,\n )\n const resolvedArchivist = assertEx(asArchivistInstance(resolvedModule), () => 'Invalid outArchivist resolved')\n this._outArchivist = resolvedArchivist\n return this._outArchivist\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<BlockBoundWitness[]> {\n const inArchivist = await this.resolveInArchivist()\n const inMap = inArchivist\n const blocks = (payloads ?? []).map(b => asBlockBoundWitness(b)).filter(exists)\n const validationResults = await Promise.all(blocks.map(async (block) => {\n const blockHash = await PayloadBuilder.hash(block)\n const hydratedBlock = await hydrateBlock({\n ...this.context, chainMap: inMap, caches: this.context.caches ?? {},\n }, blockHash)\n const validationErrors = await validateHydratedBlock(this.context, hydratedBlock, () => this.chainId, [], [BlockJsonSchemaValidator()])\n return validationErrors.length === 0 ? block : undefined\n }))\n const results = validationResults.filter(exists)\n\n if (isString(this.config.outArchivist)) {\n const outArchivist = await this.resolveOutArchivist()\n if (results?.length > 0) {\n await outArchivist.insert(results)\n }\n }\n\n return results\n }\n}\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport {\n assertEx, isDefined, toAddress,\n} from '@ariestools/sdk'\nimport type { Attributes, Counter } from '@opentelemetry/api'\nimport type {\n AnyConfigSchema, ArchivistInstance, DivinerConfig, DivinerParams,\n ModuleIdentifier, Payload,\n} from '@xyo-network/sdk'\nimport {\n AbstractDiviner, asArchivistInstance,\n asSchema, creatableModule,\n} from '@xyo-network/sdk'\nimport type {\n BaseContext,\n BlockViewer,\n ChainId, MempoolViewer, SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { flattenHydratedBlock } from '@xyo-network/xl1-sdk'\nimport { Mutex } from 'async-mutex'\n\nimport { ChainHeadSelector } from '#analyze'\n\nexport const HeadValidationDivinerConfigSchema = asSchema('network.xyo.diviner.chain.head.validation.config', true)\nexport type HeadValidationDivinerConfigSchema = typeof HeadValidationDivinerConfigSchema\n\nexport type HeadValidationDivinerConfig = DivinerConfig<{\n /**\n * List of allowed producer addresses, if undefined anyone can participate\n */\n allowedProducers?: Address[]\n chainId?: ChainId\n finalizedBlock?: Hash\n outArchivist?: ModuleIdentifier\n sharedSigner?: Address\n spanLevel?: number\n}, HeadValidationDivinerConfigSchema>\n\nexport interface HeadValidationDivinerParams extends DivinerParams<AnyConfigSchema<HeadValidationDivinerConfig>> {\n /**\n * List of allowed producer addresses, if undefined anyone can participate\n */\n allowedProducers?: Address[]\n blockViewer: BlockViewer\n chainId?: ChainId\n context?: BaseContext\n mempoolViewer: MempoolViewer\n}\n\ninterface FinalizedBlockAttributes extends Attributes { producer: Address }\n\n@creatableModule()\nexport class HeadValidationDiviner<TParams extends HeadValidationDivinerParams = HeadValidationDivinerParams> extends AbstractDiviner<TParams> {\n static override readonly configSchemas = [...super.configSchemas, HeadValidationDivinerConfigSchema]\n static override readonly targetSchema = HeadValidationDivinerConfigSchema\n\n protected _context?: BaseContext\n protected _headValidationDivinerHeadUpdateTotal: Counter<FinalizedBlockAttributes> | undefined\n private _headSelector?: ChainHeadSelector\n private _outArchivist: ArchivistInstance | undefined\n private _startingHead: SignedHydratedBlockWithHashMeta | undefined\n private divineMutex = new Mutex()\n\n get allowedProducers() {\n return this.params.allowedProducers ?? this.config.allowedProducers ?? []\n }\n\n get blockViewer() {\n return assertEx(this.params.blockViewer, () => 'Missing block viewer')\n }\n\n get chainId() {\n return assertEx(this.params.chainId ?? this.config.chainId, () => 'Missing chain information')\n }\n\n get context() {\n return this._context!\n }\n\n get headSelector() {\n return assertEx(this._headSelector, () => 'Missing head selector')\n }\n\n get mempoolViewer() {\n return assertEx(this.params.mempoolViewer, () => 'Missing mempool viewer')\n }\n\n override async createHandler() {\n await super.createHandler()\n this._context = this.params.context ?? { singletons: {} }\n\n this._headValidationDivinerHeadUpdateTotal = this.meter?.createCounter<FinalizedBlockAttributes>(\n 'head_validation_diviner_head_update_total',\n { description: 'Count of head updates performed by the diviner during head validation' },\n )\n this._headSelector = new ChainHeadSelector({\n context: this.context,\n allowedProducers: this.allowedProducers,\n blockViewer: this.blockViewer,\n mempoolViewer: this.mempoolViewer,\n maxWindowSize: 1000,\n })\n }\n\n async resolveOutArchivist() {\n if (this._outArchivist) return this._outArchivist\n const resolvedModule = assertEx(\n await this.resolve(assertEx(this.config.outArchivist, () => 'Missing outArchivist')),\n () => `Unable to resolve outArchivist [${this.config.outArchivist}]`,\n )\n const resolvedArchivist = assertEx(asArchivistInstance(resolvedModule), () => 'Invalid outArchivist resolved')\n this._outArchivist = resolvedArchivist\n return this._outArchivist\n }\n\n protected override async divineHandler(): Promise<Payload[]> {\n // If the diviner is already running, return early\n if (this.divineMutex.isLocked()) return []\n\n // Check for new best head and finalize if we find one\n return await this.divineMutex.runExclusive(async () => {\n // eslint-disable-next-line complexity\n return (await this.spanAsync('HeadValidationDiviner:divineHandler', async () => {\n try {\n // Determine the chain we are working with\n // const chainId = this.chainId\n\n const start = Date.now()\n\n // Use the head selector to find the best head or fallback to the starting head\n const bestHeadChain = ((await this.headSelector.findBestHead()) ?? this._startingHead)\n\n // If we found a head\n if (isDefined(bestHeadChain)) {\n // Resolve the appropriate archivists\n const outArchivist = await this.resolveOutArchivist()\n\n const oldHeadBlock = this._startingHead?.[0]\n const newHydratedHeadBlock = assertEx(bestHeadChain.at(-1), () => 'Missing best head block [HeadValidationDiviner]')\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 this.logger?.debug('Validating new HeadBlock head from (block) ', oldHeadBlock?.block, 'to', newHeadBlock.block)\n this.logger?.debug('Validating new HeadBlock head from (hash) ', oldHeadBlock?._hash, 'to', newHeadBlock._hash)\n\n if (newHeadBlock._hash === oldHeadBlock?._hash) {\n this.logger?.debug('No new blocks found', oldHeadBlock?.block, 'to', newHeadBlock.block)\n return\n }\n\n // Validate it\n // const validationErrors = await spanRootAsync('validateHydratedBlock', async () => {\n // return await validateHydratedBlock(hydratedBlock, chainId)\n // }, this.tracer)\n // // Ensure no validation errors\n // if (validationErrors.length > 0) {\n // // TODO: Metrics here with error count\n // this.logger?.error('Block validation errors', hydratedBlock[0].block, hydratedBlock[0]._hash, validationErrors)\n // break\n // }\n\n // Store the items to be committed in the correct order\n const blocksToFinalize = bestHeadChain.filter((b) => {\n return isDefined(oldHeadBlock) ? b[0].block > oldHeadBlock.block : true\n })\n\n const payloadsToFinalize = blocksToFinalize.flatMap(b => flattenHydratedBlock(b))\n\n // Store metrics about the finalized block in the correct order to allow metrics for each block in this batch\n finalizedBlocksAttributes = [{ producer: toAddress(newHeadBlock.addresses[0]) }, ...finalizedBlocksAttributes]\n\n this.logger?.info('Validated new HeadBlock head from (block) in', `${Date.now() - start}ms`, newHeadBlock.block, 'to', oldHeadBlock?.block)\n this.logger?.info('Validated new HeadBlock head from (hash) in', `${Date.now() - start}ms`, newHeadBlock._hash, 'to', oldHeadBlock?._hash)\n\n await this.spanAsync('HeadValidationDiviner:commitToOutArchivist', async () => {\n if (payloadsToFinalize.length === 0) {\n return\n }\n\n await outArchivist.insert(payloadsToFinalize)\n for (const finalizedBlockAttributes of finalizedBlocksAttributes) {\n this._headValidationDivinerHeadUpdateTotal?.add(1, finalizedBlockAttributes)\n }\n }, this.context)\n\n // Prevent us from rechecking the same head\n await this.headSelector.finalizeChainFragment(blocksToFinalize)\n\n this._startingHead = newHydratedHeadBlock\n\n // Return the finalized payloads\n return payloadsToFinalize\n }\n // If no head was found, return an empty array\n this.logger?.info('No head found to validate', this._startingHead?.[0]._hash)\n } catch (ex) {\n this.logger?.error('Error in divineHandler', ex)\n }\n }, this.context)) ?? []\n })\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { assertEx } from '@ariestools/sdk'\nimport type {\n AnyConfigSchema, ArchivistInstance,\n Payload, Schema, Sequence,\n WitnessConfig, WitnessModule, WitnessParams,\n} from '@xyo-network/sdk'\nimport {\n AbstractWitness, asArchivistInstance, asSchema,\n} from '@xyo-network/sdk'\n\nexport const ArchivistNextWitnessConfigSchema = asSchema('network.xyo.witness.archivist.next.config', true)\nexport type ArchivistNextWitnessConfigSchema = typeof ArchivistNextWitnessConfigSchema\n\nexport type ArchivistNextWitnessConfig = WitnessConfig<{\n schema: ArchivistNextWitnessConfigSchema\n sourceArchivist?: Address\n}>\n\nexport type ArchivistNextWitnessParams = WitnessParams<AnyConfigSchema<ArchivistNextWitnessConfig>>\n\nexport class ArchivistNextWitness<TParams extends ArchivistNextWitnessParams = ArchivistNextWitnessParams>\n extends AbstractWitness<TParams> implements WitnessModule {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, ArchivistNextWitnessConfigSchema]\n static override readonly defaultConfigSchema: Schema = ArchivistNextWitnessConfigSchema\n\n private _cursor?: Sequence\n\n async getSourceArchivist(): Promise<ArchivistInstance> {\n return assertEx(asArchivistInstance(\n await this.resolve(assertEx(this.config.sourceArchivist, () => 'Missing sourceArchivist')),\n ), () => 'Invalid sourceArchivist')\n }\n\n protected override async observeHandler(): Promise<Payload[]> {\n const archivist = await this.getSourceArchivist()\n const payloads = await archivist.next({ cursor: this._cursor, order: 'asc' })\n const lastPayload = payloads.at(-1)\n if (lastPayload) {\n this._cursor = lastPayload._sequence\n }\n return payloads\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { AsObjectFactory } from '@ariestools/sdk'\nimport {\n asSchema, isPayloadOfSchemaType, type Payload,\n} from '@xyo-network/sdk'\n\nexport const WeightedNetworkStakeSchema = asSchema('network.xyo.witness.chain.stake.network.weighted', true)\nexport type WeightedNetworkStakeSchema = typeof WeightedNetworkStakeSchema\n\nexport type WeightedNetworkStake = Payload<{\n amount: bigint\n blockRange: [number, number]\n staker: Address\n}, WeightedNetworkStakeSchema>\n\nexport const isWeightedNetworkStake = isPayloadOfSchemaType<WeightedNetworkStake>(WeightedNetworkStakeSchema)\n\nexport const asWeightedNetworkStakePayload = AsObjectFactory.create(isWeightedNetworkStake)\nexport const asWeightedNetworkStakePayloadWithStorageMeta = AsObjectFactory.create(isWeightedNetworkStake)\n", "import type { Address } from '@ariestools/sdk'\nimport { AsObjectFactory } from '@ariestools/sdk'\nimport {\n asSchema, isPayloadOfSchemaType, type Payload,\n} from '@xyo-network/sdk'\n\nexport const NetworkStakeObserveSchema = asSchema('network.xyo.witness.chain.stake.network.observe', true)\nexport type NetworkStakeObserveSchema = typeof NetworkStakeObserveSchema\n\nexport type NetworkStakeObserve = Payload<{\n blockRange: [number, number]\n staked: Address\n staker: Address\n}, NetworkStakeObserveSchema>\n\nexport const isNetworkStakeObserve = isPayloadOfSchemaType<NetworkStakeObserve>(NetworkStakeObserveSchema)\n\nexport const asNetworkStakeObservePayload = AsObjectFactory.create(isNetworkStakeObserve)\nexport const asNetworkStakeObservePayloadWithStorageMeta = AsObjectFactory.create(isNetworkStakeObserve)\n"],
|
|
5
|
-
"mappings": "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
|
|
6
|
-
"names": ["asSchema", "asSchema", "assertEx", "
|
|
3
|
+
"sources": ["../../src/modules/modules/diviners/BlockReward/Abstract/Config.ts", "../../src/modules/modules/diviners/BlockReward/Abstract/Diviner.ts", "../../src/modules/modules/diviners/BlockReward/Abstract/Payload.ts", "../../src/modules/modules/diviners/BlockReward/FixedPercentage/Config.ts", "../../src/modules/modules/diviners/BlockReward/FixedPercentage/Diviner.ts", "../../src/modules/modules/diviners/HeadValidationDiviner.ts", "../../src/modules/modules/witnesses/ArchivistNextWitness.ts", "../../src/modules/modules/witnesses/NetworkStake/NetworkStake.ts", "../../src/modules/modules/witnesses/NetworkStake/NetworkStakeObserve.ts"],
|
|
4
|
+
"sourcesContent": ["import { asSchema, type DivinerConfig } from '@xyo-network/sdk'\n\nexport const BlockRewardDivinerConfigSchema = asSchema('network.xyo.diviner.chain.block.reward.config', true)\nexport type BlockRewardDivinerConfigSchema = typeof BlockRewardDivinerConfigSchema\n\n/**\n * The configuration for the Total Diviner\n */\nexport type BlockRewardDivinerConfig = DivinerConfig<{}, BlockRewardDivinerConfigSchema>\n", "import type {\n DivinerInstance, DivinerModuleEventData, Schema,\n} from '@xyo-network/sdk'\nimport { AbstractDiviner } from '@xyo-network/sdk'\nimport type { BlockNumberPayload, Transfer } from '@xyo-network/xl1-sdk'\n\nimport { BlockRewardDivinerConfigSchema } from './Config.ts'\nimport type { BlockRewardDivinerParams } from './Params.ts'\n\nexport type BlockRewardDivinerInputType = BlockNumberPayload\nexport type BlockRewardDivinerOutputType = Transfer\n\nexport abstract class BlockRewardDiviner<\n TParams extends BlockRewardDivinerParams = BlockRewardDivinerParams,\n TIn extends BlockRewardDivinerInputType = BlockRewardDivinerInputType,\n TOut extends BlockRewardDivinerOutputType = BlockRewardDivinerOutputType,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends AbstractDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas: Schema[] = [BlockRewardDivinerConfigSchema]\n}\n", "import { AsObjectFactory } from '@ariestools/sdk'\nimport type { PayloadWithSources, WithSources } from '@xyo-network/sdk'\nimport {\n asSchema,\n isPayloadOfSchemaType,\n isPayloadOfSchemaTypeWithSources,\n} from '@xyo-network/sdk'\n\nexport const BlockRewardSchema = asSchema('network.xyo.block.reward', true)\nexport type BlockRewardSchema = typeof BlockRewardSchema\n\nexport interface BlockRewardFields {\n /**\n * The amount of the reward\n */\n amount: number\n\n /**\n * The currency of the reward\n */\n currency: string\n}\n\n/**\n * The result of a BlockReward\n */\nexport type BlockReward = PayloadWithSources<BlockRewardFields, BlockRewardSchema>\n\n/**\n * Identity function for determining if an object is an BlockReward\n */\nexport const isBlockReward = isPayloadOfSchemaType<BlockReward>(BlockRewardSchema)\nexport const asBlockReward = AsObjectFactory.create<BlockReward>(isBlockReward)\nexport const asOptionalBlockReward = AsObjectFactory.createOptional<BlockReward>(isBlockReward)\n\n/**\n * Identity function for determining if an object is an BlockReward with sources\n */\nexport const isBlockRewardWithSources = isPayloadOfSchemaTypeWithSources<BlockReward>(BlockRewardSchema)\nexport const asBlockRewardWithSources = AsObjectFactory.create<WithSources<BlockReward>>(isBlockRewardWithSources)\nexport const asOptionalBlockRewardWithSources = AsObjectFactory.createOptional<WithSources<BlockReward>>(isBlockRewardWithSources)\n", "import { asSchema, type DivinerConfig } from '@xyo-network/sdk'\n\nexport const FixedPercentageBlockRewardDivinerConfigSchema = asSchema('network.xyo.diviner.chain.block.reward.fixed.percent.config', true)\nexport type FixedPercentageBlockRewardDivinerConfigSchema = typeof FixedPercentageBlockRewardDivinerConfigSchema\n\n/**\n * The configuration for the FixedPercentageBlockReward Diviner\n */\nexport type FixedPercentageBlockRewardDivinerConfig = DivinerConfig<\n {\n /**\n * The address to send the producer reward to\n */\n rewardAddress?: string\n /**\n * The decimal percentage of the maximum block reward to allocate to the reward address\n */\n rewardPercentageRatio?: number\n },\n FixedPercentageBlockRewardDivinerConfigSchema\n>\n", "import type { Address } from '@ariestools/sdk'\nimport {\n asAddress, assertEx, exists, filterAs,\n isDefined,\n toHex,\n} from '@ariestools/sdk'\nimport type { DivinerInstance, DivinerModuleEventData } from '@xyo-network/sdk'\nimport { creatableModule, PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n BlockRewardViewer,\n Transfer,\n} from '@xyo-network/xl1-sdk'\nimport {\n asBlockNumberPayload, TransferSchema, XYO_STEP_REWARD_ADDRESS, XYO_ZERO_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport type { BlockRewardDivinerInputType, BlockRewardDivinerOutputType } from '../Abstract/index.ts'\nimport { BlockRewardDiviner, BlockRewardDivinerConfigSchema } from '../Abstract/index.ts'\nimport { FixedPercentageBlockRewardDivinerConfigSchema } from './Config.ts'\nimport type { FixedPercentageBlockRewardDivinerParams } from './Params.ts'\n\n@creatableModule()\nexport class FixedPercentageBlockRewardDiviner<\n TParams extends FixedPercentageBlockRewardDivinerParams = FixedPercentageBlockRewardDivinerParams,\n TIn extends BlockRewardDivinerInputType = BlockRewardDivinerInputType,\n TOut extends BlockRewardDivinerOutputType = BlockRewardDivinerOutputType,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends BlockRewardDiviner<TParams, TIn, TOut, TEventData> {\n static override readonly configSchemas = [BlockRewardDivinerConfigSchema, FixedPercentageBlockRewardDivinerConfigSchema]\n static override readonly defaultConfigSchema = FixedPercentageBlockRewardDivinerConfigSchema\n\n protected _fixedPercentageDenominator: bigint | undefined\n protected _fixedPercentageNumerator: bigint | undefined\n protected _percentageScale: number | undefined\n\n protected get blockRewardViewer(): BlockRewardViewer {\n return assertEx(this.params.blockRewardViewer, () => 'blockRewardViewer is required')\n }\n\n protected get fixedPercentageDenominator(): bigint {\n if (isDefined(this._fixedPercentageDenominator)) {\n return this._fixedPercentageDenominator\n }\n this._fixedPercentageDenominator = BigInt(this.percentageScaleNumeric)\n return this._fixedPercentageDenominator\n }\n\n protected get fixedPercentageNumerator(): bigint {\n if (isDefined(this._fixedPercentageNumerator)) {\n return this._fixedPercentageNumerator\n }\n this._fixedPercentageNumerator = BigInt(Math.round(this.rewardPercentageRatio * this.percentageScaleNumeric))\n return this._fixedPercentageNumerator\n }\n\n protected get percentageScaleNumeric(): number {\n if (isDefined(this._percentageScale)) {\n return this._percentageScale\n }\n this._percentageScale = 10 ** countDecimalPlaces(this.rewardPercentageRatio)\n return this._percentageScale\n }\n\n protected get rewardAddress(): Address {\n return assertEx(asAddress(this.config.rewardAddress), () => 'rewardAddress is required')\n }\n\n protected get rewardPercentageRatio(): number {\n assertEx(this.config.rewardPercentageRatio !== undefined, () => 'rewardPercentageRatio is required')\n return this.config.rewardPercentageRatio!\n }\n\n protected async divineHandler(payloads: TIn[] = []): Promise<TOut[]> {\n const blocks = filterAs(payloads, asBlockNumberPayload)\n const rewardGroups = await Promise.all(blocks.map(async (block) => {\n const blockNumber = block.block\n const reward = await this.blockRewardViewer.allowedRewardForBlock(blockNumber)\n const producerReward = reward * this.fixedPercentageNumerator / this.fixedPercentageDenominator\n const stepReward = reward - producerReward\n assertEx(producerReward >= 0n, () => 'producerReward must be greater than or equal to 0')\n const transfers = Object.fromEntries([\n [String(this.rewardAddress), toHex(producerReward)],\n [String(XYO_STEP_REWARD_ADDRESS), toHex(stepReward)],\n ])\n const transferBuilder = new PayloadBuilder<Transfer>({ schema: TransferSchema })\n const transfer: Transfer = transferBuilder.fields({\n epoch: Date.now(), from: XYO_ZERO_ADDRESS, transfers,\n }).build()\n return [transfer]\n }))\n const rewards = rewardGroups.flat()\n return rewards.filter(exists) as TOut[]\n }\n}\n\n/**\n * Given a number, count the number of decimal places\n * @param num A JavaScript number\n * @returns The number of decimal places\n */\nconst countDecimalPlaces = (num: number): number => {\n if (!Number.isFinite(num)) {\n throw new TypeError('Input must be a finite number')\n }\n const numStr = num.toString()\n const decimalIndex = numStr.indexOf('.')\n return decimalIndex === -1 ? 0 : numStr.length - decimalIndex - 1\n}\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport {\n assertEx, isDefined, toAddress,\n} from '@ariestools/sdk'\nimport type { Attributes, Counter } from '@opentelemetry/api'\nimport type {\n AnyConfigSchema, ArchivistInstance, DivinerConfig, DivinerParams,\n ModuleIdentifier, Payload,\n} from '@xyo-network/sdk'\nimport {\n AbstractDiviner, asArchivistInstance,\n asSchema, creatableModule,\n} from '@xyo-network/sdk'\nimport type {\n BaseContext,\n BlockViewer,\n ChainId, MempoolViewer, SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { flattenHydratedBlock } from '@xyo-network/xl1-sdk'\nimport { Mutex } from 'async-mutex'\n\nimport { ChainHeadSelector } from '#analyze'\n\nexport const HeadValidationDivinerConfigSchema = asSchema('network.xyo.diviner.chain.head.validation.config', true)\nexport type HeadValidationDivinerConfigSchema = typeof HeadValidationDivinerConfigSchema\n\nexport type HeadValidationDivinerConfig = DivinerConfig<{\n /**\n * List of allowed producer addresses, if undefined anyone can participate\n */\n allowedProducers?: Address[]\n chainId?: ChainId\n finalizedBlock?: Hash\n outArchivist?: ModuleIdentifier\n sharedSigner?: Address\n spanLevel?: number\n}, HeadValidationDivinerConfigSchema>\n\nexport interface HeadValidationDivinerParams extends DivinerParams<AnyConfigSchema<HeadValidationDivinerConfig>> {\n /**\n * List of allowed producer addresses, if undefined anyone can participate\n */\n allowedProducers?: Address[]\n blockViewer: BlockViewer\n chainId?: ChainId\n context?: BaseContext\n mempoolViewer: MempoolViewer\n}\n\ninterface FinalizedBlockAttributes extends Attributes { producer: Address }\n\n@creatableModule()\nexport class HeadValidationDiviner<TParams extends HeadValidationDivinerParams = HeadValidationDivinerParams> extends AbstractDiviner<TParams> {\n static override readonly configSchemas = [...super.configSchemas, HeadValidationDivinerConfigSchema]\n static override readonly targetSchema = HeadValidationDivinerConfigSchema\n\n protected _context?: BaseContext\n protected _headValidationDivinerHeadUpdateTotal: Counter<FinalizedBlockAttributes> | undefined\n private _headSelector?: ChainHeadSelector\n private _outArchivist: ArchivistInstance | undefined\n private _startingHead: SignedHydratedBlockWithHashMeta | undefined\n private divineMutex = new Mutex()\n\n get allowedProducers() {\n return this.params.allowedProducers ?? this.config.allowedProducers ?? []\n }\n\n get blockViewer() {\n return assertEx(this.params.blockViewer, () => 'Missing block viewer')\n }\n\n get chainId() {\n return assertEx(this.params.chainId ?? this.config.chainId, () => 'Missing chain information')\n }\n\n get context() {\n return this._context!\n }\n\n get headSelector() {\n return assertEx(this._headSelector, () => 'Missing head selector')\n }\n\n get mempoolViewer() {\n return assertEx(this.params.mempoolViewer, () => 'Missing mempool viewer')\n }\n\n override async createHandler() {\n await super.createHandler()\n this._context = this.params.context ?? { singletons: {} }\n\n this._headValidationDivinerHeadUpdateTotal = this.meter?.createCounter<FinalizedBlockAttributes>(\n 'head_validation_diviner_head_update_total',\n { description: 'Count of head updates performed by the diviner during head validation' },\n )\n this._headSelector = new ChainHeadSelector({\n context: this.context,\n allowedProducers: this.allowedProducers,\n blockViewer: this.blockViewer,\n mempoolViewer: this.mempoolViewer,\n maxWindowSize: 1000,\n })\n }\n\n async resolveOutArchivist() {\n if (this._outArchivist) return this._outArchivist\n const resolvedModule = assertEx(\n await this.resolve(assertEx(this.config.outArchivist, () => 'Missing outArchivist')),\n () => `Unable to resolve outArchivist [${this.config.outArchivist}]`,\n )\n const resolvedArchivist = assertEx(asArchivistInstance(resolvedModule), () => 'Invalid outArchivist resolved')\n this._outArchivist = resolvedArchivist\n return this._outArchivist\n }\n\n protected override async divineHandler(): Promise<Payload[]> {\n // If the diviner is already running, return early\n if (this.divineMutex.isLocked()) return []\n\n // Check for new best head and finalize if we find one\n return await this.divineMutex.runExclusive(async () => {\n // eslint-disable-next-line complexity\n return (await this.spanAsync('HeadValidationDiviner:divineHandler', async () => {\n try {\n // Determine the chain we are working with\n // const chainId = this.chainId\n\n const start = Date.now()\n\n // Use the head selector to find the best head or fallback to the starting head\n const bestHeadChain = ((await this.headSelector.findBestHead()) ?? this._startingHead)\n\n // If we found a head\n if (isDefined(bestHeadChain)) {\n // Resolve the appropriate archivists\n const outArchivist = await this.resolveOutArchivist()\n\n const oldHeadBlock = this._startingHead?.[0]\n const newHydratedHeadBlock = assertEx(bestHeadChain.at(-1), () => 'Missing best head block [HeadValidationDiviner]')\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 this.logger?.debug('Validating new HeadBlock head from (block) ', oldHeadBlock?.block, 'to', newHeadBlock.block)\n this.logger?.debug('Validating new HeadBlock head from (hash) ', oldHeadBlock?._hash, 'to', newHeadBlock._hash)\n\n if (newHeadBlock._hash === oldHeadBlock?._hash) {\n this.logger?.debug('No new blocks found', oldHeadBlock?.block, 'to', newHeadBlock.block)\n return\n }\n\n // Validate it\n // const validationErrors = await spanRootAsync('validateHydratedBlock', async () => {\n // return await validateHydratedBlock(hydratedBlock, chainId)\n // }, this.tracer)\n // // Ensure no validation errors\n // if (validationErrors.length > 0) {\n // // TODO: Metrics here with error count\n // this.logger?.error('Block validation errors', hydratedBlock[0].block, hydratedBlock[0]._hash, validationErrors)\n // break\n // }\n\n // Store the items to be committed in the correct order\n const blocksToFinalize = bestHeadChain.filter((b) => {\n return isDefined(oldHeadBlock) ? b[0].block > oldHeadBlock.block : true\n })\n\n const payloadsToFinalize = blocksToFinalize.flatMap(b => flattenHydratedBlock(b))\n\n // Store metrics about the finalized block in the correct order to allow metrics for each block in this batch\n finalizedBlocksAttributes = [{ producer: toAddress(newHeadBlock.addresses[0]) }, ...finalizedBlocksAttributes]\n\n this.logger?.info('Validated new HeadBlock head from (block) in', `${Date.now() - start}ms`, newHeadBlock.block, 'to', oldHeadBlock?.block)\n this.logger?.info('Validated new HeadBlock head from (hash) in', `${Date.now() - start}ms`, newHeadBlock._hash, 'to', oldHeadBlock?._hash)\n\n await this.spanAsync('HeadValidationDiviner:commitToOutArchivist', async () => {\n if (payloadsToFinalize.length === 0) {\n return\n }\n\n await outArchivist.insert(payloadsToFinalize)\n for (const finalizedBlockAttributes of finalizedBlocksAttributes) {\n this._headValidationDivinerHeadUpdateTotal?.add(1, finalizedBlockAttributes)\n }\n }, this.context)\n\n // Prevent us from rechecking the same head\n await this.headSelector.finalizeChainFragment(blocksToFinalize)\n\n this._startingHead = newHydratedHeadBlock\n\n // Return the finalized payloads\n return payloadsToFinalize\n }\n // If no head was found, return an empty array\n this.logger?.info('No head found to validate', this._startingHead?.[0]._hash)\n } catch (ex) {\n this.logger?.error('Error in divineHandler', ex)\n }\n }, this.context)) ?? []\n })\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { assertEx } from '@ariestools/sdk'\nimport type {\n AnyConfigSchema, ArchivistInstance,\n Payload, Schema, Sequence,\n WitnessConfig, WitnessModule, WitnessParams,\n} from '@xyo-network/sdk'\nimport {\n AbstractWitness, asArchivistInstance, asSchema,\n} from '@xyo-network/sdk'\n\nexport const ArchivistNextWitnessConfigSchema = asSchema('network.xyo.witness.archivist.next.config', true)\nexport type ArchivistNextWitnessConfigSchema = typeof ArchivistNextWitnessConfigSchema\n\nexport type ArchivistNextWitnessConfig = WitnessConfig<{\n schema: ArchivistNextWitnessConfigSchema\n sourceArchivist?: Address\n}>\n\nexport type ArchivistNextWitnessParams = WitnessParams<AnyConfigSchema<ArchivistNextWitnessConfig>>\n\nexport class ArchivistNextWitness<TParams extends ArchivistNextWitnessParams = ArchivistNextWitnessParams>\n extends AbstractWitness<TParams> implements WitnessModule {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, ArchivistNextWitnessConfigSchema]\n static override readonly defaultConfigSchema: Schema = ArchivistNextWitnessConfigSchema\n\n private _cursor?: Sequence\n\n async getSourceArchivist(): Promise<ArchivistInstance> {\n return assertEx(asArchivistInstance(\n await this.resolve(assertEx(this.config.sourceArchivist, () => 'Missing sourceArchivist')),\n ), () => 'Invalid sourceArchivist')\n }\n\n protected override async observeHandler(): Promise<Payload[]> {\n const archivist = await this.getSourceArchivist()\n const payloads = await archivist.next({ cursor: this._cursor, order: 'asc' })\n const lastPayload = payloads.at(-1)\n if (lastPayload) {\n this._cursor = lastPayload._sequence\n }\n return payloads\n }\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { AsObjectFactory } from '@ariestools/sdk'\nimport {\n asSchema, isPayloadOfSchemaType, type Payload,\n} from '@xyo-network/sdk'\n\nexport const WeightedNetworkStakeSchema = asSchema('network.xyo.witness.chain.stake.network.weighted', true)\nexport type WeightedNetworkStakeSchema = typeof WeightedNetworkStakeSchema\n\nexport type WeightedNetworkStake = Payload<{\n amount: bigint\n blockRange: [number, number]\n staker: Address\n}, WeightedNetworkStakeSchema>\n\nexport const isWeightedNetworkStake = isPayloadOfSchemaType<WeightedNetworkStake>(WeightedNetworkStakeSchema)\n\nexport const asWeightedNetworkStakePayload = AsObjectFactory.create(isWeightedNetworkStake)\nexport const asWeightedNetworkStakePayloadWithStorageMeta = AsObjectFactory.create(isWeightedNetworkStake)\n", "import type { Address } from '@ariestools/sdk'\nimport { AsObjectFactory } from '@ariestools/sdk'\nimport {\n asSchema, isPayloadOfSchemaType, type Payload,\n} from '@xyo-network/sdk'\n\nexport const NetworkStakeObserveSchema = asSchema('network.xyo.witness.chain.stake.network.observe', true)\nexport type NetworkStakeObserveSchema = typeof NetworkStakeObserveSchema\n\nexport type NetworkStakeObserve = Payload<{\n blockRange: [number, number]\n staked: Address\n staker: Address\n}, NetworkStakeObserveSchema>\n\nexport const isNetworkStakeObserve = isPayloadOfSchemaType<NetworkStakeObserve>(NetworkStakeObserveSchema)\n\nexport const asNetworkStakeObservePayload = AsObjectFactory.create(isNetworkStakeObserve)\nexport const asNetworkStakeObservePayloadWithStorageMeta = AsObjectFactory.create(isNetworkStakeObserve)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["asSchema", "asSchema", "assertEx", "isDefined", "AbstractDiviner", "asSchema", "creatableModule", "asSchema", "AbstractDiviner", "assertEx", "isDefined", "creatableModule", "assertEx", "asArchivistInstance", "asSchema", "AsObjectFactory", "asSchema", "isPayloadOfSchemaType", "AsObjectFactory", "asSchema", "isPayloadOfSchemaType"]
|
|
7
7
|
}
|
|
@@ -132,7 +132,7 @@ async function buildBlock(options) {
|
|
|
132
132
|
step_hashes,
|
|
133
133
|
protocol,
|
|
134
134
|
...supersedesField(options)
|
|
135
|
-
}).meta({ $
|
|
135
|
+
}).meta({ $signatures: [] }).signers(signers).payloads(await PayloadBuilder.addStorageMeta(payloads)).build();
|
|
136
136
|
assertEx(isBlockBoundWitness(bw), () => "Build of BlockBoundWitness failed");
|
|
137
137
|
return [await PayloadBuilder.addStorageMeta(bw), txPayloads];
|
|
138
138
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/modules/protocol/block/buildBlock.ts", "../../src/modules/protocol/block/BuildBlockOptions.ts", "../../src/modules/protocol/block/buildGenesisBlock.ts", "../../src/modules/protocol/block/buildNextBlock.ts", "../../src/modules/protocol/block/createGenesisBlock.ts", "../../src/modules/protocol/block/createProducerChainStakeIntentTransaction.ts", "../../src/modules/protocol/block/sort.ts", "../../src/modules/protocol/frameList.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Hash, Hex } from '@ariestools/sdk'\nimport { assertEx, isDefined } from '@ariestools/sdk'\nimport type { AnyPayload, WithStorageMeta } from '@xyo-network/sdk'\nimport {\n asAnyPayload, BoundWitnessBuilder, PayloadBuilder,\n} from '@xyo-network/sdk'\nimport type {\n BlockBoundWitness, SignedHydratedBlockWithHashMeta, Transfer,\n} from '@xyo-network/xl1-sdk'\nimport {\n asXL1BlockNumber,\n AttoXL1,\n createTransferPayload,\n isBlockBoundWitness,\n rewardAddressFromStepIdentity,\n StepRewardFractions, StepSizes,\n validateTransactionsOpcodes,\n XL1_PROTOCOL_VERSION, XYO_STEP_REWARD_ADDRESS, XYO_ZERO_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport {\n type BuildBlockOptions, isBuildGenesisBlockOptions, isBuildNextBlockOptions,\n} from './BuildBlockOptions.ts'\n\n/*\n//this is for testing only to speed up the pace\nexport const StepRewardFractions = [\n [0n, 1n], // 0%\n [1n, 10_000n], // 0.01%\n [2n, 1000n], // 0.2%\n [3n, 100n], // 3%\n [45n, 100n], // 45%\n] as const\n */\n\nfunction calculateCompletedStepReward(step: number, balance: AttoXL1): AttoXL1 {\n return AttoXL1(StepRewardFractions[step][0] * balance / StepRewardFractions[step][1])\n}\n\n/**\n * The supersedes entry for the signed fields, empty when nothing is superseded.\n *\n * Spread rather than assigned, because an absent supersedes has to stay absent from the signed\n * fields \u2014 a key present with an undefined value would change the hash of every block ever built.\n */\nfunction supersedesField(options: BuildBlockOptions): { supersedes?: Hash } {\n return isBuildNextBlockOptions(options) && options.supersedes !== undefined\n ? { supersedes: options.supersedes }\n : {}\n}\n\nexport async function buildBlock(options: BuildBlockOptions): Promise<SignedHydratedBlockWithHashMeta> {\n const previousBlockNumber = isBuildGenesisBlockOptions(options) ? -1 : options.previousBlockNumber\n const blockNumber = asXL1BlockNumber(previousBlockNumber + 1, true)\n const inStepHashes = isBuildNextBlockOptions(options) ? options.previousStepHashes : []\n const previousBlockHash = isBuildNextBlockOptions(options) ? options.previousBlockHash : undefined\n const stepRewardPoolBalance = isBuildNextBlockOptions(options) ? options.stepRewardPoolBalance : AttoXL1(0n)\n const {\n chainId, txs,\n chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS,\n blockPayloads, protocol = XL1_PROTOCOL_VERSION, signers,\n } = options\n const step_hashes: Hex[] = []\n\n for (const [tx] of txs) {\n if (tx.nbf > blockNumber) {\n throw new Error(`Transaction ${await PayloadBuilder.hash(tx)} not valid for block ${blockNumber} - NBF is ${tx.nbf}`)\n }\n if (tx.exp < blockNumber) {\n throw new Error(`Transaction ${await PayloadBuilder.hash(tx)} not valid for block ${blockNumber} - EXP is ${tx.exp}`)\n }\n }\n\n const completedStepRewardTransfers: Transfer[] = []\n\n // update the step hashes\n for (const [i, step] of StepSizes.entries()) {\n if (blockNumber < step) {\n break\n }\n if (blockNumber % step === 0) {\n if (StepRewardFractions[i][0] > 0 && chainStepRewardAddress !== XYO_ZERO_ADDRESS) {\n const completedStepRewardHolderAddress = rewardAddressFromStepIdentity({ block: blockNumber, step })\n const completedStepReward = calculateCompletedStepReward(i, stepRewardPoolBalance)\n completedStepRewardTransfers.push(createTransferPayload(chainStepRewardAddress, { [completedStepRewardHolderAddress]: completedStepReward }))\n }\n step_hashes.push(assertEx(previousBlockHash, () => `Previous block hash is required for step ${step} at block ${blockNumber}`))\n } else {\n if (isDefined(inStepHashes.at(i))) {\n step_hashes.push(inStepHashes[i])\n }\n }\n }\n\n const previous = previousBlockHash ?? null\n const block = blockNumber\n const txElevatedPayloads = await validateTransactionsOpcodes(txs)\n\n const payloads = [\n ...txs.map(([tx]) => tx),\n ...blockPayloads,\n ...txElevatedPayloads,\n ...completedStepRewardTransfers,\n ].map(p => asAnyPayload(p, true))\n\n const boundWitnessBuilder = new BoundWitnessBuilder<BlockBoundWitness, WithStorageMeta<AnyPayload>>()\n const [bw, txPayloads] = await boundWitnessBuilder\n .fields({\n block,\n chain: chainId,\n previous,\n step_hashes,\n protocol,\n ...supersedesField(options),\n })\n .meta({ $epoch: Date.now(), $signatures: [] })\n .signers(signers)\n .payloads(await PayloadBuilder.addStorageMeta(payloads))\n .build()\n assertEx(isBlockBoundWitness(bw), () => 'Build of BlockBoundWitness failed')\n return [await PayloadBuilder.addStorageMeta(bw), txPayloads]\n}\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport {\n isAddress, isArray, isHash,\n isNumber, isObject,\n} from '@ariestools/sdk'\nimport type { AccountInstance } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, AttoXL1, ChainId, SignedHydratedTransaction,\n XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\n\nexport interface BaseBuildBlockOptions {\n blockPayloads: AllowedBlockPayload[]\n chainId: ChainId\n chainStepRewardAddress?: Address\n previousBlockNumber?: XL1BlockNumber\n protocol?: number\n signers: AccountInstance[]\n txs: SignedHydratedTransaction[]\n}\n\nexport const isBaseBuildBlockOptions = (value: unknown): value is BaseBuildBlockOptions => {\n if (!isObject(value)) {\n return false\n }\n const typedValue = value as BaseBuildBlockOptions\n if (!isArray(typedValue.blockPayloads) || !isAddress(typedValue.chainId) || !isArray(typedValue.signers) || !isArray(typedValue.txs)) {\n return false\n }\n return true\n}\n\nexport interface BuildGenesisBlockOptions extends BaseBuildBlockOptions {\n previousBlockHash: null\n}\n\nexport const isBuildGenesisBlockOptions = (value: unknown): value is BuildGenesisBlockOptions => {\n if (!isBaseBuildBlockOptions(value)) {\n return false\n }\n const typedValue = value as BuildGenesisBlockOptions\n if (typedValue.previousBlockHash !== null) {\n return false\n }\n if (typedValue.previousBlockNumber !== undefined) {\n return false\n }\n return true\n}\n\nexport interface BuildNextBlockOptions extends BaseBuildBlockOptions {\n previousBlockHash: Hash\n previousBlockNumber: XL1BlockNumber\n previousStepHashes: Hash[]\n stepRewardPoolBalance: AttoXL1\n /**\n * Hash of this producer's own earlier candidate at the same height and parent, when re-proposing.\n *\n * Signed, so it cannot be added or dropped after the fact. Its whole job is to make honest\n * re-proposal distinguishable from equivocation: two differing candidates at one height are\n * indistinguishable from outside unless the later one says which one it replaces.\n */\n supersedes?: Hash\n}\n\nexport const isBuildNextBlockOptions = (value: unknown): value is BuildNextBlockOptions => {\n if (!isBaseBuildBlockOptions(value)) {\n return false\n }\n const typedValue = value as BuildNextBlockOptions\n if (!isHash(typedValue.previousBlockHash)) {\n return false\n }\n if (!isNumber(typedValue.previousBlockNumber)) {\n return false\n }\n if (!isArray(typedValue.previousStepHashes)) {\n return false\n }\n return true\n}\n\nexport type BuildBlockOptions = BuildGenesisBlockOptions | BuildNextBlockOptions\n", "import type { AccountInstance } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, ChainId,\n SignedHydratedBlockWithHashMeta,\n SignedHydratedTransactionWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { XYO_ZERO_ADDRESS } from '@xyo-network/xl1-sdk'\n\nimport { buildBlock } from './buildBlock.ts'\n\nexport async function buildGenesisBlock(\n chainId: ChainId,\n txs: SignedHydratedTransactionWithHashMeta[],\n blockPayloads: AllowedBlockPayload[],\n signers: AccountInstance[],\n chainStepRewardAddress = XYO_ZERO_ADDRESS,\n protocol?: number,\n): Promise<SignedHydratedBlockWithHashMeta> {\n return await buildBlock({\n previousBlockHash: null,\n chainId,\n txs,\n blockPayloads,\n signers,\n chainStepRewardAddress,\n protocol,\n })\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport type { AccountInstance, WithHashMeta } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, BlockBoundWitness,\n ChainId,\n SignedHydratedBlockWithHashMeta,\n SignedHydratedTransaction,\n} from '@xyo-network/xl1-sdk'\nimport {\n AttoXL1,\n XYO_STEP_REWARD_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport { buildBlock } from './buildBlock.ts'\n\nexport async function buildNextBlock(\n previousBlock: WithHashMeta<BlockBoundWitness>,\n txs: SignedHydratedTransaction[],\n blockPayloads: AllowedBlockPayload[],\n signers: AccountInstance[],\n chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS,\n stepRewardPoolBalance: AttoXL1 = AttoXL1(0n),\n protocol?: number,\n chainId?: ChainId,\n supersedes?: Hash,\n): Promise<SignedHydratedBlockWithHashMeta> {\n return await buildBlock({\n chainId: chainId ?? previousBlock.chain,\n previousBlockNumber: previousBlock.block,\n previousStepHashes: previousBlock.step_hashes ?? [],\n previousBlockHash: previousBlock._hash,\n txs,\n blockPayloads,\n signers,\n protocol,\n chainStepRewardAddress,\n stepRewardPoolBalance,\n supersedes,\n })\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { toAddress } from '@ariestools/sdk'\nimport type {\n AccountInstance, WithHashMeta, XyoAddress,\n} from '@xyo-network/sdk'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, ChainId,\n SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport {\n BlockBoundWitnessSchemaPayload, BlockBoundWitnessWithStorageMetaSchemaPayload,\n ChainStakeIntentPayloadJsonSchemaPayload,\n createTransferPayload,\n HashPayloadJsonSchemaPayload,\n TransactionBoundWitnessSchemaPayload, TransactionBoundWitnessWithStorageMetaSchemaPayload, TransferPayloadJsonSchemaPayload,\n} from '@xyo-network/xl1-sdk'\n\nimport { buildGenesisBlock } from './buildGenesisBlock.ts'\nimport { createProducerChainStakeIntent } from './createProducerChainStakeIntentTransaction.ts'\n\nexport const createGenesisBlock = async (\n initialBlockProducer: AccountInstance,\n nextContractAddress: ChainId,\n genesisBlockRewardAmount: bigint,\n genesisBlockRewardAddress: XyoAddress,\n): Promise<SignedHydratedBlockWithHashMeta> => {\n const blockPayloads: WithHashMeta<AllowedBlockPayload>[] = await PayloadBuilder.addHashMeta([\n TransferPayloadJsonSchemaPayload,\n BlockBoundWitnessSchemaPayload,\n BlockBoundWitnessWithStorageMetaSchemaPayload,\n TransactionBoundWitnessSchemaPayload,\n TransactionBoundWitnessWithStorageMetaSchemaPayload,\n ChainStakeIntentPayloadJsonSchemaPayload,\n HashPayloadJsonSchemaPayload,\n ])\n const intentPayload = await createProducerChainStakeIntent(toAddress(initialBlockProducer.address), 1, 0)\n blockPayloads.push(intentPayload)\n if (genesisBlockRewardAmount > 0n) {\n blockPayloads.push(await PayloadBuilder.addHashMeta(createTransferPayload(\n nextContractAddress as Address,\n { [genesisBlockRewardAddress]: genesisBlockRewardAmount },\n )))\n }\n return await buildGenesisBlock(nextContractAddress, [], blockPayloads, [initialBlockProducer])\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { toAddress } from '@ariestools/sdk'\nimport type { AccountInstance } from '@xyo-network/sdk'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n ChainId,\n ChainStakeIntent,\n HydratedTransactionWithHashMeta,\n XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\nimport {\n asXL1BlockNumber, buildTransaction,\n ChainStakeIntentSchema, defaultTransactionFees,\n} from '@xyo-network/xl1-sdk'\n\nexport async function createProducerChainStakeIntent(from: Address, exp: number, nbf = 0) {\n const builder = new PayloadBuilder<ChainStakeIntent>({ schema: ChainStakeIntentSchema })\n return await PayloadBuilder.addHashMeta(builder.fields({\n from,\n exp,\n nbf,\n intent: 'producer',\n }).build())\n}\n\nexport async function createProducerChainStakeIntentTransaction(\n chain: ChainId,\n signers: AccountInstance[] = [],\n producer: Address,\n exp: XL1BlockNumber,\n nbf = asXL1BlockNumber(0, true),\n fees = defaultTransactionFees,\n): Promise<HydratedTransactionWithHashMeta> {\n // Create staked intents for all the block producers declaring their intent to produce blocks\n const intent = await createProducerChainStakeIntent(producer, exp, nbf)\n const tx = await buildTransaction(\n chain,\n [intent],\n [],\n signers,\n nbf,\n exp,\n toAddress(signers[0].address),\n fees,\n )\n return tx\n}\n", "import type { BlockBoundWitness } from '@xyo-network/xl1-sdk'\n\nexport type BlockBoundWitnessComparator = (a: BlockBoundWitness, b: BlockBoundWitness) => number\n\nexport const sortBlocksAscending: BlockBoundWitnessComparator = (a, b) => {\n const compared = a.block - b.block\n return compared > 0 ? 1 : compared < 0 ? -1 : 0\n}\n\nexport const sortBlocksDescending: BlockBoundWitnessComparator = (first, second) => sortBlocksAscending(second, first)\n\nexport const sortBlocks = (\n blocks: BlockBoundWitness[],\n compareFn: BlockBoundWitnessComparator = sortBlocksAscending,\n): BlockBoundWitness[] => blocks.toSorted(compareFn)\n\nexport const toSortedBlocks = (\n blocks: BlockBoundWitness[],\n compareFn: BlockBoundWitnessComparator = sortBlocksAscending,\n): BlockBoundWitness[] => sortBlocks([...blocks], compareFn)\n", "import type { Hash } from '@ariestools/sdk'\nimport type { ReadArchivist } from '@xyo-network/sdk'\nimport {\n asBlockBoundWitnessWithStorageMeta, type BlockBoundWitness, StepSizes,\n} from '@xyo-network/xl1-sdk'\n\n// This function is not yet complete and definitely not tested, so do not use!\n\nfunction shouldStopAtBreak(blockToCheck: BlockBoundWitness, breaks: (Hash | null)[], breakIndex: number): boolean {\n const breakHash = breaks[breakIndex]\n if (breakHash === null) return false\n return blockToCheck.step_hashes?.at(breakIndex) === breakHash\n}\n\nfunction hasBreakForBlock(blockToCheck: BlockBoundWitness, breaks: (Hash | null)[]): boolean {\n for (const [i] of breaks.entries()) {\n if (shouldStopAtBreak(blockToCheck, breaks, i)) {\n return true\n }\n }\n return false\n}\n\nasync function collectStepHashes(\n block: BlockBoundWitness,\n stepIndex: number,\n archivist: ReadArchivist,\n breaks: (Hash | null)[],\n): Promise<Hash[]> {\n const stepHashes: Hash[] = []\n let blockToCheck: BlockBoundWitness | undefined = block\n while (blockToCheck) {\n const stepHash: Hash | undefined = blockToCheck.step_hashes?.at(stepIndex)\n if (stepHash === undefined) {\n break\n }\n if (hasBreakForBlock(blockToCheck, breaks)) {\n break\n }\n stepHashes.push(stepHash)\n const archivistResult = await archivist.get([stepHash])\n blockToCheck = asBlockBoundWitnessWithStorageMeta(archivistResult.at(0))\n }\n return stepHashes\n}\n\n// goal is to return an array of arrays of all the step hashes that we should get to have the full history of the block\n// it will leave a gap from the end of the frame list to the head (unless the head just rolled a frame) and gaps between some frames\nexport async function frameList(block: BlockBoundWitness, archivist: ReadArchivist): Promise<Hash[][]> {\n const result: Hash[][] = []\n const stepSizes = [...StepSizes]\n // when to stop for smaller steps, i.e. a large step already has the block\n const breaks: (Hash | null)[] = Array.from({ length: StepSizes.length }, () => null)\n while (stepSizes.length > 0) {\n stepSizes.pop()\n const stepIndex = stepSizes.length\n const stepHashes = await collectStepHashes(block, stepIndex, archivist, breaks)\n result.unshift(stepHashes)\n }\n return result\n}\n"],
|
|
5
|
-
"mappings": ";AACA,SAAS,UAAU,iBAAiB;AAEpC;AAAA,EACE;AAAA,EAAc;AAAA,EAAqB;AAAA,OAC9B;AAIP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAAqB;AAAA,EACrB;AAAA,EACA;AAAA,EAAsB;AAAA,EAAyB;AAAA,OAC1C;;;ACjBP;AAAA,EACE;AAAA,EAAW;AAAA,EAAS;AAAA,EACpB;AAAA,EAAU;AAAA,OACL;AAiBA,IAAM,0BAA0B,CAAC,UAAmD;AACzF,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO;AAAA,EACT;AACA,QAAM,aAAa;AACnB,MAAI,CAAC,QAAQ,WAAW,aAAa,KAAK,CAAC,UAAU,WAAW,OAAO,KAAK,CAAC,QAAQ,WAAW,OAAO,KAAK,CAAC,QAAQ,WAAW,GAAG,GAAG;AACpI,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,IAAM,6BAA6B,CAAC,UAAsD;AAC/F,MAAI,CAAC,wBAAwB,KAAK,GAAG;AACnC,WAAO;AAAA,EACT;AACA,QAAM,aAAa;AACnB,MAAI,WAAW,sBAAsB,MAAM;AACzC,WAAO;AAAA,EACT;AACA,MAAI,WAAW,wBAAwB,QAAW;AAChD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAiBO,IAAM,0BAA0B,CAAC,UAAmD;AACzF,MAAI,CAAC,wBAAwB,KAAK,GAAG;AACnC,WAAO;AAAA,EACT;AACA,QAAM,aAAa;AACnB,MAAI,CAAC,OAAO,WAAW,iBAAiB,GAAG;AACzC,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS,WAAW,mBAAmB,GAAG;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,CAAC,QAAQ,WAAW,kBAAkB,GAAG;AAC3C,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AD7CA,SAAS,6BAA6B,MAAc,SAA2B;AAC7E,SAAO,QAAQ,oBAAoB,IAAI,EAAE,CAAC,IAAI,UAAU,oBAAoB,IAAI,EAAE,CAAC,CAAC;AACtF;AAQA,SAAS,gBAAgB,SAAmD;AAC1E,SAAO,wBAAwB,OAAO,KAAK,QAAQ,eAAe,SAC9D,EAAE,YAAY,QAAQ,WAAW,IACjC,CAAC;AACP;AAEA,eAAsB,WAAW,SAAsE;AACrG,QAAM,sBAAsB,2BAA2B,OAAO,IAAI,KAAK,QAAQ;AAC/E,QAAM,cAAc,iBAAiB,sBAAsB,GAAG,IAAI;AAClE,QAAM,eAAe,wBAAwB,OAAO,IAAI,QAAQ,qBAAqB,CAAC;AACtF,QAAM,oBAAoB,wBAAwB,OAAO,IAAI,QAAQ,oBAAoB;AACzF,QAAM,wBAAwB,wBAAwB,OAAO,IAAI,QAAQ,wBAAwB,QAAQ,EAAE;AAC3G,QAAM;AAAA,IACJ;AAAA,IAAS;AAAA,IACT,yBAAyB;AAAA,IACzB;AAAA,IAAe,WAAW;AAAA,IAAsB;AAAA,EAClD,IAAI;AACJ,QAAM,cAAqB,CAAC;AAE5B,aAAW,CAAC,EAAE,KAAK,KAAK;AACtB,QAAI,GAAG,MAAM,aAAa;AACxB,YAAM,IAAI,MAAM,eAAe,MAAM,eAAe,KAAK,EAAE,CAAC,wBAAwB,WAAW,aAAa,GAAG,GAAG,EAAE;AAAA,IACtH;AACA,QAAI,GAAG,MAAM,aAAa;AACxB,YAAM,IAAI,MAAM,eAAe,MAAM,eAAe,KAAK,EAAE,CAAC,wBAAwB,WAAW,aAAa,GAAG,GAAG,EAAE;AAAA,IACtH;AAAA,EACF;AAEA,QAAM,+BAA2C,CAAC;AAGlD,aAAW,CAAC,GAAG,IAAI,KAAK,UAAU,QAAQ,GAAG;AAC3C,QAAI,cAAc,MAAM;AACtB;AAAA,IACF;AACA,QAAI,cAAc,SAAS,GAAG;AAC5B,UAAI,oBAAoB,CAAC,EAAE,CAAC,IAAI,KAAK,2BAA2B,kBAAkB;AAChF,cAAM,mCAAmC,8BAA8B,EAAE,OAAO,aAAa,KAAK,CAAC;AACnG,cAAM,sBAAsB,6BAA6B,GAAG,qBAAqB;AACjF,qCAA6B,KAAK,sBAAsB,wBAAwB,EAAE,CAAC,gCAAgC,GAAG,oBAAoB,CAAC,CAAC;AAAA,MAC9I;AACA,kBAAY,KAAK,SAAS,mBAAmB,MAAM,4CAA4C,IAAI,aAAa,WAAW,EAAE,CAAC;AAAA,IAChI,OAAO;AACL,UAAI,UAAU,aAAa,GAAG,CAAC,CAAC,GAAG;AACjC,oBAAY,KAAK,aAAa,CAAC,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,qBAAqB;AACtC,QAAM,QAAQ;AACd,QAAM,qBAAqB,MAAM,4BAA4B,GAAG;AAEhE,QAAM,WAAW;AAAA,IACf,GAAG,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE;AAAA,IACvB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,EAAE,IAAI,OAAK,aAAa,GAAG,IAAI,CAAC;AAEhC,QAAM,sBAAsB,IAAI,oBAAoE;AACpG,QAAM,CAAC,IAAI,UAAU,IAAI,MAAM,oBAC5B,OAAO;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,gBAAgB,OAAO;AAAA,EAC5B,CAAC,
|
|
4
|
+
"sourcesContent": ["import type { Hash, Hex } from '@ariestools/sdk'\nimport { assertEx, isDefined } from '@ariestools/sdk'\nimport type { AnyPayload, WithStorageMeta } from '@xyo-network/sdk'\nimport {\n asAnyPayload, BoundWitnessBuilder, PayloadBuilder,\n} from '@xyo-network/sdk'\nimport type {\n BlockBoundWitness, SignedHydratedBlockWithHashMeta, Transfer,\n} from '@xyo-network/xl1-sdk'\nimport {\n asXL1BlockNumber,\n AttoXL1,\n createTransferPayload,\n isBlockBoundWitness,\n rewardAddressFromStepIdentity,\n StepRewardFractions, StepSizes,\n validateTransactionsOpcodes,\n XL1_PROTOCOL_VERSION, XYO_STEP_REWARD_ADDRESS, XYO_ZERO_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport {\n type BuildBlockOptions, isBuildGenesisBlockOptions, isBuildNextBlockOptions,\n} from './BuildBlockOptions.ts'\n\n/*\n//this is for testing only to speed up the pace\nexport const StepRewardFractions = [\n [0n, 1n], // 0%\n [1n, 10_000n], // 0.01%\n [2n, 1000n], // 0.2%\n [3n, 100n], // 3%\n [45n, 100n], // 45%\n] as const\n */\n\nfunction calculateCompletedStepReward(step: number, balance: AttoXL1): AttoXL1 {\n return AttoXL1(StepRewardFractions[step][0] * balance / StepRewardFractions[step][1])\n}\n\n/**\n * The supersedes entry for the signed fields, empty when nothing is superseded.\n *\n * Spread rather than assigned, because an absent supersedes has to stay absent from the signed\n * fields \u2014 a key present with an undefined value would change the hash of every block ever built.\n */\nfunction supersedesField(options: BuildBlockOptions): { supersedes?: Hash } {\n return isBuildNextBlockOptions(options) && options.supersedes !== undefined\n ? { supersedes: options.supersedes }\n : {}\n}\n\nexport async function buildBlock(options: BuildBlockOptions): Promise<SignedHydratedBlockWithHashMeta> {\n const previousBlockNumber = isBuildGenesisBlockOptions(options) ? -1 : options.previousBlockNumber\n const blockNumber = asXL1BlockNumber(previousBlockNumber + 1, true)\n const inStepHashes = isBuildNextBlockOptions(options) ? options.previousStepHashes : []\n const previousBlockHash = isBuildNextBlockOptions(options) ? options.previousBlockHash : undefined\n const stepRewardPoolBalance = isBuildNextBlockOptions(options) ? options.stepRewardPoolBalance : AttoXL1(0n)\n const {\n chainId, txs,\n chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS,\n blockPayloads, protocol = XL1_PROTOCOL_VERSION, signers,\n } = options\n const step_hashes: Hex[] = []\n\n for (const [tx] of txs) {\n if (tx.nbf > blockNumber) {\n throw new Error(`Transaction ${await PayloadBuilder.hash(tx)} not valid for block ${blockNumber} - NBF is ${tx.nbf}`)\n }\n if (tx.exp < blockNumber) {\n throw new Error(`Transaction ${await PayloadBuilder.hash(tx)} not valid for block ${blockNumber} - EXP is ${tx.exp}`)\n }\n }\n\n const completedStepRewardTransfers: Transfer[] = []\n\n // update the step hashes\n for (const [i, step] of StepSizes.entries()) {\n if (blockNumber < step) {\n break\n }\n if (blockNumber % step === 0) {\n if (StepRewardFractions[i][0] > 0 && chainStepRewardAddress !== XYO_ZERO_ADDRESS) {\n const completedStepRewardHolderAddress = rewardAddressFromStepIdentity({ block: blockNumber, step })\n const completedStepReward = calculateCompletedStepReward(i, stepRewardPoolBalance)\n completedStepRewardTransfers.push(createTransferPayload(chainStepRewardAddress, { [completedStepRewardHolderAddress]: completedStepReward }))\n }\n step_hashes.push(assertEx(previousBlockHash, () => `Previous block hash is required for step ${step} at block ${blockNumber}`))\n } else {\n if (isDefined(inStepHashes.at(i))) {\n step_hashes.push(inStepHashes[i])\n }\n }\n }\n\n const previous = previousBlockHash ?? null\n const block = blockNumber\n const txElevatedPayloads = await validateTransactionsOpcodes(txs)\n\n const payloads = [\n ...txs.map(([tx]) => tx),\n ...blockPayloads,\n ...txElevatedPayloads,\n ...completedStepRewardTransfers,\n ].map(p => asAnyPayload(p, true))\n\n const boundWitnessBuilder = new BoundWitnessBuilder<BlockBoundWitness, WithStorageMeta<AnyPayload>>()\n const [bw, txPayloads] = await boundWitnessBuilder\n .fields({\n block,\n chain: chainId,\n previous,\n step_hashes,\n protocol,\n ...supersedesField(options),\n })\n // no `$epoch`: it was unsigned client meta, and the signed time payload carries the block's epoch\n .meta({ $signatures: [] })\n .signers(signers)\n .payloads(await PayloadBuilder.addStorageMeta(payloads))\n .build()\n assertEx(isBlockBoundWitness(bw), () => 'Build of BlockBoundWitness failed')\n return [await PayloadBuilder.addStorageMeta(bw), txPayloads]\n}\n", "import type { Address, Hash } from '@ariestools/sdk'\nimport {\n isAddress, isArray, isHash,\n isNumber, isObject,\n} from '@ariestools/sdk'\nimport type { AccountInstance } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, AttoXL1, ChainId, SignedHydratedTransaction,\n XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\n\nexport interface BaseBuildBlockOptions {\n blockPayloads: AllowedBlockPayload[]\n chainId: ChainId\n chainStepRewardAddress?: Address\n previousBlockNumber?: XL1BlockNumber\n protocol?: number\n signers: AccountInstance[]\n txs: SignedHydratedTransaction[]\n}\n\nexport const isBaseBuildBlockOptions = (value: unknown): value is BaseBuildBlockOptions => {\n if (!isObject(value)) {\n return false\n }\n const typedValue = value as BaseBuildBlockOptions\n if (!isArray(typedValue.blockPayloads) || !isAddress(typedValue.chainId) || !isArray(typedValue.signers) || !isArray(typedValue.txs)) {\n return false\n }\n return true\n}\n\nexport interface BuildGenesisBlockOptions extends BaseBuildBlockOptions {\n previousBlockHash: null\n}\n\nexport const isBuildGenesisBlockOptions = (value: unknown): value is BuildGenesisBlockOptions => {\n if (!isBaseBuildBlockOptions(value)) {\n return false\n }\n const typedValue = value as BuildGenesisBlockOptions\n if (typedValue.previousBlockHash !== null) {\n return false\n }\n if (typedValue.previousBlockNumber !== undefined) {\n return false\n }\n return true\n}\n\nexport interface BuildNextBlockOptions extends BaseBuildBlockOptions {\n previousBlockHash: Hash\n previousBlockNumber: XL1BlockNumber\n previousStepHashes: Hash[]\n stepRewardPoolBalance: AttoXL1\n /**\n * Hash of this producer's own earlier candidate at the same height and parent, when re-proposing.\n *\n * Signed, so it cannot be added or dropped after the fact. Its whole job is to make honest\n * re-proposal distinguishable from equivocation: two differing candidates at one height are\n * indistinguishable from outside unless the later one says which one it replaces.\n */\n supersedes?: Hash\n}\n\nexport const isBuildNextBlockOptions = (value: unknown): value is BuildNextBlockOptions => {\n if (!isBaseBuildBlockOptions(value)) {\n return false\n }\n const typedValue = value as BuildNextBlockOptions\n if (!isHash(typedValue.previousBlockHash)) {\n return false\n }\n if (!isNumber(typedValue.previousBlockNumber)) {\n return false\n }\n if (!isArray(typedValue.previousStepHashes)) {\n return false\n }\n return true\n}\n\nexport type BuildBlockOptions = BuildGenesisBlockOptions | BuildNextBlockOptions\n", "import type { AccountInstance } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, ChainId,\n SignedHydratedBlockWithHashMeta,\n SignedHydratedTransactionWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport { XYO_ZERO_ADDRESS } from '@xyo-network/xl1-sdk'\n\nimport { buildBlock } from './buildBlock.ts'\n\nexport async function buildGenesisBlock(\n chainId: ChainId,\n txs: SignedHydratedTransactionWithHashMeta[],\n blockPayloads: AllowedBlockPayload[],\n signers: AccountInstance[],\n chainStepRewardAddress = XYO_ZERO_ADDRESS,\n protocol?: number,\n): Promise<SignedHydratedBlockWithHashMeta> {\n return await buildBlock({\n previousBlockHash: null,\n chainId,\n txs,\n blockPayloads,\n signers,\n chainStepRewardAddress,\n protocol,\n })\n}\n", "import type { Hash } from '@ariestools/sdk'\nimport type { AccountInstance, WithHashMeta } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, BlockBoundWitness,\n ChainId,\n SignedHydratedBlockWithHashMeta,\n SignedHydratedTransaction,\n} from '@xyo-network/xl1-sdk'\nimport {\n AttoXL1,\n XYO_STEP_REWARD_ADDRESS,\n} from '@xyo-network/xl1-sdk'\n\nimport { buildBlock } from './buildBlock.ts'\n\nexport async function buildNextBlock(\n previousBlock: WithHashMeta<BlockBoundWitness>,\n txs: SignedHydratedTransaction[],\n blockPayloads: AllowedBlockPayload[],\n signers: AccountInstance[],\n chainStepRewardAddress = XYO_STEP_REWARD_ADDRESS,\n stepRewardPoolBalance: AttoXL1 = AttoXL1(0n),\n protocol?: number,\n chainId?: ChainId,\n supersedes?: Hash,\n): Promise<SignedHydratedBlockWithHashMeta> {\n return await buildBlock({\n chainId: chainId ?? previousBlock.chain,\n previousBlockNumber: previousBlock.block,\n previousStepHashes: previousBlock.step_hashes ?? [],\n previousBlockHash: previousBlock._hash,\n txs,\n blockPayloads,\n signers,\n protocol,\n chainStepRewardAddress,\n stepRewardPoolBalance,\n supersedes,\n })\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { toAddress } from '@ariestools/sdk'\nimport type {\n AccountInstance, WithHashMeta, XyoAddress,\n} from '@xyo-network/sdk'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n AllowedBlockPayload, ChainId,\n SignedHydratedBlockWithHashMeta,\n} from '@xyo-network/xl1-sdk'\nimport {\n BlockBoundWitnessSchemaPayload, BlockBoundWitnessWithStorageMetaSchemaPayload,\n ChainStakeIntentPayloadJsonSchemaPayload,\n createTransferPayload,\n HashPayloadJsonSchemaPayload,\n TransactionBoundWitnessSchemaPayload, TransactionBoundWitnessWithStorageMetaSchemaPayload, TransferPayloadJsonSchemaPayload,\n} from '@xyo-network/xl1-sdk'\n\nimport { buildGenesisBlock } from './buildGenesisBlock.ts'\nimport { createProducerChainStakeIntent } from './createProducerChainStakeIntentTransaction.ts'\n\nexport const createGenesisBlock = async (\n initialBlockProducer: AccountInstance,\n nextContractAddress: ChainId,\n genesisBlockRewardAmount: bigint,\n genesisBlockRewardAddress: XyoAddress,\n): Promise<SignedHydratedBlockWithHashMeta> => {\n const blockPayloads: WithHashMeta<AllowedBlockPayload>[] = await PayloadBuilder.addHashMeta([\n TransferPayloadJsonSchemaPayload,\n BlockBoundWitnessSchemaPayload,\n BlockBoundWitnessWithStorageMetaSchemaPayload,\n TransactionBoundWitnessSchemaPayload,\n TransactionBoundWitnessWithStorageMetaSchemaPayload,\n ChainStakeIntentPayloadJsonSchemaPayload,\n HashPayloadJsonSchemaPayload,\n ])\n const intentPayload = await createProducerChainStakeIntent(toAddress(initialBlockProducer.address), 1, 0)\n blockPayloads.push(intentPayload)\n if (genesisBlockRewardAmount > 0n) {\n blockPayloads.push(await PayloadBuilder.addHashMeta(createTransferPayload(\n nextContractAddress as Address,\n { [genesisBlockRewardAddress]: genesisBlockRewardAmount },\n )))\n }\n return await buildGenesisBlock(nextContractAddress, [], blockPayloads, [initialBlockProducer])\n}\n", "import type { Address } from '@ariestools/sdk'\nimport { toAddress } from '@ariestools/sdk'\nimport type { AccountInstance } from '@xyo-network/sdk'\nimport { PayloadBuilder } from '@xyo-network/sdk'\nimport type {\n ChainId,\n ChainStakeIntent,\n HydratedTransactionWithHashMeta,\n XL1BlockNumber,\n} from '@xyo-network/xl1-sdk'\nimport {\n asXL1BlockNumber, buildTransaction,\n ChainStakeIntentSchema, defaultTransactionFees,\n} from '@xyo-network/xl1-sdk'\n\nexport async function createProducerChainStakeIntent(from: Address, exp: number, nbf = 0) {\n const builder = new PayloadBuilder<ChainStakeIntent>({ schema: ChainStakeIntentSchema })\n return await PayloadBuilder.addHashMeta(builder.fields({\n from,\n exp,\n nbf,\n intent: 'producer',\n }).build())\n}\n\nexport async function createProducerChainStakeIntentTransaction(\n chain: ChainId,\n signers: AccountInstance[] = [],\n producer: Address,\n exp: XL1BlockNumber,\n nbf = asXL1BlockNumber(0, true),\n fees = defaultTransactionFees,\n): Promise<HydratedTransactionWithHashMeta> {\n // Create staked intents for all the block producers declaring their intent to produce blocks\n const intent = await createProducerChainStakeIntent(producer, exp, nbf)\n const tx = await buildTransaction(\n chain,\n [intent],\n [],\n signers,\n nbf,\n exp,\n toAddress(signers[0].address),\n fees,\n )\n return tx\n}\n", "import type { BlockBoundWitness } from '@xyo-network/xl1-sdk'\n\nexport type BlockBoundWitnessComparator = (a: BlockBoundWitness, b: BlockBoundWitness) => number\n\nexport const sortBlocksAscending: BlockBoundWitnessComparator = (a, b) => {\n const compared = a.block - b.block\n return compared > 0 ? 1 : compared < 0 ? -1 : 0\n}\n\nexport const sortBlocksDescending: BlockBoundWitnessComparator = (first, second) => sortBlocksAscending(second, first)\n\nexport const sortBlocks = (\n blocks: BlockBoundWitness[],\n compareFn: BlockBoundWitnessComparator = sortBlocksAscending,\n): BlockBoundWitness[] => blocks.toSorted(compareFn)\n\nexport const toSortedBlocks = (\n blocks: BlockBoundWitness[],\n compareFn: BlockBoundWitnessComparator = sortBlocksAscending,\n): BlockBoundWitness[] => sortBlocks([...blocks], compareFn)\n", "import type { Hash } from '@ariestools/sdk'\nimport type { ReadArchivist } from '@xyo-network/sdk'\nimport {\n asBlockBoundWitnessWithStorageMeta, type BlockBoundWitness, StepSizes,\n} from '@xyo-network/xl1-sdk'\n\n// This function is not yet complete and definitely not tested, so do not use!\n\nfunction shouldStopAtBreak(blockToCheck: BlockBoundWitness, breaks: (Hash | null)[], breakIndex: number): boolean {\n const breakHash = breaks[breakIndex]\n if (breakHash === null) return false\n return blockToCheck.step_hashes?.at(breakIndex) === breakHash\n}\n\nfunction hasBreakForBlock(blockToCheck: BlockBoundWitness, breaks: (Hash | null)[]): boolean {\n for (const [i] of breaks.entries()) {\n if (shouldStopAtBreak(blockToCheck, breaks, i)) {\n return true\n }\n }\n return false\n}\n\nasync function collectStepHashes(\n block: BlockBoundWitness,\n stepIndex: number,\n archivist: ReadArchivist,\n breaks: (Hash | null)[],\n): Promise<Hash[]> {\n const stepHashes: Hash[] = []\n let blockToCheck: BlockBoundWitness | undefined = block\n while (blockToCheck) {\n const stepHash: Hash | undefined = blockToCheck.step_hashes?.at(stepIndex)\n if (stepHash === undefined) {\n break\n }\n if (hasBreakForBlock(blockToCheck, breaks)) {\n break\n }\n stepHashes.push(stepHash)\n const archivistResult = await archivist.get([stepHash])\n blockToCheck = asBlockBoundWitnessWithStorageMeta(archivistResult.at(0))\n }\n return stepHashes\n}\n\n// goal is to return an array of arrays of all the step hashes that we should get to have the full history of the block\n// it will leave a gap from the end of the frame list to the head (unless the head just rolled a frame) and gaps between some frames\nexport async function frameList(block: BlockBoundWitness, archivist: ReadArchivist): Promise<Hash[][]> {\n const result: Hash[][] = []\n const stepSizes = [...StepSizes]\n // when to stop for smaller steps, i.e. a large step already has the block\n const breaks: (Hash | null)[] = Array.from({ length: StepSizes.length }, () => null)\n while (stepSizes.length > 0) {\n stepSizes.pop()\n const stepIndex = stepSizes.length\n const stepHashes = await collectStepHashes(block, stepIndex, archivist, breaks)\n result.unshift(stepHashes)\n }\n return result\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["XYO_ZERO_ADDRESS", "XYO_ZERO_ADDRESS", "AttoXL1", "XYO_STEP_REWARD_ADDRESS", "XYO_STEP_REWARD_ADDRESS", "AttoXL1", "toAddress", "PayloadBuilder", "createTransferPayload", "PayloadBuilder", "asXL1BlockNumber", "PayloadBuilder", "toAddress", "createTransferPayload", "StepSizes"]
|
|
7
7
|
}
|
|
@@ -174,7 +174,8 @@ async function processPendingBlocks({
|
|
|
174
174
|
observer,
|
|
175
175
|
admission,
|
|
176
176
|
eligibility,
|
|
177
|
-
publishAdmissionShadow
|
|
177
|
+
publishAdmissionShadow,
|
|
178
|
+
timeRules
|
|
178
179
|
}) {
|
|
179
180
|
const start = Date.now();
|
|
180
181
|
const currentBlock = await blockViewer.currentBlock();
|
|
@@ -190,7 +191,8 @@ async function processPendingBlocks({
|
|
|
190
191
|
minCandidates,
|
|
191
192
|
admission,
|
|
192
193
|
eligibility,
|
|
193
|
-
publishAdmissionShadow
|
|
194
|
+
publishAdmissionShadow,
|
|
195
|
+
timeRules
|
|
194
196
|
});
|
|
195
197
|
const bestHeadChain = await headSelector.findBestHead();
|
|
196
198
|
if (isDefined(bestHeadChain) && bestHeadChain.length > 0) {
|
|
@@ -492,6 +494,7 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider4 {
|
|
|
492
494
|
_blockValidationViewer;
|
|
493
495
|
_chainParamsViewer;
|
|
494
496
|
_finalizationViewer;
|
|
497
|
+
_headEpochCache;
|
|
495
498
|
_lastRejectedBuildAt = 0;
|
|
496
499
|
/** Cache of the last candidate this runner signed; the mempool is the source of truth. */
|
|
497
500
|
_lastSignedCandidate;
|
|
@@ -650,7 +653,7 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider4 {
|
|
|
650
653
|
const nonTxPayloads = [];
|
|
651
654
|
const producerRedeclarationPayload = await this.getProducerRedeclaration(head);
|
|
652
655
|
if (producerRedeclarationPayload) nonTxPayloads.push(producerRedeclarationPayload);
|
|
653
|
-
if (nextBlockTransactions.length === 0 && !this.heartbeatRequired(head)
|
|
656
|
+
if (nextBlockTransactions.length === 0 && !force && !await this.heartbeatRequired(head)) return;
|
|
654
657
|
const rewardTransferPayloads = await this.getBlockRewardTransfers(nextBlock);
|
|
655
658
|
nonTxPayloads.push(...rewardTransferPayloads);
|
|
656
659
|
const transactionTransfers = await generateTransactionFeeTransfers(this.address, nextBlockTransactions);
|
|
@@ -773,17 +776,45 @@ var SimpleBlockRunner = class extends AbstractCreatableProvider4 {
|
|
|
773
776
|
}
|
|
774
777
|
return timePayload;
|
|
775
778
|
}
|
|
779
|
+
/**
|
|
780
|
+
* The head's signed epoch, read once per head.
|
|
781
|
+
*
|
|
782
|
+
* It comes from the head's own time payload, by way of the time sync viewer, rather than from the
|
|
783
|
+
* unsigned `$epoch` meta on the bound witness: the finalizer paces heartbeats by the signed
|
|
784
|
+
* epoch, and a producer pacing itself by anything else would drift from what qualifies. The
|
|
785
|
+
* viewer may be remote, and a head lasts many ticks, so the answer is cached until the head moves.
|
|
786
|
+
* A read failure is not cached — the next tick asks again — and reads as "no epoch", which errs
|
|
787
|
+
* toward heartbeating rather than toward silence.
|
|
788
|
+
* @param head The current head block
|
|
789
|
+
* @returns The head's signed epoch, or undefined when the head carries none or it could not be read
|
|
790
|
+
*/
|
|
791
|
+
async headEpoch(head) {
|
|
792
|
+
const cached = this._headEpochCache;
|
|
793
|
+
if (cached?.hash === head._hash) return cached.epoch;
|
|
794
|
+
try {
|
|
795
|
+
const epoch = await this.timeSyncViewer.convertTime("xl1", "epoch", head.block);
|
|
796
|
+
if (epoch <= 0) return void 0;
|
|
797
|
+
this._headEpochCache = { epoch, hash: head._hash };
|
|
798
|
+
return epoch;
|
|
799
|
+
} catch (error) {
|
|
800
|
+
this.logger?.warn(`Could not read the head's signed epoch for heartbeat pacing: ${String(error)}`);
|
|
801
|
+
return void 0;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
776
804
|
/**
|
|
777
805
|
* Check if a heartbeat block is required based on network activity.
|
|
806
|
+
*
|
|
807
|
+
* A head with no signed epoch — the genesis block, or a head that predates the time payload —
|
|
808
|
+
* cannot be aged, and the chain needs a block to establish its clock, so a heartbeat is due at
|
|
809
|
+
* once rather than never. The finalizer's pacing agrees: it only paces against a head that has
|
|
810
|
+
* a signed epoch.
|
|
778
811
|
* @param head The current head block
|
|
779
812
|
* @returns True if a heartbeat is required, false otherwise
|
|
780
813
|
*/
|
|
781
|
-
heartbeatRequired(head) {
|
|
782
|
-
const epoch = head
|
|
783
|
-
if (isDefined3(epoch)
|
|
784
|
-
|
|
785
|
-
}
|
|
786
|
-
return false;
|
|
814
|
+
async heartbeatRequired(head) {
|
|
815
|
+
const epoch = await this.headEpoch(head);
|
|
816
|
+
if (!isDefined3(epoch)) return true;
|
|
817
|
+
return Date.now() - epoch > this.heartbeatInterval;
|
|
787
818
|
}
|
|
788
819
|
async instrument(name, operation) {
|
|
789
820
|
const instrumentation = this.instrumentation;
|