Season day: reading the status

Final Testnet Season

Until the season ends, miners earn testnet DNDR by a formula published in advance. The DNDR the season pays you are your points, and each one becomes one mainnet DNDR. Rewards are computed in public, from chain records and published evidence, for each miner identity.

View

Simple keeps what you need to take part. Advanced adds the full rules, their sources and how to recompute a day.

A miner identity is a miner as the chain registers it. It has its own operator key, which signs for it on chain, and its own stake, the DNDR it locks as a bond.

ends

7 November 2026

23:59 UTC, by block timestamp

entry

No sign-up, no entry test

Every running miner takes part.

payment

Paid weekly

Every seven season days, in testnet DNDR; the last payment covers the days left at the end.

points

Season payments count as points

One mainnet DNDR per testnet DNDR the season pays, credited in the mainnet genesis (how).

Your wallet balance is not your reward

Only the DNDR the season pays you counts. Those DNDR are your points, and each one becomes one mainnet DNDR.

Counts

  • The season’s weekly payments. Each is an on-chain transfer from the season’s payout account to your payout address, with a memo starting dendra-final-season-week-. Every testnet DNDR it pays becomes one mainnet DNDR, at the address that received it.

Does not count

  • Faucet drips, the free testnet DNDR your miner bonds.
  • Your stake, the bond your miner locks on chain.
  • The chain’s own payments per job: the miner’s share of each fee, and the work subsidy.
  • Transfers between addresses.

Example: made-up amounts, not a reading of the network

Over two weeks your address receives 1.2 DNDR, then 0.9 DNDR, from the season’s weekly payments. It also receives 0.35 DNDR of job pay from the chain, and 2 DNDR from a friend. Your points are 1.2 + 0.9 = 2.1, so 2.1 mainnet DNDR. The other 2.35 DNDR never count, whatever your balance shows.

Where to read your points. Anyone can write that memo on a transfer, so the memo is not the reference: the rankings are. Each daily ranking, ranking/day-NNN.json, has a row for your identity: its paid_udndr is what the season pays you for that day (1 DNDR = 1,000,000 udndr). Your points are the sum over the published days. A day is ranked only once all its requests are final, so the days just closed are not in the rankings yet.

The season, right now

Read when the page loads, from the season service and the chain, and refreshed every minute. Nothing on this band is written into the page.

reading the season status

...

season day, counted from 1 (day in the status)

...

state of the season (ended in the status)

...

last minute of the season (rules.end_time, exclusive)

...

latest block (/rpc/status)

First days of the dated rules

RuleStarts onStatus field
Delivered work is paid, below...unwound_audit_work_from_day
Doubled rewards, below...doubled_rates_from_day
More requests a day, below...more_requests_from_day
Judge reward, kit floor and probation, below...kit_rules_from_day

Counted here from 1, as the season’s days are named on this page; the status counts from 0. “Not published yet” is an answer of the service, and “unavailable” means the status could not be read.

Weeks and days, from the published rankings

not read yet

The rankings are one file per day. This reads them one by one when you ask, and adds up what each one pays. It does not read the weekly transfers on chain: see Check it yourself for those.

How a season day works

Each day the programme acts as an ordinary paying client and sends the network a fixed number of AI prompts (requests). The chain, not the programme, picks who serves each request, among the miners it counts as online (present miners, defined below). The chain also draws some requests for audit: a jury of other miners checks the answer.

When the day closes, a few answers of each identity are graded. The day is ranked, with its evidence, once its requests are final, and payment follows every seven season days.

The programme is a service the project runs for the season. The Final Testnet Season ends on 7 November 2026 at 23:59 UTC: it counts every block timestamped before 8 November 2026, 00:00 UTC, and the chain’s own block times decide. A request counts on the block it settles, so the programme opens none in the last ten minutes before the end, by block timestamp; on the last, shorter day the requests are spread over the time left. After the end, the service refuses new answers.

A season day, step by step During the day, for each request When the day closes every 17 280 blocks 1 · The programme sends it a fixed number of requests every day 2 · The chain draws the miner among present miners, by stake up to a ceiling 3 · The miner answers the programme records the answer 4 · Settled on chain some are drawn for audit by a jury of miners Not counted convicted, or refunded otherwise Verified final, or upheld; delivered work: below 5 · Up to 3 answers graded per identity, among the answers recorded is each a coherent attempt? all incoherent: that day's work and presence lost 6 · Daily ranking, with its evidence published once the day's requests are final 7 · Weekly payment after a check of every published day a draw made by the chain, seeded by the validators A season day, step by step During the day, for each request 1 · The programme sends it a fixed number of requests every day 2 · The chain draws the miner among present miners, by stake up to a ceiling 3 · The miner answers the programme records the answer 4 · Settled on chain some are drawn for audit by a jury of other miners Not counted convicted, or refunded otherwise Verified final, or upheld; delivered work: below When the day closes every 17 280 blocks 5 · Up to 3 answers graded per identity, among the answers recorded is each a coherent attempt? all incoherent: work and presence lost 6 · Daily ranking, with its evidence published once the day's requests are final 7 · Weekly payment after a check of every published day a draw made by the chain
  1. The programme sends a fixed number of requests every day.
  2. The chain draws the miner that serves each request, among present miners, by stake up to a ceiling.
  3. The miner answers, and the programme records the answer.
  4. The job is settled on chain; some jobs are drawn for audit by a jury of other miners.
  5. A final or upheld request is verified. Delivered work, a request refunded because no audit of it concluded in time, follows its own rule, from the day the season service names (below). A convicted request, or one refunded for any other reason, is not counted.
  6. When the day closes, every 17 280 blocks (the last day is cut at the season’s end), up to 3 of each identity’s recorded answers are graded. If all are judged incoherent, that day’s work and presence are lost.
  7. The daily ranking is published with its evidence, once the day’s requests are final.
  8. Payment is weekly, after a check of every published day.
  9. Steps 2 and 4 are draws made by the chain, seeded by the validators.

A request is verified when its answer reached the programme and the chain settled it for good, with no conviction against it.

In full: the programme got its answer, the chain settled it, and no audit of it can still be open (it is final). If it was audited, the jury must have upheld it, unless it falls under the delivered-work rule below. It never counts if its miner was slashed for it (penalised with part of its stake), nor if its fee went back to the client for any other reason.

Delivered work: paid from the day the season service names

A programme request refunded because no audit of it concluded in time is paid as a verified request when its answer reached the programme and the season’s grading did not reject it: its own grade first, otherwise its miner’s grades that day. A request with no grade at all, or whose miner was convicted, is never paid. The rule applies from the season day the season service publishes (reading its status…).

The chain marks such a job unwound: the client is refunded, and the miner is neither paid nor slashed by the chain. That happens when a drawn job’s jury does not conclude within audit_unwind_blocks of settlement, and also when the audit draw itself waits that long for a usable seed. An answer graded on its own is decided by that grade: coherent is paid, incoherent never, whatever the rest of its day says. An answer not graded itself follows its miner’s day: it is paid when that day has at least one grade and its work is not taken away (Graded answers). No grade, or a grading that cannot be read, is not paid. The rule’s first day is the status field unwound_audit_work_from_day, counted from 0; a day already ranked is never ranked again under it. Each ranking under the rule lists every unwound programme job of the day, paid or not, with the reason (inputs.unwound_audit_work). An unwound audit pays no juror: no juror judged.

Graded answers

When the day closes, a few answers of each identity are graded by a language model, which asks one question of each: is this a coherent attempt? If every graded answer is judged incoherent, that day’s work and presence rewards are lost; its juror rewards are kept.

At most three answers per identity are drawn from the first 50 that identity gave that day. The draw follows an order set by the service’s own secret, so no miner can tell in advance which answers are read. The drawn answers are published with their requests. Taking a day’s work away needs at least two grades, or one when a single answer was drawn, and a grade the model cannot give clearly is not posted.

How an audit jury decides

An audit concludes only when votes the same way reach the jury bar, and the jury excludes the miner under audit. The bar is the larger of audit_min_quorum jurors and two thirds of the anchored seats (the seats the chain drew and recorded for that audit before any vote), rounded up. Convicting needs “invalid” votes at that bar and a strict majority of the voting stake. A convicted miner is slashed and the client is refunded. Upholding the answer takes the same bar, with “valid” votes.

A drawn job below the jury floor (audit_min_quorum + 1 present, eligible miners), or whose jury does not conclude within audit_unwind_blocks, is refunded and nobody is slashed; the season may still pay it as delivered work.

What earns DNDR

Three things earn season rewards, and a fourth, the judge presence reward, from the season day named below. Nothing else does.

Rewards are doubled from the fifth season day. From Season day 5 (day 4 when counted from 0, as the ranking files are: day-004.json) to the season’s end, every rate of the first three rows below and the programme’s daily cap are twice those of the first four days, and the season cap is 3 000 DNDR. A day already ranked keeps the rules it was ranked under: each ranking carries the fingerprint of its rules, and the season service names the first doubled day in its status (doubled_rates_from_day), next to rules, the rules of the current day. First doubled day (reading the status…).

More requests a day, at the same rates. From one season day to the season’s end, the programme sends more requests a day (requests_per_day in rules), so there is more verified work to share among the miners that answer. Every rate and both caps stay those of the doubled days, and a day already ranked keeps the rules it was ranked under. The season service names that first day in its status (more_requests_from_day). First day of the larger volume (reading the status…).

A judge reward, a kit floor and a probation, from one season day. From the season day the season service publishes in its status as kit_rules_from_day (counted from 0, so day N is “Season day N+1”; null until the service fixes it) to the season’s end, one rule set pays the judge presence reward of the table below and applies two more rules.

The kit floor: an identity whose latest signed capacity report, at or before the day’s end, declares a kit below kit_min, or that has no such report, is paid nothing for the day. The probation: an identity earns 60 percent of its season pay on its first full season day after its registration. The first day of the rule set is the season day that begins closest to KIT_DEADLINE, fixed before it begins; the season service publishes it once it fixes it, and a day already ranked keeps the rules it was ranked under. An identity whose registration cannot be dated is paid nothing under this rule set either. The floor is the kit number of the announced release.

Read KIT_MIN and KIT_DEADLINE with curl -sf https://testnet-api.dendranetwork.com/network-info.txt, and kit_rules_from_day, then rules.kit_min from that day, with curl -s https://testnet-api.dendranetwork.com/final-season/v1/status. First day of the rule set (reading the status…).

RewardRateWhat counts
Work0.10 DNDR per verified request (0.05 on the first four days)A programme request the identity served, verified as above
Juror0.016 DNDR per verdict (0.008 on the first four days)A verdict that matches the audit’s outcome, by a drawn juror, on an audit of a programme request
Presence0.004 DNDR per window, up to 50 a day (0.2 DNDR); 0.002 and 0.1 DNDR on the first four daysAn availability window proven on chain, paid only on a day with at least one verified request
Judge presence0.5 DNDR per active judge per day, from the day named aboveA season day on which the identity meets the five conditions below; apart from the contradiction check, the verdict’s value is not read

Daily reward = 0.10 × verified requests + 0.016 × verdicts + 0.004 × paid windows, plus 0.5 for an active judge from the day named above, the whole paid at 60 percent on a probation day.

For example, with made-up counts: 6 verified requests and 50 windows give 6 × 0.10 + 50 × 0.004 = 0.6 + 0.2 = 0.8 DNDR.

An availability window is a fixed stretch of blocks. In each one, the miner software proves it is online by answering a chain challenge with its own key (its VRF key). A miner is present, and can be drawn, when it proved a window, or registered, in the current or the previous one.

A verdict is a juror’s vote on an audited answer. Other terms: the glossary.

One rate for everyone

Every verified request pays the same, whatever card, CPU or model served it. The programme’s daily volume of requests is fixed and shared among the miners present: the more miners present, the fewer requests each.

Juror rewards need an active judge

The chain draws jurors among the present miners, whether they run a judge or not. Only a node running a judge posts a verdict, and only a verdict earns a juror reward: a miner without an active judge is a silent seat, drawn onto juries where it votes nothing. Judging runs on the CPU, with or without a GPU, with the model the kit reads from the model registry (audit_judge_model, which no consensus code enforces), and a judge needs at least MOE_CPU_MIN_RAM_MB of system RAM, the kit’s judge floor.

Read the pinned model with curl -s https://testnet-api.dendranetwork.com/rest/dendra/modelregistry/v1/params, and the RAM floor the kit applies in the report of bash deploy/hw_probe.sh (from kit v0.2.1, bash deploy/hw_probe.sh --judge-floor-mb prints it alone). From kit v0.2.1, the kit declares each identity’s judge role in its signed capacity report (judge_role: active, mute, off or unknown). That is a declaration: only a verdict posted on chain shows that a judge works.

Judge presence: a dated participation

From the day named above, the season pays 0.5 DNDR per active judge per day, inside the same daily cap as every other reward. It is paid in testnet DNDR and counted as points like the others, once per identity and per day. On a season day an identity is an active judge when all five of these hold:

  1. it is seated on the jury, drawn that day, of at least one audit that reached an outcome, of a programme request settled that day or within the finality span before it;
  2. the relay holds a reveal sealed to it for that audit, stored before its verdict;
  3. it committed a verdict on that audit after that reveal arrived, and before the audit concluded;
  4. no verdict it posted on a programme audit concluded that day contradicts how that audit ended;
  5. its latest signed capacity report, at or before the day’s end, declares the judge role active on a kit at or above kit_min.

A verdict is a signed byte; apart from the contradiction check, these conditions do not read its value, so they prove neither that a model ran nor that the reveal was opened. The reward pays for being seated, answering in time and not being contradicted. A mute seat earns nothing from it.

The five conditions are read by final_season_facts.py::judge_presence. Each ranking under the kit rule set publishes them for every seated identity, paid or not, with the reason, under inputs.judge_presence.

Separately, the chain pays the miner for each job that becomes final without a refund: its share of the fee, and a work subsidy within limits the chain sets. That pay is not a season reward, and it never counts as points.

Estimate a day, or the rest of the season

Type the counts of one identity for one season day. The page multiplies them by the rates in force, read live from the season service. It is arithmetic on the counts you type, not a forecast: how many requests an identity gets depends on the chain’s draw and on how many identities are present. The rates change on the days listed under First days of the dated rules; every day counted here uses today’s rates, and a day already ranked keeps the rules it was ranked under.

Testnet DNDR is not for sale

The project sells no testnet DNDR, and this page puts no price on it. Season rewards are paid in testnet DNDR and counted as points: each one becomes one mainnet DNDR, as Points and mainnet explains.

reading the rules in force

Programme requests your identity served, verified as described under How a season day works. Type 0 for none.

Only a node running a judge posts verdicts, and the rules in force say which count (see What earns DNDR). Type 0 for none.

Paid only on a day with at least one verified request, and at most ... a day. Type 0 for none.

estimate

One moment.

Worked examples

The formula, at the rates of the doubled days, worked through for one identity on four made-up days, before the day’s budget is shared out. The counts show the arithmetic, not what a day pays.

Four worked examples of the formula work verdicts presence presence, not paid Online all day 6 verified requests, 50 windows 0.8 DNDR 6 × 0.10 + 50 × 0.004 = 0.6 + 0.2 With juror votes the same, plus 10 verdicts 0.96 DNDR 0.6 + 10 × 0.016 + 0.2 = 0.6 + 0.16 + 0.2 No verified request 10 verdicts, 50 windows 0.16 DNDR 10 × 0.016 = 0.16 Busy day 20 verified requests, 50 windows 2.2 DNDR 20 × 0.10 + 50 × 0.004 = 2 + 0.2 Worked examples, before the day's budget. Amounts in testnet DNDR. Four worked examples of the formula work verdicts presence presence, not paid Online all day 6 verified requests, 50 windows 0.8 DNDR 6 × 0.10 + 50 × 0.004 = 0.6 + 0.2 With juror votes the same, plus 10 verdicts 0.96 DNDR 0.6 + 10 × 0.016 + 0.2 = 0.6 + 0.16 + 0.2 No verified request 10 verdicts, 50 windows 0.16 DNDR 10 × 0.016 = 0.16 Busy day 20 verified requests, 50 windows 2.2 DNDR 20 × 0.10 + 50 × 0.004 = 2 + 0.2 Worked examples, before the day's budget.
  1. Online all day, 6 verified requests and 50 windows: 6 × 0.10 + 50 × 0.004 = 0.6 + 0.2 = 0.8 DNDR.
  2. With juror votes, the same plus 10 verdicts that match the outcome: 0.6 + 0.16 + 0.2 = 0.96 DNDR.
  3. No verified request, 10 such verdicts and 50 windows: 10 × 0.016 = 0.16 DNDR; the windows are not paid.
  4. Busy day, 20 verified requests and 50 windows: 2 + 0.2 = 2.2 DNDR.

Stake and the work draw

Your stake earns no season reward by itself. It weighs in the draw that picks who serves each request: the chain weights each present identity by its stake, up to a ceiling of assignment_stake_cap_multiple × min_stake. At a multiple of 1, a stake above min_stake buys no more work.

On this testnet, neither the stake nor the number of identities protects against an operator who runs many identities, each with its own stake: what bounds the season’s total is the programme’s caps, 100 DNDR a day and 3 000 DNDR over the season (50 and 1 500 on the first four days).

Governance sets the multiple, and which one is in force is a reading of the chain, not a line of this page. Proposal 1 on this testnet proposes a multiple of 1; read its status with curl -s https://testnet-api.dendranetwork.com/rest/cosmos/gov/v1/proposals/1, and assignment_stake_cap_multiple and min_stake in

Read the stake parameterscurl
$ curl -s https://testnet-api.dendranetwork.com/rest/dendra/jobs/v1/params

The faucet’s drip size is the amount in its status, curl -s http://testnet-api.dendranetwork.com:4500/, next to amount_source, where it comes from. The faucet code of kit v0.2.1 can read it from the chain’s min_stake (DENDRA_FAUCET_AMOUNT=min_stake, faucet_daemon.py::drip_amount), so that one drip bonds one identity. Splitting a stake into identities bonded at min_stake keeps every part under the ceiling, so the whole stake weighs in the draw. The programme’s caps are cap_programme_day and cap_season, in each rule set of final_season_rules.py (RULE_HISTORY).

The ceiling is applied by committee.go::capAssignmentWeights. A field missing from the params output holds zero: an assignment_stake_cap_multiple of 0 selects the compiled 2, and a min_stake of 0 sets no ceiling. Proposals are read with curl -s https://testnet-api.dendranetwork.com/rest/cosmos/gov/v1/proposals. The audit jury is drawn by stake too, and that draw does not read this ceiling (audit_committee.go::drawMembersWithDomain).

From reward to payment

Each day’s rewards are paid within the day’s budget: 100 DNDR (50 DNDR on the first four days), or what remains of the season’s 3 000 DNDR if that is less. Above it, every reward of the day is cut by the same ratio. Payment is weekly, every seven season days, after a check of every published day; the last payment covers the days left at the end.

A reward goes through four steps, in this order. The order is part of the rule: a reward that cannot be paid takes no share of the day’s budget.

From reward to payment, in four steps 1 · Gross the formula on the day's counts 2 · Payable the gross, or 0 when no address is known 3 · Paid within the day's budget, pro rata 4 · Weekly payment after a check of every published day Where a reward is paid 1. the address the identity declared, signed with its operator key 2. else the operator that signed its availability proofs that day 3. else the operator in the registry none known: payable 0 The day's budget 100 DNDR, or what remains of the season's 3 000 DNDR, if that is less. Above it, every payable reward is cut by the same ratio, rounded down to the smallest unit (udndr). From reward to payment, in four steps 1 · Gross the formula on the day's counts 2 · Payable the gross, or 0 when no address is known Where a reward is paid 1. the address the identity declared, signed with its operator key 2. else the operator that signed its availability proofs that day 3. else the operator in the registry none known: payable 0 3 · Paid within the day's budget, pro rata The day's budget 100 DNDR, or what remains of the season's 3 000 DNDR, if that is less. Above it, every payable reward is cut by the same ratio, rounded down. 4 · Weekly payment after a check of every published day
  1. Gross: the formula on the day’s counts.
  2. Payable: the gross, or 0 with the reason “no payout address known”. The address is, first found: the one the identity declared, signed with its operator key; else the operator that signed its availability proofs that day; else the operator in the registry.
  3. Paid: the day’s budget is 100 DNDR (50 on the first four days), or what remains of the season’s 3 000 if that is less. Above it, every payable reward of the day is cut by the same ratio, rounded down to the smallest unit (udndr).
  4. Weekly payment, after a check of every published day.

There is no cap per identity. The work an identity gets is the chain’s draw over a fixed daily volume (above), so an operator that runs more identities is drawn more often, and a cap per identity would not stop it: each identity would stay under the cap. The programme’s caps bound the total instead.

Without a declaration, rewards go to your miner’s operator address. They can go to another address, such as one made on the Wallet page. Declare it in the Dendra app (its Where rewards go card) or by hand from deploy/testnet-miner/; the operator key signs the declaration. After the season’s end, the service refuses new declarations.

Declare a payout addressfrom deploy/testnet-miner/
$ docker compose exec miner python3 final_season_miner.py payout --address dendra1…

Points and mainnet

Your points are the season rewards actually paid to you: the paid amount of each published ranking, after the day’s pro rata, one point per testnet DNDR. They convert one for one: each testnet DNDR the season paid becomes one mainnet DNDR, credited in the mainnet genesis to the address that received it. The season cap bounds the total at 3 000 mainnet DNDR. Mainnet launches after the Final Testnet Season.

Keep the key of the address that received your payments: the same key controls the same address on mainnet.

Before mainnet launches, the list of addresses and amounts is published with its hash; anyone can recompute it from the published rankings and the payout transfers on chain.

How points convert into mainnet DNDR Your points × 1 mainnet DNDR per point = Your mainnet DNDR Credited in the mainnet genesis to the address that received the payments; at most 3 000 mainnet DNDR in total, the season cap. Counts as points work, juror, presence, judge rewards Never counts faucet grants, your stake, transfers, the chain's own job payment, the subsidy How points convert into mainnet DNDR Your points × 1 mainnet DNDR per point = Your mainnet DNDR Credited in the mainnet genesis to the address that received the payments; at most 3 000 mainnet DNDR in total, the season cap. Counts as points work, juror, presence, judge rewards Never counts faucet grants, your stake, transfers between addresses, the chain's own job payment, the subsidy

Your points times one mainnet DNDR per point equals your mainnet DNDR, credited in the mainnet genesis to the address that received the payments; at most 3 000 mainnet DNDR in total, the season cap. Work, juror, presence and judge rewards count as points. Faucet grants, your stake, transfers between addresses, the chain’s own job payment and the subsidy never count.

Take part

Before installing, check your machine: bash deploy/hw_probe.sh, from the repository, says what it can serve. Full guide, faucet and manual path: Run a miner.

  1. Install the miner

    Download deploy/install.sh, read it, then run it with --yes; never pipe it from a URL. On Windows, deploy/install.ps1 prepares WSL 2 and runs the same installer. With an NVIDIA GPU the machine mines. The installer also sets up the judge, which juror rewards need, when hw_probe.sh says the machine can judge: the judge runs on the CPU and needs at least MOE_CPU_MIN_RAM_MB of system RAM (bash deploy/hw_probe.sh --judge-floor-mb prints it), with or without a GPU; under Windows, the RAM of WSL 2.

  2. Open the Dendra app

    On a desktop session the installer adds the Dendra app, built for Linux first. It shows your recovery phrase once, then your season figures and where your rewards go.

  3. Check that it proves it is online

    In docker compose -f deploy/testnet-miner/docker-compose.yml logs miner, look for availability PROVEN (VRF). Without it no window is proven, and a NO VRF KEY line says how to fix that. A miner without proofs soon stops being present: it is then not drawn for work or juries and earns nothing.

Kits v0.2.1 and v0.2.2, for machines without a GPU. A machine with no GPU joins only as a judge: it needs at least MOE_CPU_MIN_RAM_MB of system RAM, and it answers the requests drawn for it with the judge’s model, not with a mining model. With no GPU and less RAM, those kits refuse to join.

Check it yourself

Every ranking is published with the evidence it was computed from, and anyone can recompute a day and compare it byte for byte: see Recompute a day below.

status
The rules and the current day, counted from 0, with the rules’ fingerprint and the season’s start height; the season’s end (rules.end_time, exclusive), whether the chain is past it (ended; the day count goes on after the end) and, once it is, the season’s last block and last day (end_height, last_day); the first day of the delivered-work rule (unwound_audit_work_from_day), the first day of the doubled rewards (doubled_rates_from_day, null when there is none) and the first day of the larger daily volume (more_requests_from_day, null when there is none): https://testnet-api.dendranetwork.com/final-season/v1/status
ranking
https://testnet-api.dendranetwork.com/final-season/v1/ranking/day-NNN.json, NNN being the day in three digits from 000: “Season day 1” is day-000.json. A day not ranked yet answers 404.
evidence
https://testnet-api.dendranetwork.com/final-season/v1/evidence/day-NNN.jsonl: payout declarations, sampled answers, their grades, and each day’s seal (which answers the programme received)
chain
curl -s https://testnet-api.dendranetwork.com/rest/dendra/jobs/v1/params → avail_epoch_blocks, assignment_stake_cap_multiple, min_stake, audit_min_quorum, audit_unwind_blocks, committee_min_vrf_contributors. A field missing from that output holds zero: an assignment_stake_cap_multiple of 0 selects the compiled 2, a min_stake of 0 sets no stake ceiling, an audit_min_quorum of 0 selects the compiled 4, a committee_min_vrf_contributors of 0 sets no minimum number of validators behind the draws’ randomness, and an avail_epoch_blocks of 0 turns the online check off: no window can be proven and every miner counts as present.
block
curl -s https://testnet-api.dendranetwork.com/rpc/status → sync_info.latest_block_height, the latest block shown in the season’s live figures
validators
curl -s https://testnet-api.dendranetwork.com/rpc/validators
payments
Each weekly payment is an on-chain transfer sent by the season’s payout account to the payout address, with a memo starting dendra-final-season-week-. The memo alone proves nothing, since anyone can write it: the payment finds its own parts by their sender (final_season_payout.py::paid_parts), and your points are the paid_udndr of the rankings.

Each ranking row gives an identity’s counts, its payout address, its gross, payable and paid reward, and the reason for any shortfall. Amounts are in udndr: 1 DNDR = 1,000,000 udndr.

A season day is 17 280 blocks, counted from the season’s start height: about 24 hours at about 5 seconds per block, an interval the chain does not fix. The last day is cut at the season’s end, so how many days the season holds follows from the chain’s pace. A day is ranked once all its requests are final, after audit_unwind_blocks; the last day’s ranking names the season’s last block (inputs.season_end_height). A week is seven season days; the last payment covers the days left after the last full week, once the last day is final.

Before paying a week, the payment checks every published day so far against the rules, and pays nothing for the week if one breaks them. No IP address enters the evidence or the formula.

Recompute a day

The script needs Python 3 and the chain client dendrad; the miner container has both. From deploy/testnet-miner/, for the first day:

Recompute day 0 and comparefrom deploy/testnet-miner/
$ docker compose exec miner python3 final_season_rank.py --day 0 \
    --evidence https://testnet-api.dendranetwork.com/final-season/v1/ \
    --node tcp://testnet-api.dendranetwork.com:26657 \
    --generator GENERATOR --start START \
    --compare https://testnet-api.dendranetwork.com/final-season/v1/ranking/day-000.json

Replace GENERATOR and START with the inputs.generator and inputs.start_height of the ranking you check. The ranking also records the day’s last counted block (inputs.last_height) and, on the season’s last day, the season’s last block (inputs.season_end_height); the script derives both from its own node, from the block times, and does not copy them. The script says whether that ranking is identical, and refuses a day that is not final yet or that starts after the season’s end.

Sources

In the public repository, the programme’s files are under services/ and the chain’s under chain/. The rates and caps are in services/final_season_rules.py, and the formula in services/final_season_calc.py.

  • Rates, caps, day length, daily volume (requests_per_day) and the season’s end (end_time): final_season_rules.py, one rule set per period (RULE_HISTORY); the last day’s cut: final_season_rank.py::season_window
  • Formula, in whole udndr: final_season_calc.py::gross_of; pro rata: final_season_calc.py::compute_day
  • Verified request: final_season_facts.py::job_is_final_positive, final_season_facts.py::answered_jobs
  • Sample, and the rule that takes a day’s work away: final_season_server.py::WORK_SAMPLE, final_season_server.py::WORK_PENDING_MAX, final_season_facts.py::GRADES_TO_VOID
  • Presence: final_season_chain.py::presence_proofs; payout address: final_season_facts.py::day_identities, with the default operator from final_season_rank.py::rank_day; address check: final_season_address.py::payable_address
  • Recompute: final_season_rank.py::main
  • Weekly check: final_season_payout.py::check_days; requests: final_season_generator.py::make_prompt
  • Delivered work under an unwound audit: final_season_rules.py::UNWOUND_AUDIT_WORK, final_season_facts.py::unwound_work
  • Stake ceiling: committee.go::capAssignmentWeights; jury seats: audit_committee.go::drawMembersWithDomain; the judge’s model: judge_worker.py::resolve_judge_model