diff --git a/tools/observer/observer.mjs b/tools/observer/observer.mjs index 9cc45255d..6de8f72dd 100644 --- a/tools/observer/observer.mjs +++ b/tools/observer/observer.mjs @@ -46,6 +46,7 @@ import { readFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { blockSubsidy } from '../../site/lib/emission.mjs'; import { keccak256 } from '../../site/lib/eth.mjs'; +import { vendorShareTick } from './vendor-share.mjs'; const RPC = process.env.IGNEUM_RPC || 'ws://127.0.0.1:28610'; const RETAIN_HOURS = Number(process.env.LIVE_RETAIN_HOURS || 24); @@ -128,6 +129,8 @@ async function setupSchema() { // Explorer: this process's RPC calls per minute, and the hourly coinbase-versus-rule comparison `ALTER TABLE ${TS} ADD COLUMN IF NOT EXISTS rpc_load jsonb`, `ALTER TABLE ${TS} ADD COLUMN IF NOT EXISTS supply_check jsonb`, + // Vendor share (Counter ASIC 3.0 item 7, tools/observer/vendor-share.mjs): hash rate by vendor, fleet-reported and chain-attributed + `ALTER TABLE ${TS} ADD COLUMN IF NOT EXISTS vendor_share jsonb`, // One row per planned shard of a chain block (spec 7.7 item 8): the plan as the block joins the chain, then the // record's progress. prover is the first 8 hex characters of the record's vote key hash (never the full key, R4.6.2). `CREATE TABLE IF NOT EXISTS ${TP} ( @@ -1008,6 +1011,7 @@ async function provingState() { // of every block it merges (utxo_validation.rs:176 pays a merged block what its own payload declares; blues and reds // inside the DAA window alike). Written to live_state.supply_check; /api/supply shows it beside the rule's total. const SUPPLY_CHECK_EVERY_MS = 60 * 60_000, SUPPLY_SAMPLE = 500; +const VENDOR_SHARE_EVERY_MS = 60_000; // live_state.vendor_share, written by tools/observer/vendor-share.mjs let lastSupplyCheck = null; async function supplyCheck() { try { @@ -1138,6 +1142,7 @@ async function main() { setInterval(() => tick(rpc), STATE_EVERY_MS); setInterval(prune, PRUNE_EVERY_MS); setInterval(supplyCheck, SUPPLY_CHECK_EVERY_MS); setTimeout(supplyCheck, 20_000); + setInterval(() => vendorShareTick(sql, T, log), VENDOR_SHARE_EVERY_MS); setTimeout(() => vendorShareTick(sql, T, log), 30_000); tick(rpc); prune(); } diff --git a/tools/observer/vendor-share.mjs b/tools/observer/vendor-share.mjs new file mode 100644 index 000000000..026bd8e13 --- /dev/null +++ b/tools/observer/vendor-share.mjs @@ -0,0 +1,233 @@ +// The vendor-share metric (Counter ASIC 3.0 item 7, docs/analysis/asic-resistance-history.md section 4.3 rank 7; +// docs/benchmarks/repro.md section 8). Hash rate by vendor (nvidia, amd, apple, intel, unknown), two ways, each +// named for what it is: +// +// (a) fleet_reported: the sum of "now=X MH/s wall" from the newest STATUS line of every miner worker that reported +// to the log intake (miner_logs, labels miner---) in the last 10 minutes. +// It covers ONLY the machines that upload to the intake: the project's own fleet and any app install that +// carries the intake key. It says nothing about the rest of the network. +// (b) chain_attributed: every miner id's (vote_key_hash) share of the BLUE blocks of the last 10 minutes +// (live_blocks.color = 'blue'; pending and red blocks are left out) times the node's network hash-rate +// estimate (live_state.hashes_per_second_estimate), attributed to a vendor where the vote key is one a fleet +// worker logged ("identity N '