Repository navigation
Releases
Instawards · Week 4
Week 4 changelog, as of Thu 12 Nov 2026, 21:03 Chile time. English is the official text; la versión en español está más abajo. It goes into CHANGELOG.md when the run ends on Tue 17 Nov.
Week 4 — 9 to 13 November 2026
Summary
This week the seven-day live run started on Stellar testnet, one day later than planned, and so far every hour has been judged and anchored. On Mon 9 Nov tests A–D and the independence test passed on a fresh 2/2/3 rehearsal account (PR #66). The stand-in drill and the kill tests were not done, and both founders decided to go anyway (PR #67). The run started by itself on Tue 10 Nov at 00:00 Chile time (03:00 UTC), from commit 9ee4646 (tag code-freeze); the day's delay is deviation DV-12 (PR #65). It ends on Tue 17 Nov at 00:00. By Thu 12 Nov at 21:03 Chile time, all 69 hourly batches had been anchored on the run's 2-of-3 account, each signed by the proposer and the verifier, and the reconciliation read RECONCILED. 12 five-minute intervals had been refused, every one of them on the list published before the run, including the first two injected faults, F01 and F02. The reconciliation page on qwatt.org now opens the run by itself (PR #69). We also corrected our own record: the verifier stop of Mon 9 Nov, before the start, was a manual stop made by mistake (PR #70). On Thu 12 Nov a Windows update restarted the Linux layer of the verifier's computer: the verifier was down for about 5½ minutes between two anchors, and no batch waited. All input is still simulated, assurance A0.
Added
-
The live run on Stellar testnet. It was armed on Mon 9 Nov at 19:19 Chile time at
9ee4646, started with no manual step on Tue 10 Nov at 00:00 and runs for 7 days. The run accountGDSEQAD3…4MDCanchored its first batch,QW#0, at 01:01 Chile time:31b72314…, ledger 5,651,924. Each anchor writes on Stellar testnet the batch's SHA-256 (qwatt.anchor.sha256) and the running total of simulated energy (qwatt.cumulative_mwh), with the memoQW#n. By Thu 12 Nov at 21:03 Chile time there were 69 anchors,QW#0toQW#68: one for every hour, none missed, each landing within 3 minutes of its hour's close. -
The run's public evidence (SOW Deliverable 4):
- the feed,
qwatt-evidence/run. It holds every batch, its raw readings, the accepted and rejected ledgers, andfaults.json, which was published before the start with the eight faults, the code commit and the three public keys; - the verifier's log,
qwatt-verifier-log/run: each decision, with the feed commit it read (but see Blockers); - the reconciliation of the run, in any browser: qwatt.org/reconcile.html, which opens the run by itself since Wed 11 Nov. On Thu 12 Nov at 21:03 Chile time the same check, run as
anchor/reconcile-cli.js, read RECONCILED: 69 of 69 batches anchored, all by the proposer and the verifier, none by a stand-in, and the account at 2/2/3 with master weight 0.
- the feed,
-
The rejection log is filling as planned. By Thu 12 Nov at 21:03 Chile time, 12 intervals had been refused, and each one is on
live/expected-run.json, the list published before the run (12 of its 30 entries so far):- at dawn on Tue 10, Wed 11 and Thu 12 Nov, the interval that starts at 06:45 Chile time, for
plausibility.energy_power. The first was logged under batchqwatt-chispa-01-000006; - F01, a shaded sensor, Wed 11 Nov from 13:05 to 13:25 Chile time: 4 intervals,
agreement.diverge, logged under batchqwatt-chispa-01-000037; - F02, a disconnected meter, Thu 12 Nov from 12:05 to 12:25: 4 intervals,
agreement.diverge, logged under batchqwatt-chispa-01-000060; - at dusk on Thu 12 Nov, the interval that starts at 20:25, for
plausibility.energy_power.
A refused interval is left out of its batch's energy (the batch only counts it), so it never makes the verifier refuse a batch, and the verifier refused none. As of Thu 12 Nov at 21:03 Chile time, the next faults were F03, a night injection, on Fri 13 Nov at 01:35 Chile time, and F04, an implausible ramp, at 14:35.
- at dawn on Tue 10, Wed 11 and Thu 12 Nov, the interval that starts at 06:45 Chile time, for
-
Energy re-derivation (PR #64).
node live/rederive.js <feed-dir>replays the publishedsamples/*.csvthrough the same adapter and interval builder the run uses. It then compares every published interval's energy, sample count, mean power and the hash of its raw readings (source.raw_sha256), and recomputes the energy of accepted batches. No service runs it, and it only prints its result. On a simulated run it found 2,016 of 2,016 intervals equal. At the close, RUNBOOK step 3 saves its output asevidence/energy-rederivation.json, and a mismatch there is a finding to publish, not something to fix. -
The write-up lists every outage (PR #63).
ops/writeup.jsnow has an "Outages (OD-8)" section: host gaps from the audit, anchors that landed late, the cause of each where the founders recorded one, and a verdict on the seven days. -
Evidence documents for Deliverables 2 and 3 (PR #71):
docs/DELIVERABLE-2-EVIDENCE.mdanddocs/DELIVERABLE-3-EVIDENCE.md. Each maps the SOW's evidence of completion (§6) to public files and transactions, and lists what was not done, the deviations and the decisions still open. -
Tests A–D and the independence test: PASS (PR #66). They ran as
rehearsal-2026-11-09on a fresh rehearsal account,GCJ5LL6T…E4GY, with the same three public keys and both hosts at9ee4646. All of them used one proposal,d75c10d7…:- A, the proposer alone: refused by the network (
tx_bad_auth); - B, the verifier alone, on the same transaction body: refused (
tx_bad_auth); - D, the batch altered after the proposer signed: the verifier refused (
verifier.hash_mismatch), and nothing was submitted; - independence, the batch withheld from the verifier's only input path (the public feed was not touched): the verifier refused (
verifier.not_published), and nothing was signed; - C, the proposer and the verifier: anchored on Mon 9 Nov at 19:00 Chile time, ledger 5,647,595.
The evidence is in
evidence/rehearsal/2026-11-09-abcd/. - A, the proposer alone: refused by the network (
-
Between the weeks (Sat 7 – Sun 8 Nov): the first anchor on a 2/2/3 account with the sprint's three keys. The rehearsal
rehearsal-2026-11-07ran on the rehearsal accountGBITYDTM…HFC2. At 20:43 Chile time on Sat 7 Nov it anchored test C, signed by the proposer and the verifier:13457b4b…, ledger 5,614,274. It anchored 24 batches in all, up to Sun 8 Nov at 12:30 Chile time (15:30 UTC). Tests B, D and independence were refused as expected, as the freeze's DV-12 entry records; that rehearsal's test files are not public, and the tests of Mon 9 Nov replace them. Test A, the stand-in drill and the kill tests did not run that day. -
The go decision, and a correction, on the record. A dated status note in the architecture freeze lists what ran on Mon 9 Nov and what did not, and records the go, at about 19:20 Chile time, in the same minutes as the arming (PR #67). A second note, of Wed 11 Nov, corrects what the first said about the verifier stop (PR #70; see Blockers).
Changed
- The run starts on Tue 10 Nov, not Mon 9 (DV-12, PR #65, merged Mon 9 Nov). The Sat 7 Nov rehearsal did not get through test A, the stand-in drill, the kill tests or the go/no-go, so the services were not armed for Mon 9. The run now covers Tue 10 Nov 00:00 to Tue 17 Nov 00:00, Chile time (03:00 UTC), days 23 to 29 of the sprint. The eight faults moved with it, to Wed 11 – Mon 16 Nov. The expected list was regenerated with the same seed: 30 refusals in 2,016 intervals.
- The run's code is frozen at
9ee4646, the commit both hosts run (code_commitinrun/faults.json). The tagcode-freezewent on it on Tue 10 Nov at 17:49 Chile time, about 18 hours after the start. On Wed 11 Nov, during the run, eight pull requests reachedmain: fixes and one new tool for checking and closing the run (#60 to #64), which no service on ei...
Instawards · Week 2
Full changelog: CHANGELOG.md · Español: CHANGELOG.es.md
Summary
This week we built what the real 2-of-3 anchoring account needs, so that creating it is a set of commands and not new code. Every key is now created on the machine that uses it and signs through stellar-cli. Every batch carries a fingerprint of its raw readings, and the verifier reads the public evidence pinned to one git commit and publishes its own log. The reconciliation page is back on qwatt.org. Tests went from 194 to 449, all passing. The account itself, tests A–D and the first anchor did not happen this week, because two of the three public keys are still missing (see Blockers). All input is simulated.
Added
-
Signing through stellar-cli, never with a secret in a file (V3-8):
- the proposer and the verifier ask stellar-cli 28.1.0 to sign, and refuse to start if a secret key is in their environment (PR #18);
- the account is set up from the four public keys only. The setup and funding transactions are rebuilt from public values and checked before anything signs, and docs/THIRD-SIGNER.md tells the signer from outside the team what to do (PR #22);
keys.js checkconfirms a key on its own machine without reading it, and a backup drill proves that each paper backup restores the same key before the account is created (PR #23).
-
A fingerprint of every raw reading in each batch (V3-5,
samples_root, batch format 1.1.0, deviation DV-6). The raw readings are published next to each batch inraw/<batch_id>.jsonl, and every reader recomputes the fingerprint (PR #24). The live-run audit ties every raw reading to a row of a published samples file (PR #28). -
Two public evidence repositories, each written by one host only (V3-7):
- the publisher, with integrity rules, consistent snapshots and an audit of the public history (PR #19);
- the verifier's public log (its decisions, its refusals and its status), published only from the verifier's host (deviation DV-8; PR #25, PR #26);
- every reader takes one commit of the evidence, after reading Stellar, and reads every file at that commit, so it never mixes two versions (PR #29);
- Jay Kim created academiaseul/qwatt-evidence and academiaseul/qwatt-verifier-log: public, MIT-licensed, each with two rules on GitHub, one that forbids deleting or rewriting the history and one that lets only its host's deploy key push. Nothing is published in them yet.
-
Tests A–D and the independence test, ready for the real account (V3-4a, deviation DV-7), run as one sequence. In the independence step the real verifier code must refuse a batch withheld from its only input (PR #27). They were tested against a simulated network; they have not run on the real account, which does not exist yet.
-
Clock offset on every input path (V3-6,
clock_skew_s): each interval records how far the node's clock was from the gateway's (PR #14, PR #15). -
Host package (PR #32). One script installs either host from a given commit:
- Node 24.14.1 and stellar-cli 28.1.0, each checked against its official SHA-256;
- the services of that host's role only, and its deploy key;
- on Windows, a task that keeps WSL running with no window open and starts it after a reboot with nobody signed in;
- 26 acceptance tests, 23 of them automated.
A new CI job installs it on a clean Ubuntu machine for each role. That job found a defect before the merge: the deploy key's private file was left readable by others (644), and ssh refuses such a key. Jay installed the verifier's host on his PC with this package, with no failed check. His verifier key was created on that machine, in his own terminal, and backed up on paper; its public key is
GAJCK4PA3CFEZNQD3TLVWWSMHIXGIBV33SIYWZM6CUTMLH7LQKKSYI3U. -
CI runs every test step even after an earlier one fails, so a red commit records every failing suite (PR #13).
Changed
- The reconciliation reads the account from Stellar: its signers, its thresholds and the signatures of every anchor (V3-9.1, PR #16, PR #17). Each run's
faults.jsonnow carries the fixed label "Simulated input · assurance A0 · Stellar testnet", the three signer public keys and the commit of the code it started from (V3-9.2, PR #21). - The reconciliation page is back at qwatt.org/reconcile.html, on the site template, in Spanish and English. It says that there is no public feed yet (V3-9.3, PR #31).
- A neutral site name,
qwatt-chispa-01. Batch ids readqwatt-chispa-01-000000and name no place (FD-14, PR #30). - The August ideas are back on qwatt.org, each labeled TESTNET, PROTOTIPO or PLANIFICADO, with a verification page that re-derives a published batch in the browser (PR #12).
Fixed
- No energy is estimated across a meter dropout longer than three sample periods (V3-10, PR #20).
- Three defects found by Diego Ostertag's review of PRs 8 to 14 (27 Oct), each fixed with a failing test first:
- a "file not found" at a pinned commit was remembered for that commit, so one delay of GitHub's file server right after a push could become a public refusal that no later check corrected. Now the file is read once more and a miss is never remembered (PR #29);
- a power cut in the middle of a write could leave the verifier unable to start again. Now a half-written last line is removed before the next line is written (PR #26);
- test C took the latest anchor instead of the transaction that tests A and B used. Now it looks that transaction up (PR #27).
- An empty file named
=1000, which reached main by mistake, was removed (PR #27).
Progress vs. last week
Last week's "Next week" goals:
- Goal: create the real 2-of-3 account → Result: not done. It moves to Sat 31 Oct – Sun 1 Nov, the plan's margin. It still needs the proposer's public key, which waits for the proposer's server, and the public key of the signer from outside the team.
- Goal: tests A–D and the independence test on that account → Result: built and tested against a simulated network (PR #27); not run, because the account does not exist.
- Goal: a fingerprint of all raw readings in every batch → Result: done (PR #24, PR #28). The first anchor and its evidence in the new repositories → not done.
- Also due in week 2 under freeze v3:
- every input path records its clock offset → done;
- each key is created on its own machine → done in code, and the verifier's key now exists;
- the reconciliation reads signers and thresholds from Stellar → done;
- no energy estimated across a dropout → done.
- Mid-week post with test A → not done: test A needs the account.
In numbers
- Tests: 194 passing at
semana-1→ 449 passing on main at03169a8, 0 failing (342 innpm test, 107 anchoring tests). CI on main: run #117. - Pull requests merged: 21 (#12 to #32). Commits on main from
semana-1to03169a8: 72, not counting merge commits. - Deviations from freeze v3 approved by both founders: DV-6, DV-7 and DV-8.
Blockers and lessons
-
Two public keys are missing. The account is created only with all three keys:
- the proposer's key waits for the proposer's server, an always-on machine at a cloud provider, which was not set up this week;
- the signer from outside the team has been chosen and has the instructions; their public key has not arrived.
If it has not arrived by the evening of Sun 1 Nov, both founders will write a numbered deviation together, never a quiet change.
-
PR #25 was merged with only its failing test, so main was red until PR #26 brought the change. It is the same lesson as week 1: merge a test together with its fix.
-
Installing on a clean machine finds what tests in place do not. The deploy key left readable by others showed up only when the package ran on a fresh Ubuntu machine in CI. On Jay's PC, the Windows script registered its task before asking for the password, and Windows refused it (0x8007052E). Jay ran a corrected copy that worked; the fix to the repository is open as [PR #33](https://github.com...
Instawards · Week 1
Full changelog: CHANGELOG.md · Español: CHANGELOG.es.md
Summary
QWATT is an open-source verifier that turns solar meter readings into records on Stellar testnet that anyone can re-check from public data alone; it cannot show that a meter is accurate or that the energy was really produced. This week we closed two ways to fool our own verifier, plus four more found by reviewing those fixes; tests went from 154 to 194, all passing. All input is simulated (no real meter was read), and we sent 0 testnet transactions this week, on purpose.
Added
- Prior work, public and labeled. Diego Ostertag's 20 commits from 8 to 17 Oct were brought into this repository with their original dates and author (PR #4). The tag
dia-1(7336e20) marks the cut-off, and docs/PRIOR-WORK.md lists everything before it (added in6be021f). - 40 new automated tests (154 → 194), most of them tampering attempts that must be refused.
- Architecture freeze v3 (docs/ARCHITECTURE-FREEZE-v3.md,
b304ddb), agreed by both founders on Wed 21 Oct (Day 3) and written into the repository on Thu 22 Oct. It sets the evidence format, the signing and rejection rules, and the plan for each week. It reached main in a later pull request, after PR #10 (see Blockers). - Evidence for Deliverable 1, reading any meter (
cae00a6, PR #10): docs/DELIVERABLE-1-EVIDENCE.md, the saved output of the acceptance test (evidence/harness/harness-c1ae630.txt) and 5 new meter-reading tests. One of them tests Modbus RTU (Modbus over a serial cable) on a simulated port. - License notices for third-party code and public data:
THIRD_PARTY_NOTICES.mdanddatasets/LICENSE(141089a). One point is still open: a file from the August prior work,assets/vendor/stellar-wallets-kit.js(not deployed on the site), bundles a GPL-3.0 package, and we have not yet decided whether to keep it. - CHANGELOG.es.md: this changelog in Spanish.
Changed
- A rejected batch no longer adds energy to the running total that will be written to Stellar testnet; it carries the previous total forward (
8385da3, PR #8). Planned for week 3, built now because without it the same energy could count twice. - Thresholds 2/2/3 for the anchoring account (
075b14etest,666c65bchange, PR #9). On that account, which does not exist yet, no single key, not even one of our two, will be able to send a transaction; anchoring will need 2 of the 3 keys, and changing signers or thresholds all 3. Our two team keys together can anchor without the signer from outside the team, but cannot change signers or thresholds without the third key. Built into the account setup tool and its check, and tested against a simulated network; the real account is planned for next week. - Prior work relabeled accurately (
141089a). The 8 Oct run once called a "two-day live run" is now described as what it was: an accelerated rehearsal of 48 simulated hours in 4 min 18 s, on throwaway testnet accounts. Energy totals in our reports now say "Simulated input · Stellar testnet". - README, website and
stellar.toml(the public file that describes our Stellar testnet accounts) now describe the sprint, say that the input is simulated, and say that we use testnet only (152e088, PR #2;8175ba9,799ab5a, PR #6;155fb0f, PR #3). The demo page names the anchored value correctly:qwatt.cumulative_mwh, in milliwatt-hours (ad71bee).
Fixed
Flaws 1 and 2 were found in our own code review on 12 Oct, before Day 1. They affected no real record: the real anchoring account does not exist yet, and every rehearsal used throwaway accounts.
- Flaw 1 (S1), "the inherited total". The independent verifier copied the previous batch's running total from our published file without checking it, so an altered file could inflate the total. Now, before signing, it walks the chain back to the last batch anchored on Stellar and recomputes every fingerprint and total. Test
bdd5784(PR #7), fix09210b0(PR #5). - Flaw 2 (S2), "the same energy, twice". A batch rebuilt from intervals already counted passed as new. Now intervals that are repeated, overlapping, off the 5-minute grid or from another installation are refused. Test
6204b12(PR #5), fix40aaa3d(PR #1). - Review of both fixes: four more ways to count the same energy twice, closed (DV-1 to DV-4 in freeze v3). Test
301bc50(PR #1), fix8385da3(PR #8):- each new batch is checked against the last accepted batch only, never a rejected one, so a rejected batch cannot reopen time already counted;
- each earlier batch is downloaded once and its fingerprint checked before it is read;
- the input stage refuses just the interval, not its whole batch, when it comes from another installation or device or overlaps the previous one;
- the web (HTTP) input stores each timestamp in one standard format, and rejects an off-grid interval at once instead of accepting it and dropping it later.
- One way anchoring could stop for good (DV-5, same commits). After more than 168 rejected batches in a row (a week of hourly batches), the verifier refused the next batch again and again with the error code meant for a forged chain, and nothing could be anchored again without changing the code. Reaching the walk's limit now has its own code,
verifier.walk_too_long, and the proposer runs the same walk before proposing.
Removed
- Google Analytics from the home page, the demo page and the error page (
8175ba9,799ab5a). - The 11 pages of the August 2026 hackathon from qwatt.org; their URLs now redirect to the home page (
c3fd035, PR #3). - The reconciliation page (which checks every anchor on Stellar against the published batches) from the site, until it reads the account's signers and thresholds from Stellar instead of stating them (
141089a). - Old pitch material, internal documents, earlier versions of our proposal and local editor settings from the repository's current files (
152e088,772b8f3,c2fd8db,16bc6c2,184f885,26e615c). They remain in the public git history.
Progress vs. last week
This is our first week, so "last week" is the prior work that existed before Day 1 (Mon 19 Oct), listed in docs/PRIOR-WORK.md. It is not funded by the Instawards program and is not counted below. "Goal (Monday)" means a goal we set on Day 1.
- Goal (Monday): prior work public, labeled and tagged
dia-1→ Result: done Wed 21 Oct (PR #4,7336e20). - Goal (Monday): Flaw 1 closed, red to green → Result: done. Red in run #19, green in run #29 (pull request) and on main in run #30.
- Goal (Monday): Flaw 2 closed, 4 of 4 attempts refused → Result: done, 4 of 4. Red in run #17, green in runs #29 and #30.
- Goal (our proposal, days 1–3): agree on the architecture → Result: architecture freeze v3 agreed on Day 3, Wed 21 Oct, and written into the repository on Day 4 (
b304ddb). - Goal (our proposal, week 1): Deliverable 1, read any meter (Modbus, HTTP or CSV) with byte-identical output → Result: the reader was built before Day 1 (prior work,
98b281a, 9 Sep). This week we added its evidence (cae00a6): 24 of 24 intervals accepted, identical across the three inputs, with Modbus read from a simulator. Three items stay open (see Blockers). - Goal (our proposal): a signer from outside the team, designated at kickoff → Result: confirmed this week, not at kickoff.
In numbers
- Tests: 154 passing at
dia-1→ 194 passing on main, 0 failing (run #34). - Tests for the two flaws: 10 written, 9 of them cases that must be refused, and all 9 are. 5 were red until their fix landed; the other 5 came with the fix.
- Review of the fixes: 14 new tests and 6 rewritten; 19 of those 20 were red before the fix and are green after. Thresholds: 11 new tests, 8 of them red without the change (checked locally).
- No change for untampered data: one month of a public research dataset (NREL PVDAQ, September 2017; not our measurements), replayed offline as 720 batches, still verifies with 0 rejected and the same final fingerprint as at
dia-1. Nothing is sent to Stellar in this test. - Commits: 30 on main from
dia-1to4ac5632, plus `b304...