Skip to content

Commit 6b20bf6

Browse files
Maikolpcarranzavclaude
authored
[DIPS] Cherry-pick old commits + contracts setup (#1172)
Co-authored-by: Pablo Carranza Velez <pablo@edgeandnode.com> Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3129aac commit 6b20bf6

38 files changed

Lines changed: 3808 additions & 133 deletions

packages/indexer-agent/src/__tests__/indexer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ const setup = async () => {
148148
const network = await Network.create(
149149
logger,
150150
networkSpecification,
151+
models,
151152
queryFeeModels,
152153
graphNode,
153154
metrics,

packages/indexer-agent/src/agent.ts

Lines changed: 142 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,20 @@ export class Agent {
291291
{ logger, milliseconds: requestIntervalSmall },
292292
async () => {
293293
return this.multiNetworks.map(async ({ network, operator }) => {
294+
if (network.specification.indexerOptions.enableDips) {
295+
// There should be a DipsManager in the operator
296+
if (!operator.dipsManager) {
297+
throw new Error('DipsManager is not available')
298+
}
299+
logger.debug('Ensuring indexing rules for DIPs', {
300+
protocolNetwork: network.specification.networkIdentifier,
301+
})
302+
await operator.dipsManager.ensureAgreementRules()
303+
} else {
304+
logger.debug(
305+
'DIPs is disabled, skipping indexing rule enforcement',
306+
)
307+
}
294308
logger.trace('Fetching indexing rules', {
295309
protocolNetwork: network.specification.networkIdentifier,
296310
})
@@ -324,12 +338,21 @@ export class Agent {
324338
},
325339
)
326340

327-
// Skip fetching active deployments if the deployment management mode is manual and POI tracking is disabled
341+
// Skip fetching active deployments if the deployment management mode is manual, DIPs is disabled, and POI tracking is disabled
328342
const activeDeployments: Eventual<SubgraphDeploymentID[]> =
329343
sequentialTimerMap(
330344
{ logger, milliseconds: requestIntervalLarge },
331345
async () => {
332-
if (this.deploymentManagement === DeploymentManagementMode.AUTO) {
346+
let dipsEnabled = false
347+
await this.multiNetworks.map(async ({ network }) => {
348+
if (network.specification.indexerOptions.enableDips) {
349+
dipsEnabled = true
350+
}
351+
})
352+
if (
353+
this.deploymentManagement === DeploymentManagementMode.AUTO ||
354+
dipsEnabled
355+
) {
333356
logger.debug('Fetching active deployments')
334357
const assignments =
335358
await this.graphNode.subgraphDeploymentsAssignments(
@@ -338,7 +361,7 @@ export class Agent {
338361
return assignments.map(assignment => assignment.id)
339362
} else {
340363
logger.info(
341-
"Skipping fetching active deployments fetch since DeploymentManagementMode = 'manual' and POI tracking is disabled",
364+
"Skipping fetching active deployments fetch since DeploymentManagementMode = 'manual' and DIPs is disabled",
342365
)
343366
return []
344367
}
@@ -351,37 +374,63 @@ export class Agent {
351374
},
352375
)
353376

354-
const networkDeployments: Eventual<NetworkMapped<SubgraphDeployment[]>> =
355-
sequentialTimerMap(
356-
{ logger, milliseconds: requestIntervalSmall },
357-
async () =>
358-
await this.multiNetworks.map(({ network }) => {
359-
logger.trace('Fetching network deployments', {
360-
protocolNetwork: network.specification.networkIdentifier,
361-
})
362-
return network.networkMonitor.subgraphDeployments()
363-
}),
364-
{
365-
onError: error =>
366-
logger.warn(
367-
`Failed to obtain network deployments, trying again later`,
368-
{ error },
369-
),
370-
},
371-
)
377+
const networkAndDipsDeployments: Eventual<
378+
NetworkMapped<SubgraphDeployment[]>
379+
> = sequentialTimerMap(
380+
{ logger, milliseconds: requestIntervalSmall },
381+
async () =>
382+
await this.multiNetworks.map(async ({ network, operator }) => {
383+
logger.trace('Fetching network deployments', {
384+
protocolNetwork: network.specification.networkIdentifier,
385+
})
386+
const deployments = network.networkMonitor.subgraphDeployments()
387+
if (network.specification.indexerOptions.enableDips) {
388+
if (!operator.dipsManager) {
389+
throw new Error('DipsManager is not available')
390+
}
391+
const resolvedDeployments = await deployments
392+
const dipsDeployments = await Promise.all(
393+
(await operator.dipsManager.getActiveDipsDeployments()).map(
394+
deployment =>
395+
network.networkMonitor.subgraphDeployment(
396+
deployment.ipfsHash,
397+
),
398+
),
399+
)
400+
for (const deployment of dipsDeployments) {
401+
if (
402+
resolvedDeployments.find(
403+
d => d.id.bytes32 === deployment.id.bytes32,
404+
) == null
405+
) {
406+
resolvedDeployments.push(deployment)
407+
}
408+
}
409+
return resolvedDeployments
410+
}
411+
return deployments
412+
}),
413+
{
414+
onError: error =>
415+
logger.warn(
416+
`Failed to obtain network deployments, trying again later`,
417+
{ error },
418+
),
419+
},
420+
)
372421

373422
const networkDeploymentAllocationDecisions: Eventual<
374423
NetworkMapped<AllocationDecision[]>
375424
> = join({
376-
networkDeployments,
425+
networkAndDipsDeployments,
377426
indexingRules,
378427
}).tryMap(
379-
async ({ indexingRules, networkDeployments }) => {
428+
async ({ indexingRules, networkAndDipsDeployments }) => {
380429
return this.multiNetworks.mapNetworkMapped(
381-
this.multiNetworks.zip(indexingRules, networkDeployments),
430+
this.multiNetworks.zip(indexingRules, networkAndDipsDeployments),
382431
async (
383432
{ network }: NetworkAndOperator,
384-
[indexingRules, networkDeployments]: [
433+
[indexingRules, networkAndDipsDeployments]: [
385434
IndexingRuleAttributes[],
386435
SubgraphDeployment[],
387436
],
@@ -405,7 +454,11 @@ export class Agent {
405454
logger.trace('Evaluating which deployments are worth allocating to')
406455
return indexingRules.length === 0
407456
? []
408-
: evaluateDeployments(logger, networkDeployments, indexingRules)
457+
: evaluateDeployments(
458+
logger,
459+
networkAndDipsDeployments,
460+
indexingRules,
461+
)
409462
},
410463
)
411464
},
@@ -599,9 +652,42 @@ export class Agent {
599652
}
600653
break
601654
case DeploymentManagementMode.MANUAL:
602-
this.logger.debug(
603-
`Skipping subgraph deployment reconciliation since DeploymentManagementMode = 'manual'`,
604-
)
655+
await this.multiNetworks.map(async ({ network, operator }) => {
656+
if (network.specification.indexerOptions.enableDips) {
657+
// Reconcile DIPs deployments anyways
658+
this.logger.warn(
659+
`Deployment management is manual, but DIPs is enabled. Reconciling DIPs deployments anyways.`,
660+
)
661+
if (!operator.dipsManager) {
662+
throw new Error('DipsManager is not available')
663+
}
664+
const dipsDeployments =
665+
await operator.dipsManager.getActiveDipsDeployments()
666+
const newTargetDeployments = new Set([
667+
...activeDeployments,
668+
...dipsDeployments,
669+
])
670+
try {
671+
await this.reconcileDeployments(
672+
activeDeployments,
673+
Array.from(newTargetDeployments),
674+
eligibleAllocations,
675+
)
676+
} catch (err) {
677+
logger.warn(
678+
`Exited early while reconciling deployments. Skipped reconciling actions.`,
679+
{
680+
err: indexerError(IndexerErrorCode.IE005, err),
681+
},
682+
)
683+
return
684+
}
685+
} else {
686+
this.logger.debug(
687+
`Skipping subgraph deployment reconciliation since DeploymentManagementMode = 'manual'`,
688+
)
689+
}
690+
})
605691
break
606692
default:
607693
throw new Error(
@@ -622,6 +708,28 @@ export class Agent {
622708
})
623709
return
624710
}
711+
712+
await this.multiNetworks.mapNetworkMapped(
713+
activeAllocations,
714+
async ({ network, operator }, activeAllocations: Allocation[]) => {
715+
if (network.specification.indexerOptions.enableDips) {
716+
if (!operator.dipsManager) {
717+
throw new Error('DipsManager is not available')
718+
}
719+
720+
await operator.dipsManager.acceptPendingProposals(
721+
activeAllocations,
722+
)
723+
724+
this.logger.debug(
725+
`Matching agreement allocations for network ${network.specification.networkIdentifier}`,
726+
)
727+
await operator.dipsManager.matchAgreementAllocations(
728+
activeAllocations,
729+
)
730+
}
731+
},
732+
)
625733
},
626734
)
627735
}
@@ -948,6 +1056,7 @@ export class Agent {
9481056
maxAllocationDuration: HorizonTransitionValue,
9491057
network: Network,
9501058
operator: Operator,
1059+
forceAction: boolean = false,
9511060
): Promise<void> {
9521061
const logger = this.logger.child({
9531062
deployment: deploymentAllocationDecision.deployment.ipfsHash,
@@ -971,6 +1080,7 @@ export class Agent {
9711080
logger,
9721081
deploymentAllocationDecision,
9731082
activeDeploymentAllocations,
1083+
forceAction,
9741084
)
9751085
case true: {
9761086
// If no active allocations and subgraph health passes safety check, create one
@@ -1008,6 +1118,7 @@ export class Agent {
10081118
deploymentAllocationDecision,
10091119
mostRecentlyClosedAllocation,
10101120
isHorizon,
1121+
forceAction,
10111122
)
10121123
}
10131124
} else if (activeDeploymentAllocations.length > 0) {
@@ -1016,6 +1127,7 @@ export class Agent {
10161127
logger,
10171128
deploymentAllocationDecision,
10181129
activeDeploymentAllocations,
1130+
forceAction,
10191131
)
10201132
} else {
10211133
// Refresh any expiring allocations
@@ -1032,6 +1144,7 @@ export class Agent {
10321144
logger,
10331145
deploymentAllocationDecision,
10341146
expiringAllocations,
1147+
forceAction,
10351148
)
10361149
}
10371150
}

packages/indexer-agent/src/commands/start.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
createIndexerManagementClient,
1616
createIndexerManagementServer,
1717
defineIndexerManagementModels,
18+
definePendingRcaProposalModel,
1819
defineQueryFeeModels,
1920
GraphNode,
2021
indexerError,
@@ -361,6 +362,26 @@ export const start = {
361362
required: false,
362363
group: 'Indexer Infrastructure',
363364
})
365+
.option('enable-dips', {
366+
description: 'Whether to enable Indexing Fees (DIPs)',
367+
type: 'boolean',
368+
default: false,
369+
group: 'Indexing Fees ("DIPs")',
370+
})
371+
.option('dipper-endpoint', {
372+
description: 'Gateway endpoint for DIPs receipts',
373+
type: 'string',
374+
array: false,
375+
required: false,
376+
group: 'Indexing Fees ("DIPs")',
377+
})
378+
.option('dips-allocation-amount', {
379+
description: 'Amount of GRT to allocate for DIPs',
380+
type: 'number',
381+
default: 1,
382+
required: false,
383+
group: 'Indexing Fees ("DIPs")',
384+
})
364385
.check(argv => {
365386
if (
366387
!argv['network-subgraph-endpoint'] &&
@@ -388,6 +409,9 @@ export const start = {
388409
) {
389410
return 'Invalid --rebate-claim-max-batch-size provided. Must be > 0 and an integer.'
390411
}
412+
if (argv['enable-dips'] && !argv['dipper-endpoint']) {
413+
return 'Invalid --dipper-endpoint provided. Must be provided when --enable-dips is true.'
414+
}
391415
return true
392416
})
393417
},
@@ -428,6 +452,10 @@ export async function createNetworkSpecification(
428452
maxProvisionInitialSize: argv.maxProvisionInitialSize,
429453
finalityTime: argv.chainFinalizeTime,
430454
legacyMnemonics: argv.legacyMnemonics,
455+
enableDips: argv.enableDips,
456+
dipperEndpoint: argv.dipperEndpoint,
457+
dipsAllocationAmount: argv.dipsAllocationAmount,
458+
dipsEpochsMargin: argv.dipsEpochsMargin,
431459
}
432460

433461
const transactionMonitoring = {
@@ -643,6 +671,9 @@ export async function run(
643671
await sequelize.sync()
644672
logger.info(`Successfully synced database models`)
645673

674+
// Define after sync so Sequelize won't try to create/alter this indexer-rs-owned table
675+
const pendingRcaModel = definePendingRcaProposalModel(sequelize)
676+
646677
// --------------------------------------------------------------------------------
647678
// * Networks
648679
// --------------------------------------------------------------------------------
@@ -653,7 +684,14 @@ export async function run(
653684
const networks: Network[] = await pMap(
654685
networkSpecifications,
655686
async (spec: NetworkSpecification) =>
656-
Network.create(logger, spec, queryFeeModels, graphNode, metrics),
687+
Network.create(
688+
logger,
689+
spec,
690+
managementModels,
691+
queryFeeModels,
692+
graphNode,
693+
metrics,
694+
),
657695
)
658696

659697
// --------------------------------------------------------------------------------
@@ -676,6 +714,7 @@ export async function run(
676714
},
677715
},
678716
multiNetworks,
717+
pendingRcaModel,
679718
})
680719

681720
// --------------------------------------------------------------------------------

0 commit comments

Comments
 (0)