tools/harness runs the standard consensus-attack catalogue against a private test network of our own igneumd nodes (127.0.0.1 ports 27200+, /tmp/igneum-harness, never the live devnet or the PC node), with a pass criterion per scenario from the spec and a measured result each. Built on the node fork's own crates (igneum-harness-sim on kaspa_utils::sim as simpa does; igneum-p2p-probe for the wire). Scenarios: 1 withholding, 2 timestamp edges and drift, 3 partition and heal, 4 eclipse, 5 malformed and boundary inputs on every p2p and RPC surface, 6 resource exhaustion, 7 fast-miner flood. Finality and difficulty-controller scenarios are stubs with their criteria written. bench-log: one dated entry, a row per scenario (criterion, measured, pass or fail). First run: 19 of 20 measured rows pass. Findings recorded in the entry: scenario 5 reproduces ledger M15 on HEAD (bogus past-day or DAA headers build a 256 MiB cache before rejection; the r3-fixes branch removes it); scenario 1 at 45% hash with burst withholding shows a selfish-mining blue-share gain (50.7% of blues), the one failing row. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
36 lines
1.5 KiB
JavaScript
36 lines
1.5 KiB
JavaScript
// Kaspa-style address encoder (copied from tools/observer/observer.mjs). Devnet prefix is igneumdev.
|
|
const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
|
|
function polymod(values) {
|
|
let c = 1n;
|
|
for (const d of values) {
|
|
const c0 = c >> 35n;
|
|
c = ((c & 0x07ffffffffn) << 5n) ^ BigInt(d);
|
|
if (c0 & 0x01n) c ^= 0x98f2bc8e61n;
|
|
if (c0 & 0x02n) c ^= 0x79b76d99e2n;
|
|
if (c0 & 0x04n) c ^= 0xf33e5fb3c4n;
|
|
if (c0 & 0x08n) c ^= 0xae2eabe2a8n;
|
|
if (c0 & 0x10n) c ^= 0x1e4f43e470n;
|
|
}
|
|
return c ^ 1n;
|
|
}
|
|
function conv8to5(bytes) {
|
|
const out = []; let buff = 0, bits = 0;
|
|
for (const b of bytes) {
|
|
buff = ((buff << 8) | b) & 0xffff; bits += 8;
|
|
while (bits >= 5) { bits -= 5; out.push((buff >> bits) & 31); buff &= (1 << bits) - 1; }
|
|
}
|
|
if (bits > 0) out.push((buff << (5 - bits)) & 31);
|
|
return out;
|
|
}
|
|
export function encodeAddress(prefix, version, payload) {
|
|
const five = conv8to5([version, ...payload]);
|
|
const pre = [...prefix].map(ch => ch.charCodeAt(0) & 0x1f);
|
|
const sum = polymod([...pre, 0, ...five, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
const sumBytes = []; for (let i = 4; i >= 0; i--) sumBytes.push(Number((sum >> BigInt(i * 8)) & 0xffn));
|
|
return `${prefix}:${[...five, ...conv8to5(sumBytes)].map(v => CHARSET[v]).join('')}`;
|
|
}
|
|
/// A deterministic devnet pay address for a miner label (32-byte payload from the label).
|
|
export function devAddress(label = 'harness') {
|
|
const payload = Array.from({ length: 32 }, (_, i) => (label.charCodeAt(i % label.length) * (i + 1)) & 0xff);
|
|
return encodeAddress('igneumdev', 0, payload);
|
|
}
|