Merge miner-ui-4 4af9ab4 for 0.3.15: the chain's own words back on user surfaces (shard, segment, checkpoint, aggregator, verifying), each with one grey explanation
Every file under app/igneum-app/ui/ is that branch's side; the Rust files are as in 7ce5965.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
commit
fa20b72fea
4 changed files with 36 additions and 33 deletions
|
|
@ -499,17 +499,17 @@ var View = (function () {
|
|||
// the Prove page: pv = state.proving, enabled = state.settings.prove, synced = state.node.synced
|
||||
function proveWords(pv, enabled, synced) {
|
||||
pv = pv || {};
|
||||
if (!enabled) return { word: 'off', sub: 'not proving', tone: 'off', note: 'Off. Switch it on and this machine proves the pieces it is given.' };
|
||||
if (!enabled) return { word: 'off', sub: 'not proving', tone: 'off', note: 'Off. Switch it on and this machine proves the shards it is given.' };
|
||||
if (pv.status === 'setup' || (pv.enabled && !pv.available && pv.setup_hint)) return { word: 'needs setup', sub: 'one-time install', tone: 'bad', note: pv.setup_hint || pv.message || 'The prover is not installed yet.' };
|
||||
if (!synced || pv.status === 'waiting') return { word: 'waiting', sub: 'for the node to sync', tone: '', note: pv.message || 'Proving starts once the node has every block.' };
|
||||
if (pv.status === 'proving') return { word: 'proving', sub: pv.current || 'a piece', tone: 'on', note: pv.message || 'A proof takes minutes on a CPU and seconds on an NVIDIA card.' };
|
||||
if (pv.status === 'proving') return { word: 'proving', sub: pv.current || 'a shard', tone: 'on', note: pv.message || 'A proof takes minutes on a CPU and seconds on an NVIDIA card.' };
|
||||
if (pv.status === 'submitted') return { word: 'submitted', sub: 'waiting to be paid', tone: 'on', note: pv.message || 'The node checks the proof, then the chain pays it.' };
|
||||
if (pv.status === 'idle') return { word: 'idle', sub: 'nothing assigned', tone: 'ok', note: pv.message || 'On. Nothing to prove right now. The next piece arrives within a minute.' };
|
||||
if (pv.status === 'idle') return { word: 'idle', sub: 'nothing assigned', tone: 'ok', note: pv.message || 'On. Nothing to prove right now. The next shard arrives within a minute.' };
|
||||
return { word: pv.status || 'on', sub: pv.backend ? pv.backend.toUpperCase() : '', tone: '', note: pv.message || '' };
|
||||
}
|
||||
function verifierWords(pv) {
|
||||
var vm = (pv && pv.verifier_mode) || 'unknown';
|
||||
var word = { command: 'checking proofs', trust: 'trusting without checking (devnet only)', off: 'off, passing proofs along', unknown: 'not read yet' }[vm] || vm;
|
||||
var word = { command: 'verifying', trust: 'trusting without verifying (devnet only)', off: 'off, passing proofs along', unknown: 'not read yet' }[vm] || vm;
|
||||
if (vm === 'command' && pv.pool_entries) word += ' · pool ' + pv.pool_verified + '/' + pv.pool_entries + (pv.pool_failed ? ', ' + pv.pool_failed + ' rejected' : '');
|
||||
return { word: word, tone: vm === 'command' ? 'ok' : (vm === 'off' || vm === 'trust') ? 'warn' : 'dim', needsSetup: vm === 'off' && /WSL2 prover is not installed/.test((pv && pv.verifier_reason) || '') };
|
||||
}
|
||||
|
|
@ -518,7 +518,7 @@ var View = (function () {
|
|||
function proveTier(cd) {
|
||||
var gb = cd.vram_mb ? Math.round(cd.vram_mb / 1024) : 0;
|
||||
if (cd.vendor === 'apple') return cd.name + ': proves on the CPU, slowly.';
|
||||
if (cd.vendor === 'nvidia') return gb >= PROVE_GB ? cd.name + ': proves while it mines (' + gb + ' GB; a full piece needs ' + SHARD_GB + ' GB).' : cd.name + ': cannot prove a full piece (' + gb + ' GB; a full piece needs ' + SHARD_GB + ' GB).';
|
||||
if (cd.vendor === 'nvidia') return gb >= PROVE_GB ? cd.name + ': proves while it mines (' + gb + ' GB; a full shard needs ' + SHARD_GB + ' GB).' : cd.name + ': cannot prove a full shard (' + gb + ' GB; a full shard needs ' + SHARD_GB + ' GB).';
|
||||
return cd.name + ': cannot prove yet (proving needs an NVIDIA card).';
|
||||
}
|
||||
// the counts in one sentence: "idle · nothing assigned · 0 assigned · 0 proven · 0 paid · 0.0000 IGN"
|
||||
|
|
@ -619,11 +619,11 @@ var View = (function () {
|
|||
[/^GPU worker built from source/, function () { return 'Mining program built'; }],
|
||||
[/^block (\d+) shard (\d+) paid (.+) IGN/, function (m) { return 'Proof paid: ' + m[3] + ' IGN'; }],
|
||||
[/^block (\d+) shard (\d+) proven and submitted in (\d+) s/, function (m) { return 'Proof sent in ' + m[3] + ' s'; }],
|
||||
[/^segment .+ paid (.+) IGN to the aggregator/, function (m) { return 'Run of blocks paid: ' + m[1] + ' IGN'; }],
|
||||
[/^segment (\S+)\.\.(\S+) aggregated and submitted in (\d+) s/, function (m) { return 'Run of blocks proven in ' + m[3] + ' s'; }],
|
||||
[/^segment (\S+)\.\.(\S+): (\d+) shards proven, aggregated and submitted in (\d+) s/, function (m) { return 'Run of blocks proven: ' + m[3] + ' pieces in ' + m[4] + ' s'; }],
|
||||
[/^segment (\S+)\.\.(\S+): (\d+) shards proven and submitted in (\d+) s; the segment record is held/, function (m) { return 'Run of blocks proven: ' + m[3] + ' pieces in ' + m[4] + ' s. Its record waits for the chain'; }],
|
||||
[/^segment (\S+)\.\.(\S+) record accepted on retry/, function () { return 'Run of blocks accepted'; }],
|
||||
[/^segment .+ paid (.+) IGN to the aggregator/, function (m) { return 'Segment paid: ' + m[1] + ' IGN'; }],
|
||||
[/^segment (\S+)\.\.(\S+) aggregated and submitted in (\d+) s/, function (m) { return 'Segment proven in ' + m[3] + ' s'; }],
|
||||
[/^segment (\S+)\.\.(\S+): (\d+) shards proven, aggregated and submitted in (\d+) s/, function (m) { return 'Segment proven: ' + m[3] + ' shards in ' + m[4] + ' s'; }],
|
||||
[/^segment (\S+)\.\.(\S+): (\d+) shards proven and submitted in (\d+) s; the segment record is held/, function (m) { return 'Segment proven: ' + m[3] + ' shards in ' + m[4] + ' s. Its record waits for the chain'; }],
|
||||
[/^segment (\S+)\.\.(\S+) record accepted on retry/, function () { return 'Segment record accepted'; }],
|
||||
[/^WSL2 prover setup started/, function () { return 'Prover setup started in its own window'; }],
|
||||
[/^Card removed: (.+); its worker stopped/, function (m) { return 'Card removed: ' + m[1]; }],
|
||||
[/^(.+): not usable \((.+?)\); its worker stopped/, function (m) { return m[1] + ': not usable (' + m[2] + ')'; }],
|
||||
|
|
@ -995,7 +995,7 @@ if (typeof document !== 'undefined') (function () {
|
|||
$('r-wallet').addEventListener('click', function () { api('api/open', { url: 'https://igneum.network/wallet' }); });
|
||||
|
||||
// ---------- Prove ----------
|
||||
$('s-prove').addEventListener('change', function () { var on = this.checked; api('api/prove', { on: on }).then(function (r) { if (r.ok) toast(on ? 'Proving on. The first piece arrives within a minute' : 'Proving off'); else { toast(r.error || 'could not change'); $('s-prove').checked = !on; } }); });
|
||||
$('s-prove').addEventListener('change', function () { var on = this.checked; api('api/prove', { on: on }).then(function (r) { if (r.ok) toast(on ? 'Proving on. The first shard arrives within a minute' : 'Proving off'); else { toast(r.error || 'could not change'); $('s-prove').checked = !on; } }); });
|
||||
$('pv-setup').addEventListener('click', function () { api('api/prove/setup', {}).then(function (r) { toast(r.ok ? 'Setup started in its own window' : (r.error || 'could not start')); }); });
|
||||
|
||||
// ---------- Settings ----------
|
||||
|
|
@ -1570,7 +1570,7 @@ if (typeof document !== 'undefined') (function () {
|
|||
$('n-switches').innerHTML = (n.consensus_switches || []).map(function (x) { return '<span class="' + (sw && x.key === sw.key ? 'next' : x.daa <= n.daa ? 'past' : '') + '"><span>' + esc(x.name) + (x.daa <= n.daa ? ' (applied)' : '') + '</span><span>' + withCommas(x.daa) + '</span></span>'; }).join('');
|
||||
}
|
||||
if (f.last_lock > 0) { setText('f-lock', '#' + withCommas(f.last_lock) + ' · ' + rel(f.age_s)); setText('f-note', 'a point the miners agreed can never be undone. It locks at two thirds of the last 30 days of mining'); }
|
||||
else { setText('f-lock', 'none yet'); setText('f-note', f.message || 'locks appear once this machine votes'); }
|
||||
else { setText('f-lock', 'none yet'); setText('f-note', f.message || 'checkpoints lock once this machine and the others vote'); }
|
||||
setText('f-votes', withCommas(f.votes));
|
||||
}
|
||||
|
||||
|
|
@ -1610,10 +1610,10 @@ if (typeof document !== 'undefined') (function () {
|
|||
setText('pv-note', (!enabled && pv.default_note) ? pv.default_note + '.' : w.note);
|
||||
var v = View.verifierWords(pv);
|
||||
setText('pv-verifier', v.word); $('pv-verifier').className = 'v ' + v.tone;
|
||||
setText('pv-verifier-help', pv.verifier_note || 'the node checks a proof before it counts');
|
||||
setText('pv-verifier-help', pv.verifier_note || 'the verifier: the node checks a proof before it counts');
|
||||
$('pv-setup-row').hidden = !((pv.enabled && !pv.available && pv.setup_hint) || v.needsSetup);
|
||||
var seg = pv.segments_submitted ? pv.segments_submitted + ' proven whole, ' + (pv.segments_paid || 0) + ' paid' + (pv.segment_paid_wei && Number(pv.segment_paid_wei) ? ' (' + (Number(pv.segment_paid_wei) / 1e18).toFixed(4) + ' IGN)' : '') + (pv.segment_last_s ? ', the last took ' + Math.round(pv.segment_last_s) + ' s' : '') + (pv.segments_held ? ', ' + pv.segments_held + ' waiting for the chain' : '') : 'none yet';
|
||||
setText('pv-seg', seg); setText('pv-seg-note', pv.segment_note && enabled ? pv.segment_note : 'whole runs of blocks this machine proved');
|
||||
setText('pv-seg', seg); setText('pv-seg-note', pv.segment_note && enabled ? pv.segment_note : 'whole segments (runs of 8 blocks) this machine proved');
|
||||
setText('pv-program', pv.program_id || 'not read yet');
|
||||
setText('pv-aggregator', pv.aggregator_id || 'not read yet');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,11 +188,11 @@
|
|||
<div class="card dag-card" id="dag-card">
|
||||
<div class="card-head"><h3>The chain, live</h3><div class="head-right"><span class="eyebrow" id="dag-state">connecting</span><button class="btn tiny ghost" id="dag-pause" aria-pressed="false">Pause</button></div></div>
|
||||
<div class="dag-wrap">
|
||||
<canvas id="dag-live" aria-label="The last two minutes of blocks: your row and the other miners, the main chain as a lit path, locks as bands"></canvas>
|
||||
<canvas id="dag-live" aria-label="The last two minutes of blocks: your row and the other miners, the selected chain as a lit path, checkpoints as bands"></canvas>
|
||||
<div class="dag-tip mono" id="dag-tip" hidden></div>
|
||||
<canvas id="dag" aria-hidden="true" hidden></canvas>
|
||||
</div>
|
||||
<div class="legend"><span><i class="lg you"></i>yours</span><span><i class="lg pending"></i>pending</span><span><i class="lg included"></i>included</span><span><i class="lg excluded"></i>excluded</span><span><i class="lg proven"></i>proven</span><span><i class="lg locked"></i>locked</span><span class="dim" id="dag-note"></span></div>
|
||||
<div class="legend"><span><i class="lg you"></i>yours</span><span><i class="lg pending"></i>pending</span><span><i class="lg included"></i>included</span><span><i class="lg excluded"></i>excluded</span><span><i class="lg proven"></i>proven</span><span><i class="lg locked"></i>locked checkpoint</span><span class="dim" id="dag-note"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="card node-card" id="node-card">
|
||||
|
|
@ -212,8 +212,8 @@
|
|||
<div><span class="k">tips</span><span class="v mono" id="n-tips">0</span><span class="m">open ends of the chain right now</span></div>
|
||||
<div><span class="k">blue score</span><span class="v mono" id="n-blue">0</span><span class="m">blocks on the agreed main chain (the blue score)</span></div>
|
||||
<div><span class="k">next program</span><span class="v mono" id="d-eta">--:--</span><span class="m" id="d-eta-sub">the hourly mining program</span></div>
|
||||
<div><span class="k">last lock</span><span class="v mono" id="f-lock">none yet</span><span class="m" id="f-note">a point the miners agreed can never be undone</span></div>
|
||||
<div><span class="k">votes sent</span><span class="v mono" id="f-votes">0</span><span class="m">this machine signs a lock point every 30 s</span></div>
|
||||
<div><span class="k">last checkpoint</span><span class="v mono" id="f-lock">none yet</span><span class="m" id="f-note">a point the miners agreed can never be undone</span></div>
|
||||
<div><span class="k">votes sent</span><span class="v mono" id="f-votes">0</span><span class="m">this machine signs a checkpoint every 30 s (a point the miners agree can never be undone)</span></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="k">rules fingerprint</div>
|
||||
|
|
@ -314,7 +314,7 @@
|
|||
<div class="lead-row">
|
||||
<div class="lead-text">
|
||||
<h3>Prove on this machine</h3>
|
||||
<p class="help">Every block is turned into a short proof. Your cards prove pieces of it and earn IGN for each one.</p>
|
||||
<p class="help">Every block is turned into a short proof, in pieces called shards. Your cards prove shards and earn IGN for each one.</p>
|
||||
</div>
|
||||
<label class="switch lg" title="Prove on this machine"><input type="checkbox" id="s-prove" aria-label="Prove on this machine"><span class="track"></span></label>
|
||||
</div>
|
||||
|
|
@ -326,16 +326,16 @@
|
|||
<div class="details" id="pv-details" hidden>
|
||||
<div class="kv">
|
||||
<div><span class="k">verifier</span><span class="v" id="pv-verifier">not read yet</span><span class="m" id="pv-verifier-help">the node checks a proof before it counts</span></div>
|
||||
<div><span class="k">segments</span><span class="v" id="pv-seg">none yet</span><span class="m" id="pv-seg-note">whole runs of blocks this machine proved</span></div>
|
||||
<div><span class="k">segments</span><span class="v" id="pv-seg">none yet</span><span class="m" id="pv-seg-note">whole segments (runs of 8 blocks) this machine proved</span></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="k">proof program id</div>
|
||||
<div class="k">shard program id</div>
|
||||
<div class="box mono"><span id="pv-program">not read yet</span><button class="btn tiny" data-copy="pv-program">Copy</button></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="k">combiner program id</div>
|
||||
<div class="k">aggregator id</div>
|
||||
<div class="box mono"><span id="pv-aggregator">not read yet</span><button class="btn tiny" data-copy="pv-aggregator">Copy</button></div>
|
||||
<p class="help">Every proof names the program that made it. Other nodes accept a proof only from these two ids.</p>
|
||||
<p class="help">Every proof names the program that made it: the shard program for one shard, the aggregator for a whole segment. Other nodes accept a proof only from these two ids.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -418,7 +418,7 @@
|
|||
|
||||
<details class="card adv" id="s-advanced">
|
||||
<summary><h3>Advanced</h3><span class="eyebrow">devnet</span></summary>
|
||||
<label class="switch"><input type="checkbox" id="s-vote"><span class="track"></span><span class="sw-text"><b>Vote on lock points</b> <span class="dim">Signs a lock point every 30 s. Votes are what lock the chain. Leave it on.</span></span></label>
|
||||
<label class="switch"><input type="checkbox" id="s-vote"><span class="track"></span><span class="sw-text"><b>Vote on checkpoints</b> <span class="dim">Signs a checkpoint every 30 s. Votes are what lock the chain. Leave it on.</span></span></label>
|
||||
<label class="switch"><input type="checkbox" id="s-trust"><span class="track"></span><span class="sw-text"><b>Trust proofs without checking them</b> <span class="dim">Devnet only. The node includes proofs it never checked. Changing this restarts the node.</span></span></label>
|
||||
<div class="ask inline" id="ask-trust" hidden>
|
||||
<span class="ask-text" id="ask-trust-text"></span>
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ test('the prove words follow the switch, the setup, the node and the status', ()
|
|||
assert.equal(V.proveWords(pv({ status: 'proving', current: 'block 59199 shard 0' }), true, true).sub, 'block 59199 shard 0');
|
||||
assert.equal(V.proveWords(pv({ status: 'submitted' }), true, true).tone, 'on');
|
||||
assert.equal(V.proveWords(pv(), true, true).word, 'idle');
|
||||
assert.equal(V.verifierWords(pv()).word, 'checking proofs · pool 4/4');
|
||||
assert.equal(V.verifierWords(pv()).word, 'verifying · pool 4/4');
|
||||
assert.equal(V.verifierWords(pv()).tone, 'ok');
|
||||
assert.equal(V.verifierWords(pv({ verifier_mode: 'off', pool_entries: 0 })).tone, 'warn');
|
||||
assert.equal(V.verifierWords(pv({ verifier_mode: 'off', verifier_reason: 'the WSL2 prover is not installed' })).needsSetup, true);
|
||||
|
|
@ -294,8 +294,8 @@ test('the Tuning card schedule and the goal consequence', () => {
|
|||
});
|
||||
|
||||
test('the prove tier sentence per card, and the counts in one line', () => {
|
||||
assert.equal(V.proveTier(card()), 'NVIDIA GeForce RTX 5090: proves while it mines (32 GB; a full piece needs 20.4 GB).');
|
||||
assert.equal(V.proveTier(card({ name: 'NVIDIA GeForce RTX 4070', vram_mb: 12288 })), 'NVIDIA GeForce RTX 4070: cannot prove a full piece (12 GB; a full piece needs 20.4 GB).');
|
||||
assert.equal(V.proveTier(card()), 'NVIDIA GeForce RTX 5090: proves while it mines (32 GB; a full shard needs 20.4 GB).');
|
||||
assert.equal(V.proveTier(card({ name: 'NVIDIA GeForce RTX 4070', vram_mb: 12288 })), 'NVIDIA GeForce RTX 4070: cannot prove a full shard (12 GB; a full shard needs 20.4 GB).');
|
||||
assert.equal(V.proveTier(card({ name: 'Apple M5 Max', vendor: 'apple' })), 'Apple M5 Max: proves on the CPU, slowly.');
|
||||
assert.equal(V.proveTier(card({ name: 'AMD Radeon RX 9070 XT', vendor: 'amd', vram_mb: 16384 })), 'AMD Radeon RX 9070 XT: cannot prove yet (proving needs an NVIDIA card).');
|
||||
assert.equal(V.proveLine({ assigned: 0, submitted: 0, paid: 0, paid_wei: '0' }, false, true), 'Off · not proving · 0 assigned · 0 proven · 0 paid · 0.0000 IGN');
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ the project lead, on the Cards screenshot: "'As the fleet' might need some work,
|
|||
prior, hill climb, sweep, DAA, epoch, vote key, digest, manifest, shard, segment, aggregator, verifier, worker, engine
|
||||
become plain words or carry one grey explanation), every state line one short sentence with the number first, labels
|
||||
are nouns and buttons are verbs, no colon where a sentence will do, no two-beat lines, one word for one thing (tune,
|
||||
card). the project lead's rulings folded in: the per-card inherit option is "Default · <shared goal>" in grey, updating when the
|
||||
card). Main's correction (20:0x UK): the chain's own objects keep the words of the site, the litepaper and the ledger,
|
||||
with a grey explanation where they first appear: shard (not piece), segment (not run of blocks), checkpoint and
|
||||
"locked checkpoint" (not lock point), aggregator (not combiner), verifying (not checking proofs); "network blocks (the
|
||||
DAA score)" stays. The rows below that renamed those words are superseded by this correction. the project lead's rulings folded in: the per-card inherit option is "Default · <shared goal>" in grey, updating when the
|
||||
shared goal changes; "Default" wherever a per-card setting follows the shared one (the cap's "Back to Default"); the
|
||||
Cards strip is titled "Ember Tune"; every goal option carries its meaning as a tooltip: Efficiency "most hashes per
|
||||
watt, a little rate traded", Balanced "a little rate for most of the saving", Maximum "most hashes, watts second",
|
||||
|
|
@ -22,14 +25,14 @@ Default "the goal set for all cards". 150 strings changed.
|
|||
| Cards, the cap lines | cap applied: 460 W / cap not applied: Windows needs the administrator prompt / Unpin | Cap in force: 460 W / Cap not set yet. Windows needs the administrator prompt. / Back to Default |
|
||||
| Cards, the row's state word | held for a remote job / stopped after repeated faults | paused for a job from the team / stopped after repeated errors |
|
||||
| Overview, the big button | switch a GPU on below first / no GPU this app can drive / worker starting | switch a card on in Cards first / no card this app can use / card starting |
|
||||
| Prove | verifying / off: relay only / shard program id / aggregator id / a full shard needs 20.4 GB | checking proofs / off, passing proofs along / proof program id / combiner program id / a full piece needs 20.4 GB |
|
||||
| Node details | DAA score / rules digest / next rule switch / signs a checkpoint | network blocks (the DAA score) / rules fingerprint / next rule change / signs a lock point |
|
||||
| Settings | Vote on finality checkpoints / Trust proof records without verifying them / Hill climb | Vote on lock points / Trust proofs without checking them / Fine tuning |
|
||||
| Prove | off: relay only / Every block is turned into a short proof. The chain hands pieces to your cards | off, passing proofs along / Every block is turned into a short proof, in pieces called shards. Your cards prove shards and earn IGN for each one (shard, segment and aggregator keep their names, each explained once) |
|
||||
| Node details | DAA score / rules digest / next rule switch / last lock | network blocks (the DAA score) / rules fingerprint / next rule change / last checkpoint (a point the miners agree can never be undone) |
|
||||
| Settings | Vote on finality checkpoints / Trust proof records without verifying them / Hill climb | Vote on checkpoints / Trust proofs without checking them / Fine tuning |
|
||||
|
||||
Every toast and event sentence lost its semicolon or colon joint for a full stop ("Mining stops. The node keeps
|
||||
running"). "Worker" (the engine's word for a card's mining process) became "card" wherever a user reads it; "engine"
|
||||
became "app"; "shard" became "piece"; "segment" became "run of blocks"; "checkpoint" became "lock point"; "fleet
|
||||
prior" became "what other miners found". The engine's own log strings are untouched: `View.plainEvent` maps them.
|
||||
became "app"; "fleet prior" became "what other miners found". Shard, segment, checkpoint and aggregator stay (the
|
||||
chain's own words), each with a grey explanation where it first appears. The engine's own log strings are untouched: `View.plainEvent` maps them.
|
||||
|
||||
## Every string changed
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue