Skip to content

Commit 22a71aa

Browse files
committed
fix: doc fixes after testing
1 parent c48f3f7 commit 22a71aa

2 files changed

Lines changed: 83 additions & 32 deletions

File tree

packages/subgraph-service/docs/dips/testing/LocalNetworkDetails.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Local Network — Details
22

3-
local-network runs the **full DIPS payer pipeline** (`iisa` + `dipper` + `indexer-service` + `indexer-agent`) locally — useful for development and before the payer services are live on your target network. Bring it up with the `indexing-payments` recipe.
3+
local-network runs the **full DIPS payer pipeline** (`iisa` + `dipper` + `indexer-service` + `indexer-agent`) locally — useful for development and before the payer services are live on your target network. Enable the `indexing-payments` profile in `.env` (or `.env.local`), then bring the stack up:
44

55
```bash
6-
# in the local-network checkout
7-
just up indexing-payments
6+
# in the local-network checkout — enable the profile in .env, then:
7+
COMPOSE_PROFILES=block-oracle,explorer,indexing-payments
8+
just up
89
```
910

1011
## Contract Addresses — dynamic
@@ -33,7 +34,7 @@ Chain ID is `1337`.
3334
| indexer-service | validates pushed proposals, queues `pending_rca_proposals` rows |
3435
| dipper | payer side — triggers DIPS origination; the on-chain offer is posted via RAM (`RecurringAgreementManager.offerAgreement`) |
3536
| iisa / iisa-scoring | indexer selection (the dipper calls it to choose indexers) |
36-
| escrow funding service (TBD) | funds the payer's escrow via `RecurringAgreementManager` / issuance, as part of the flow |
37+
| issuance → RAM (on-chain; no separate service) | funds the DIPS payer escrow: issuance routes GRT/block to `RecurringAgreementManager`, whose `beforeCollection()` tops up `PaymentsEscrow` before each collect. Configured by graph-contracts at deploy time. (Distinct from `graph-tally-escrow-manager`, which handles TAP query-fee escrow + signer authorization, not DIPS.) |
3738
| indexing-payments subgraph | indexes `Offer` + `indexingAgreements`; the agent's source of truth |
3839
| graph-node, postgres, ipfs | indexing, agent DB, deployment storage |
3940

packages/subgraph-service/docs/dips/testing/LocalNetworkTestPlan.md

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ curl -s "$AGENT_URL" -H 'content-type: application/json' \
8989
-d '{"query":"{ indexingRules(merged:false){ identifier decisionBasis } }"}'
9090
```
9191

92+
> 💡 The `graph indexer rules` CLI is the usual way to set rules (it supplies the network via
93+
> `--network`). If you call `setIndexingRule` on the management API **directly**, the rule input
94+
> must include `protocolNetwork` (CAIP-2, e.g. `eip155:1337`) or the mutation is rejected.
95+
9296
Active allocation for a deployment — network subgraph:
9397

9498
```bash
@@ -207,22 +211,30 @@ Two environment-note patterns recur:
207211

208212
### D-1.2 Baseline capture
209213

210-
**Objective**: Capture a baseline — pick the target reward-earning deployment and identify the rewards-denied deployment for the D-4 sizing variant.
214+
**Objective**: Capture a baseline — pick the fixtures for the acceptance, reuse, and rewards-denied paths.
211215

212216
**Prerequisites**: D-1.1 green.
213217

214-
**Steps**: List deployment indexing rules and pick a target reward-earning deployment (one with an `always` rule); identify a separate rewards-denied deployment for the D-4 sizing variant. Record both IPFS hashes for downstream tests.
218+
**Steps**: Pick three fixtures and record their IPFS hashes. "Reward-earning" here means simply
219+
*not rewards-denied* — it does **not** require an `always` rule.
220+
221+
- **DIP-driven target** — a reward-earning deployment with **no indexing rule and no active
222+
allocation**. The accepted DIP agreement creates the allocation (D-3.2) and carries the
223+
D-4.1/D-5/D-6/D-7 lifecycle. Do **not** put an `always` rule on it: an `always` rule makes the
224+
agent continuously (re)open a plain allocation, which races/pre-empts the DIP's
225+
`multicall(startService, acceptIndexingAgreement)` and defeats D-3.2.
226+
- **Reuse target** — a separate deployment with a **pre-existing active allocation** (e.g.
227+
opened via an `always` rule), for the D-3.1 existing-allocation path.
228+
- **Rewards-denied deployment** — for the D-4.2 sizing variant.
215229

216-
Baseline rules — Observation toolbox "Indexing rules", reading the identifiers so you can pick a target:
230+
Baseline rules — Observation toolbox "Indexing rules", to see current rules/allocations:
217231

218232
```bash
219233
curl -s "$AGENT_URL" -H 'content-type: application/json' \
220234
-d '{"query":"{ indexingRules(merged:false){ identifier identifierType decisionBasis allocationAmount } }"}' \
221235
| jq -r '.data.indexingRules[] | select(.identifierType=="deployment") | "\(.identifier)\t\(.decisionBasis)"'
222236
```
223237

224-
Pick a deployment whose `decisionBasis` is `always` (reward-earning target) and export it as `<HASH>` for later tests. The `identifier` is the IPFS hash to use downstream.
225-
226238
> 💡 The rewards-denied deployment is the one flagged in the last prerequisite ("one rewards-denied deployment available"). Confirm it on-chain with `RewardsManager.isDenied(bytes32)` (returns `true`) and record its hash separately; it is only used in D-4.
227239
>
228240
> ```bash
@@ -231,31 +243,42 @@ Pick a deployment whose `decisionBasis` is `always` (reward-earning target) and
231243
232244
**Pass Criteria**:
233245
234-
- [ ] A target reward-earning deployment hash is chosen and recorded — it has an `always` rule in the toolbox "Indexing rules" output.
246+
- [ ] A DIP-driven reward-earning target is chosen and recorded — no indexing rule and no active allocation (the DIP acceptance will create the allocation in D-3.2).
247+
- [ ] A separate reuse target is chosen and recorded — it has a pre-existing active allocation (for D-3.1).
235248
- [ ] A rewards-denied deployment is identified and its hash recorded — reserved for the D-4 sizing variant.
236249
237250
---
238251
239252
## Cycle D-2 — Proposal origination (payer side)
240253
241-
### D-2.1 Trigger origination (inject the indexing-requirement signal)
254+
### D-2.1 Trigger origination (set the target candidate count)
242255
243-
**Objective**: Inject the indexing-requirement signal that drives the dipper to originate the agreement.
256+
**Objective**: Register the indexing request that drives the dipper to originate the agreement.
244257
245258
**Prerequisites**: D-1 complete. The dipper and IISA are running; IISA can select the target indexer for the deployment.
246259
247-
**Steps**: Produce an indexing-requirement message to the `indexing-requirements` Redpanda topic; the dipper's signal consumer reads it, runs IISA selection, and offers the agreement. Redpanda auto-create is off, so create the topic first if it doesn't exist.
260+
> ⚠️ **IISA prerequisite (do this first).** IISA only scores indexers that have **Redpanda
261+
> query history**. Send some gateway queries (against any subgraph — history is per-indexer,
262+
> not per-target) and run an IISA scoring pass before origination, or selection returns 0
263+
> candidates. Selection also uses: the indexer need not already index the target (it competes
264+
> in an "unsynced" pool), and the indexer's advertised DIPs price must be under the request's
265+
> `max_grt_per_30_days` ceiling.
248266
249-
```bash
250-
# create the topic if absent (idempotent)
251-
docker exec redpanda rpk topic create indexing-requirements --brokers redpanda:9092 2>/dev/null || true
267+
**Steps**: Drive origination via the dipper admin RPC with `dipper-cli`: `set-target-candidates`
268+
registers (or updates) the desired candidate count for a `(deployment, chain)`; the dipper runs
269+
IISA selection and offers the agreement. There is no `indexing-requirements` Redpanda topic
270+
consumer in the current dipper.
252271
253-
# produce the signal for the target deployment
254-
echo '{"subgraph_deployment_id":"<HASH>","redundancy_factor":1,"chain_id":1337,"version":1}' \
255-
| docker exec -i redpanda rpk topic produce indexing-requirements --brokers redpanda:9092
272+
```bash
273+
# signing key = the gateway-operator / receiver key on dipper's admin allowlist
274+
dipper-cli indexings set-target-candidates \
275+
--server-url http://localhost:9000 \
276+
--signing-key <RECEIVER_KEY> \
277+
<HASH> 1337 --num-candidates 1
256278
```
257279
258-
Message schema: `{ subgraph_deployment_id, redundancy_factor, chain_id, version }`.
280+
On success the CLI prints the indexing request UUID. `--num-candidates 0` cancels the request
281+
(and any agreement it drove — see D-8.1).
259282
260283
**Pass Criteria**:
261284
@@ -331,7 +354,7 @@ The agent's acceptance loop runs every `--dips-acceptance-interval` (default 5s)
331354
**Pass Criteria**:
332355
333356
- [ ] The `pending_rca_proposals` row flips to `accepted` — Observation toolbox "Pending proposal row", look for status `accepted`.
334-
- [ ] A `dips` indexing rule exists for the deployment — Observation toolbox "Indexing rules", `decisionBasis == "dips"` and `identifier == <HASH>`.
357+
- [ ] The deployment is tracked as a DIPs agreement — on-chain agreement `Accepted` and active on the indexing-payments subgraph. Note: a **separate `dips` rule is added only when the deployment had no prior rule** (D-3.2). If the reused allocation came from an `always` rule, that `always` rule persists and no `dips` rule is added — the agent tracks the agreement via the on-chain/subgraph state, not the rule.
335358
- [ ] An active allocation exists for the deployment and the prior allocation id is reused — Observation toolbox "Active allocation".
336359
- [ ] On-chain agreement state is `Accepted` (=1) — Observation toolbox "On-chain agreement state" (`getAgreement`), last field is `1`.
337360
- [ ] The dipper agreement status is `ACCEPTED_ON_CHAIN` — read-only admin RPC `get_agreements_by_deployment_id` (filter by `<HASH>`).
@@ -386,7 +409,7 @@ The agent sizes the DIPS allocation by whether the deployment earns indexing rew
386409
387410
### D-4.2 Rewards-denied sizing
388411
389-
**Objective**: A rewards-denied deployment's allocation uses `--dips-allocation-amount` (env `INDEXER_AGENT_DIPS_ALLOCATION_AMOUNT`), default `0`. A zero-token allocation is valid for DIPS — collection pays the RCA amount, independent of allocation size.
412+
**Objective**: A rewards-denied deployment's allocation uses `--dips-allocation-amount` (env `INDEXER_AGENT_DIPS_ALLOCATION_AMOUNT`). The value is parsed as a **GRT amount** (not wei): the documented default is `0` (a valid zero-token allocation, since collection pays the RCA amount independent of allocation size), but local-network currently sets it to `1` → a **1 GRT** allocation. Read the configured value; do not assume `0`.
390413
391414
**Prerequisites**: The rewards-denied deployment from D-1. Subgraph availability oracle configured.
392415
@@ -411,7 +434,7 @@ Read allocation tokens — Observation toolbox "Allocation tokens" (`getAllocati
411434
412435
**Pass Criteria**:
413436
414-
- [ ] The allocation `tokens` equals `--dips-allocation-amount` (default `0`a valid zero-token allocation).
437+
- [ ] The allocation `tokens` equals `--dips-allocation-amount` interpreted as GRT (documented default `0` → zero-token allocation; local-network's `1` → `1000000000000000000` = 1 GRT). Distinct from the reward-earning sizing in D-4.1.
415438
416439
---
417440
@@ -498,13 +521,19 @@ curl -s "$INDEXING_PAYMENTS_SUBGRAPH_URL" -H 'content-type: application/json' \
498521
499522
**Prerequisites**: An accepted agreement that has not yet collected (`lastCollectionAt == 0`).
500523
524+
> ⚠️ **N/A when `maxInitialTokens = 0`.** local-network's dipper currently offers RCAs with
525+
> `maxInitialTokens = 0`, so there is no bonus to observe — the first collection is just
526+
> `collectionSeconds × rate` like the rest. This check can only be demonstrated by configuring
527+
> dipper to offer a non-zero `maxInitialTokens`. Otherwise mark D-6.1 N/A and confirm only that
528+
> the first collection succeeds.
529+
501530
**Steps**: Advance the first window and let the agent collect; capture the per-collection payout.
502531
503532
> 💡 First-collection bonus: the first collection includes `maxInitialTokens` (a one-time amount added only when `lastCollectionAt == 0`); later collections do not. If you can read the per-collection payout, confirm the first is larger by roughly `maxInitialTokens`.
504533
505534
**Pass Criteria**:
506535
507-
- [ ] The first collection's payout is larger by roughly `maxInitialTokens` than subsequent collections — confirmed when `lastCollectionAt` was `0` at collection time.
536+
- [ ] With a non-zero `maxInitialTokens`: the first collection's payout is larger by roughly `maxInitialTokens` than subsequent collections — confirmed when `lastCollectionAt` was `0` at collection time. (N/A when `maxInitialTokens = 0` — local default.)
508537
- [ ] The agent log shows `Successfully collected indexing fees`.
509538
510539
---
@@ -525,17 +554,30 @@ curl -s "$INDEXING_PAYMENTS_SUBGRAPH_URL" -H 'content-type: application/json' \
525554
526555
---
527556
528-
### D-6.3 Escrow drains cumulatively
557+
### D-6.3 Collection value accrues cumulatively
529558
530-
**Objective**: The payer escrow balance decreases with each collection.
559+
**Objective**: The indexer's collected value grows with each collection.
560+
561+
> ⚠️ **Escrow does not monotonically drain in the protocol-funded flow.** On local-network the
562+
> payer is the `RecurringAgreementManager` and issuance tops up its escrow before collection, so
563+
> `getBalance(payer, recurringCollector, indexer)` stays roughly **constant** even as the indexer
564+
> is paid. Verify cumulative **`tokensCollected`** instead of a decreasing escrow. Escrow drain
565+
> only applies to a fixed-deposit payer (e.g. a consumer/gateway that deposits once), which is
566+
> not the local-network DIPs setup.
531567
532568
**Prerequisites**: D-6.2 in progress.
533569
534-
**Steps**: Re-run `getBalance(payer, recurringCollector, indexer)` per cycle and compare.
570+
**Steps**: Sum `tokensCollected` across the `indexingFeeCollections` for the agreement per cycle
571+
and confirm it increases. (Optionally also read `getBalance`; expect it flat, not draining.)
572+
573+
```bash
574+
curl -s "$INDEXING_PAYMENTS_SUBGRAPH_URL" -H 'content-type: application/json' \
575+
-d '{"query":"{ indexingFeeCollections(where:{ agreement:\"<AGREEMENT_ID>\" }){ tokensCollected blockTimestamp } }"}'
576+
```
535577
536578
**Pass Criteria**:
537579
538-
- [ ] The payer escrow balance decreases with each collection (cumulative drain) — re-run `getBalance` per cycle and compare.
580+
- [ ] Cumulative `tokensCollected` for the agreement increases with each collection. (The payer escrow balance may stay constant due to issuance top-up — that is expected in the protocol-funded flow, not a failure.)
539581
540582
---
541583
@@ -634,13 +676,21 @@ Two independent payer/SP cancellation paths plus the indexer opt-out. Each needs
634676
635677
**Prerequisites**: A fresh `Accepted`, collecting agreement (re-run D-2/D-3).
636678
637-
**Steps**: The payer cancels on-chain via `SubgraphService.cancelIndexingAgreementByPayer(bytes16)`, then advance time so the final collection window opens.
679+
**Steps**: The payer cancels the agreement, then advance time so the final collection window opens.
680+
681+
> ⚠️ **The payer is the RAM contract, not an EOA.** On local-network the on-chain `payer` is the
682+
> `RecurringAgreementManager`, so there is no `$PAYER_SECRET` that can sign
683+
> `cancelIndexingAgreementByPayer` directly — the cancel must be routed through the payer side.
684+
> Drive it via `dipper-cli` by setting the request's target candidates to `0`; dipper cancels
685+
> the agreement through RAM as the payer, yielding `CanceledByPayer`.
638686
639-
Payer cancel — payer key:
687+
Payer cancel — via dipper-cli (cancels through RAM):
640688
641689
```bash
642-
cast send --rpc-url "$RPC" --private-key "$PAYER_SECRET" \
643-
"$SUBGRAPH_SERVICE" "cancelIndexingAgreementByPayer(bytes16)" "<AGREEMENT_ID>"
690+
dipper-cli indexings set-target-candidates \
691+
--server-url http://localhost:9000 \
692+
--signing-key <RECEIVER_KEY> \
693+
<HASH> 1337 --num-candidates 0
644694
```
645695
646696
Advance time so the final collection window opens — local-network with `cast rpc --rpc-url "$RPC" anvil_mine <blocks> <interval>` as in D-6; a testnet waits the real elapsed time.

0 commit comments

Comments
 (0)