Metal worker compiles a class v3 program from the pack a prepare line names; igneum-pow chain_dataset_day seam; pow_genesis_dataset_log2 in the override files

main.swift: servePackProgram reads program.h with the packfile.h checks (generator 2 or 3, the class line against
the generator, the seed bytes, IGNEUM_SEEDW_INIT against attempt_words, class and era against the line) and
compiles program_bound.metal; the program store keys on (seed, class, era); a v3 job with no resident v3 pack
program answers need + error; v2 lines unchanged (Swift generation, the variant race); a pack program never races.
verify.rs: Epoch::chain_dataset_day(day, class, days_since_genesis, genesis_dataset_log2) and days_since_genesis,
the entry the node builds every day cache through (the ca2-mixer growth rule fills the body).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-05 20:51:24 +00:00
parent fa1f1e8088
commit ffd056a9ea
4 changed files with 120 additions and 25 deletions

View file

@ -417,6 +417,11 @@ pub struct Epoch {
/// Default dataset size: 2^28 words = 1 GiB.
pub const DEFAULT_DATASET_LOG2: u32 = 28;
/// Days a day index lies after the network's genesis day (0 for the genesis day and any day before it).
pub fn days_since_genesis(day_index: u64, genesis_day_index: u64) -> u64 {
day_index.saturating_sub(genesis_day_index)
}
impl Epoch {
pub fn new(seed: &str, day: &str, mode: DatasetMode, dataset_log2: u32) -> Self {
Self { program: generate(seed), dataset: DatasetSource::new(day, mode, dataset_log2) }
@ -467,9 +472,18 @@ impl Epoch {
/// construction (the mixer multiplier) and cache size schedule (ca2-mixer); today both classes build the day of
/// [`Epoch::from_seed_bytes`], and the engine keys its day caches on `(day, class)` so the two never share one.
pub fn chain_dataset(day_bytes: &[u8], class: ProgramClass) -> DatasetSource {
let _ = class;
Self::chain_dataset_day(day_bytes, class, 0, DEFAULT_DATASET_LOG2)
}
/// [`Epoch::chain_dataset`] with the day's position since genesis and the network's genesis dataset size: the
/// entry the node's engine and the miner's export build every day cache through, so the cache growth schedule
/// of spec 01 section 1.13.3 has one place to act. SEAM (ca2-node, 5 October 2026): the body here builds the
/// genesis-size cache for every day; the ca2-mixer branch fills the growth rule (`growth_doublings`) and the
/// class v3 item construction, keeping this signature.
pub fn chain_dataset_day(day_bytes: &[u8], class: ProgramClass, days_since_genesis: u64, genesis_dataset_log2: u32) -> DatasetSource {
let _ = (class, days_since_genesis);
let key = crate::seed::seed_words_from_bytes(day_bytes);
let mut dataset = DatasetSource::from_key(key, DatasetMode::MemoryHard, DEFAULT_DATASET_LOG2);
let mut dataset = DatasetSource::from_key(key, DatasetMode::MemoryHard, genesis_dataset_log2);
dataset.key_bytes = day_bytes.to_vec();
dataset
}

View file

@ -55,6 +55,7 @@
"proving_v0_activation_daa": 18446744073709551615,
"finality_v3_activation_daa": 18446744073709551615,
"program_class_v3_activation_daa": 18446744073709551615,
"pow_genesis_dataset_log2": 28,
"fees_v1_activation_daa": 0,
"fees": {"pgas": {"version": 1, "cycles_per_pgas": 1000, "intrinsic_pgas_per_tx": 300, "modexp_base": 10, "modexp_per_byte_numer": 1, "modexp_per_byte_denom": 10}, "block_proving_gas_limit": 120000, "shard_proving_gas_budget": 30000, "min_execution_base_fee_wei": 100000000000, "min_proving_base_fee_wei": 10000000000000, "initial_execution_base_fee_wei": 100000000000, "initial_proving_base_fee_wei": 10000000000000, "base_fee_change_denominator": 8}
}

View file

@ -2781,13 +2781,32 @@ func blockInitWords(prehash: [UInt8], nonceHi: UInt32) -> [UInt32] {
final class ServeProgram {
let seedHex: String
let program: Program
/// The Swift-generated program (class v2); nil for a program compiled from a pack (class v3, Counter ASIC 2.0),
/// which has no Swift instruction list and so never races variants
let program: Program?
/// Counter ASIC 2.0: the class ("v2" or "v3") and, for a pack program, its era seed hex and loads per hash
let programClass: String
let eraHex: String
let loadsPerHash: Int
private var slot: CompiledHash
private let lock = NSLock()
/// true until a race ran for this program (an inline compile races after the first job on it)
var raceDue = true
var raceLine = ""
init(seedHex: String, program: Program, compiled: CompiledHash) { self.seedHex = seedHex; self.program = program; self.slot = compiled }
init(seedHex: String, program: Program, compiled: CompiledHash) {
self.seedHex = seedHex; self.program = program; self.slot = compiled
self.programClass = "v2"; self.eraHex = ""; self.loadsPerHash = program.loadsPerHash
}
init(seedHex: String, packClass: String, eraHex: String, loadsPerHash: Int, compiled: CompiledHash) {
self.seedHex = seedHex; self.program = nil; self.slot = compiled
self.programClass = packClass; self.eraHex = eraHex; self.loadsPerHash = loadsPerHash; self.raceDue = false
}
/// Whether this program is the one a line naming `cls` (and `era`) wants; empty names accept any (class v2 lines).
func matches(cls: String, era: String) -> Bool {
if cls != "" && cls != programClass { return false }
if era != "" && programClass == "v3" && era.lowercased() != eraHex.lowercased() { return false }
return true
}
var compiled: CompiledHash { lock.lock(); defer { lock.unlock() }; return slot }
func install(_ c: CompiledHash) { lock.lock(); slot = c; lock.unlock() }
}
@ -2873,7 +2892,8 @@ func raceProgram(_ gpu: GPU, _ program: ServeProgram, dataset: MTLBuffer, datase
// Compile (the base is already compiled)
for i in 1..<entries.count {
if nowNs() > deadline { entries[i].note = "not compiled: the race budget ran out"; continue }
do { entries[i].compiled = try compileBound(gpu, msl: generateMSL(program.program, datasetLog2: datasetLog2, source: .stored, bound: true, variant: entries[i].v), variant: entries[i].v) }
guard let swiftProgram = program.program else { return "race \(program.seedHex.prefix(16)) skipped: a pack program (class \(program.programClass)) has no variants to race" }
do { entries[i].compiled = try compileBound(gpu, msl: generateMSL(swiftProgram, datasetLog2: datasetLog2, source: .stored, bound: true, variant: entries[i].v), variant: entries[i].v) }
catch { entries[i].note = "compile: \(error)".prefix(200).description }
}
let compileMs = ms(t0, nowNs())
@ -2926,7 +2946,7 @@ func raceProgram(_ gpu: GPU, _ program: ServeProgram, dataset: MTLBuffer, datase
if win != 0, let k = entries[win].compiled { program.install(k) }
let total = ms(t0, nowNs())
let os = ProcessInfo.processInfo.operatingSystemVersion
var line = "race \(program.seedHex.prefix(16)) device \(device) driver macos-\(os.majorVersion).\(os.minorVersion).\(os.patchVersion) arch metal loads \(program.program.loadsPerHash) wide \(program.program.wideLoadsPerHash) variants \(entries.count)"
var line = "race \(program.seedHex.prefix(16)) device \(device) driver macos-\(os.majorVersion).\(os.minorVersion).\(os.patchVersion) arch metal loads \(program.loadsPerHash) wide \(program.program?.wideLoadsPerHash ?? 0) variants \(entries.count)"
for e in entries { line += e.ok && (e.mhs > 0 || pinnedOnly) ? " \(e.v.name)=\(fmt(e.mhs, 3))/\(e.compiled!.pipeline.maxTotalThreadsPerThreadgroup)t/\(e.v.groupWidth)w" : " \(e.v.name)=-" }
let gain = baseMhs > 0 ? (winMhs / baseMhs - 1) * 100 : 0
line += " winner \(entries[win].v.name) \(fmt(winMhs, 3)) base \(fmt(baseMhs, 3)) gain \(gain >= 0 ? "+" : "")\(fmt(gain, 2))% compile \(fmt(compileMs, 0)) bench \(fmt(total - compileMs, 0)) total \(fmt(total, 0)) ms"
@ -2957,14 +2977,14 @@ final class ServeStore {
/// The pair of the last job (epoch seed hex, day seed hex); never evicted
var current: (String, String)? = nil
func program(_ seedHex: String) -> ServeProgram? { lock.lock(); defer { lock.unlock() }; return programs.first { $0.seedHex == seedHex } }
func program(_ seedHex: String, cls: String = "", era: String = "") -> ServeProgram? { lock.lock(); defer { lock.unlock() }; return programs.first { $0.seedHex == seedHex && $0.matches(cls: cls, era: era) } }
func dataset(_ dayHex: String) -> ServeDataset? { lock.lock(); defer { lock.unlock() }; return datasets.first { $0.dayHex == dayHex } }
func counts() -> (Int, Int) { lock.lock(); defer { lock.unlock() }; return (programs.count, datasets.count) }
/// Adds a program; with more than two resident, the oldest one that is not the current job's goes.
func add(_ p: ServeProgram) {
lock.lock(); defer { lock.unlock() }
if programs.contains(where: { $0.seedHex == p.seedHex }) { return }
if programs.contains(where: { $0.seedHex == p.seedHex && $0.programClass == p.programClass && $0.eraHex == p.eraHex }) { return }
programs.append(p)
while programs.count > 2, let i = programs.firstIndex(where: { $0.seedHex != current?.0 && $0.seedHex != p.seedHex }) { programs.remove(at: i) }
}
@ -3011,6 +3031,51 @@ func serveProgram(_ gpu: GPU, _ store: ServeStore, seedHex: String, seed: [UInt8
return (sp, ms(t0, nowNs()))
}
// Counter ASIC 2.0 (5 October 2026): a class v3 program comes from the pack igneum-miner export-pack / --prepare-packs
// wrote (program_bound.metal, the Rust emitter's text; program.h for the identity), never from the Swift generator.
// The pack is checked the way the one-click workers check it (proto-cuda/nvrtc/packfile.h): IGNEUM_GENERATOR 2 or 3,
// the class line against the generator, the seed bytes against the line's epoch seed, IGNEUM_SEEDW_INIT against the
// words of IGNEUM_PROGRAM_ATTEMPT of that seed, and the class and era against what the line names.
func servePackProgram(_ gpu: GPU, _ store: ServeStore, seedHex: String, seed: [UInt8], dir: String, wantClass: String, wantEra: String) throws -> (ServeProgram, Double) {
if let p = store.program(seedHex, cls: wantClass, era: wantEra) { return (p, 0) }
let t0 = nowNs()
guard let programH = try? String(contentsOfFile: dir + "/program.h", encoding: .utf8) else { throw NSError(domain: "pack", code: 1, userInfo: [NSLocalizedDescriptionKey: "cannot read \(dir)/program.h"]) }
func defineU32(_ name: String) -> UInt32? {
guard let re = try? NSRegularExpression(pattern: "#define \(name) ([0-9a-fA-Fx]+)"), let m = re.firstMatch(in: programH, range: NSRange(programH.startIndex..., in: programH)) else { return nil }
let v = String(programH[Range(m.range(at: 1), in: programH)!]).replacingOccurrences(of: "u", with: "")
return v.hasPrefix("0x") ? UInt32(v.dropFirst(2), radix: 16) : UInt32(v)
}
func defineStr(_ name: String) -> String? {
guard let re = try? NSRegularExpression(pattern: "#define \(name) \"([^\"]*)\""), let m = re.firstMatch(in: programH, range: NSRange(programH.startIndex..., in: programH)) else { return nil }
return String(programH[Range(m.range(at: 1), in: programH)!])
}
func defineWords(_ name: String) -> [UInt32]? {
guard let re = try? NSRegularExpression(pattern: "#define \(name) \\{([^}]*)\\}"), let m = re.firstMatch(in: programH, range: NSRange(programH.startIndex..., in: programH)) else { return nil }
let body = String(programH[Range(m.range(at: 1), in: programH)!])
let words = body.split(separator: ",").compactMap { t -> UInt32? in let v = t.trimmingCharacters(in: .whitespaces).replacingOccurrences(of: "u", with: ""); return v.hasPrefix("0x") ? UInt32(v.dropFirst(2), radix: 16) : UInt32(v) }
return words.count == 8 ? words : nil
}
func refuse(_ why: String) -> NSError { NSError(domain: "pack", code: 2, userInfo: [NSLocalizedDescriptionKey: "pack \(dir): \(why)"]) }
let generator = defineU32("IGNEUM_GENERATOR") ?? 1
guard generator == 2 || generator == 3 else { throw refuse("program pack generator \(generator) is not a generator version this worker runs (2 or 3)") }
let packClass = generator == 3 ? "v3" : "v2"
if let named = defineStr("IGNEUM_PROGRAM_CLASS"), named != packClass { throw refuse("program pack IGNEUM_PROGRAM_CLASS \"\(named)\" does not match IGNEUM_GENERATOR \(generator)") }
let eraHex = defineStr("IGNEUM_ERA_SEED_HEX") ?? ""
if wantClass != "" && wantClass != packClass { throw refuse("program class mismatch: this pack is class \(packClass), the line names class \(wantClass) (export the pack again)") }
if wantEra != "" && packClass == "v3" && wantEra.lowercased() != eraHex.lowercased() { throw refuse("era seed mismatch: this pack was drawn under era \(eraHex.isEmpty ? "(none)" : String(eraHex.prefix(16))), the line names era \(wantEra.prefix(16)) (export the pack again)") }
if let packSeed = defineStr("IGNEUM_SEED_BYTES_HEX"), packSeed.lowercased() != seedHex.lowercased() { throw refuse("the pack is for epoch \(packSeed.prefix(16)), not \(seedHex.prefix(16))") }
let attempt = defineU32("IGNEUM_PROGRAM_ATTEMPT") ?? 0
guard let seedw = defineWords("IGNEUM_SEEDW_INIT") else { throw refuse("program.h has no IGNEUM_SEEDW_INIT with 8 words") }
let want = attemptWords(seed, attempt)
if want != seedw { throw refuse("program pack and its seeds disagree: IGNEUM_SEEDW_INIT is not attempt \(attempt) of the epoch seed \(seedHex.prefix(16))") }
let loads = Int(defineU32("IGNEUM_LOADS_PER_HASH") ?? 128)
guard let msl = try? String(contentsOfFile: dir + "/program_bound.metal", encoding: .utf8) else { throw refuse("cannot read program_bound.metal") }
let c = try compileBound(gpu, msl: msl)
let sp = ServeProgram(seedHex: seedHex, packClass: packClass, eraHex: eraHex, loadsPerHash: loads, compiled: c)
store.add(sp)
return (sp, ms(t0, nowNs()))
}
// Builds the cache and dataset for a day seed (hex) unless resident. Returns (dataset, build ms).
func serveDataset(_ gpu: GPU, _ store: ServeStore, dayHex: String, day: [UInt8], datasetLog2: Int) -> (ServeDataset, Double) {
if let d = store.dataset(dayHex) { return (d, 0) }
@ -3036,19 +3101,19 @@ func runServe(_ opts: Options) -> Never {
var f = line.split(separator: " ").map(String.init)
if f.isEmpty { continue }
if f[0] == "quit" { break }
// Counter ASIC 2.0 (5 October 2026): a job or prepare line of a class v3 epoch ends with `class=v3 era=<hex>`.
// This worker regenerates programs from the seed with the Swift version 2 generator, so it refuses every
// class v3 line until the integration branch adds generator 3 here (the one-click workers build from packs
// and take v3 packs).
var wantClass = ""
// Counter ASIC 2.0 (5 October 2026): a job or prepare line of a class v3 epoch ends with `class=v3 era=<hex>`
// (a class v2 line is the line of before). A class v2 program is generated here from the seed (the Swift
// version 2 generator); a class v3 program is compiled from the pack the prepare line names (servePackProgram),
// so a v3 job on seeds with no prepared v3 pack asks for one (`need`) instead of mining the wrong program.
var wantClass = "", wantEra = ""
while let last = f.last, last.hasPrefix("class=") || last.hasPrefix("era=") {
if last.hasPrefix("class=") { wantClass = String(last.dropFirst(6)) }
if last.hasPrefix("class=") { wantClass = String(last.dropFirst(6)) } else { wantEra = String(last.dropFirst(4)) }
f.removeLast()
}
if wantClass != "" && wantClass != "v2" {
if wantClass != "" && wantClass != "v2" && wantClass != "v3" {
let id = f.count > 1 ? f[1] : "0"
if f[0] == "prepare" { emit("prepare-failed \(id) \(f.count > 2 ? f[2] : "0") program class \(wantClass) is not implemented by this worker (Swift generator version 2 only)") }
else { emit("error \(id) program class \(wantClass) is not implemented by this worker (Swift generator version 2 only); use the CUDA or OpenCL worker with a class \(wantClass) pack") }
if f[0] == "prepare" { emit("prepare-failed \(id) \(f.count > 2 ? f[2] : "0") program class \(wantClass) is not one this worker runs (v2 or v3)") }
else { emit("error \(id) program class \(wantClass) is not one this worker runs (v2 or v3)") }
continue
}
if f[0] == "prepare" {
@ -3058,12 +3123,16 @@ func runServe(_ opts: Options) -> Never {
emit("prepare-failed \(f[1]) \(f[2]) bad field (epoch_seed 64 hex, day_seed hex)"); continue
}
let (epochHex, dayHex) = (f[1], f[2])
let have = (store.program(epochHex) != nil, store.dataset(dayHex) != nil)
let have = (store.program(epochHex, cls: wantClass, era: wantEra) != nil, store.dataset(dayHex) != nil)
if have.0 && have.1 { emit("prepared \(epochHex) \(dayHex) 0 program 0 dataset 0 (already resident)"); continue }
let packDir = f.count > 3 ? f[3...].joined(separator: " ") : ""
if wantClass == "v3" && packDir.isEmpty { emit("prepare-failed \(epochHex) \(dayHex) a class v3 program is compiled from a pack: send prepare with a pack directory (igneum-miner --prepare-packs <dir>)"); continue }
prepareQueue.async {
let t0 = nowNs()
do {
let (sp, progMs) = try serveProgram(gpu, store, seedHex: epochHex, seed: epochSeed, datasetLog2: datasetLog2)
let (sp, progMs) = wantClass == "v3"
? try servePackProgram(gpu, store, seedHex: epochHex, seed: epochSeed, dir: packDir, wantClass: wantClass, wantEra: wantEra)
: try serveProgram(gpu, store, seedHex: epochHex, seed: epochSeed, datasetLog2: datasetLog2)
let (sd, dsMs) = serveDataset(gpu, store, dayHex: dayHex, day: daySeed, datasetLog2: datasetLog2)
// The race: the prepared program against its own dataset, exclusive windows between jobs
var raceMs = 0.0
@ -3073,8 +3142,8 @@ func runServe(_ opts: Options) -> Never {
raceMs = ms(r0, nowNs())
}
let (np, nd) = store.counts()
emit("prepared \(epochHex) \(dayHex) \(fmt(ms(t0, nowNs()), 1)) program \(fmt(progMs, 1)) dataset \(fmt(dsMs, 1)) race \(fmt(raceMs, 1)) variant \(sp.compiled.variant) loads/hash \(sp.program.loadsPerHash) cache-fill \(fmt(sd.ctx.cacheFillGPUms, 1)) resident \(np) programs \(nd) datasets")
} catch { emit("prepare-failed \(epochHex) \(dayHex) Metal compile failed: \(error)") }
emit("prepared \(epochHex) \(dayHex) \(fmt(ms(t0, nowNs()), 1)) program \(fmt(progMs, 1)) dataset \(fmt(dsMs, 1)) race \(fmt(raceMs, 1)) variant \(sp.compiled.variant) class \(sp.programClass) loads/hash \(sp.loadsPerHash) cache-fill \(fmt(sd.ctx.cacheFillGPUms, 1)) resident \(np) programs \(nd) datasets")
} catch { emit("prepare-failed \(epochHex) \(dayHex) \(wantClass == "v3" ? "" : "Metal compile failed: ")\(error.localizedDescription)") }
}
continue
}
@ -3096,9 +3165,20 @@ func runServe(_ opts: Options) -> Never {
let program: ServeProgram
let dataset: ServeDataset
do {
if store.program(pair.0) == nil || store.dataset(pair.1) == nil { prepareQueue.sync {} }
let (sp, progMs) = try serveProgram(gpu, store, seedHex: pair.0, seed: epochSeed, datasetLog2: datasetLog2)
if progMs > 0 { emit("info program epoch \(pair.0.prefix(16)) loads/hash \(sp.program.loadsPerHash) compiled inline in \(fmt(progMs, 1)) ms (not prepared)") }
if store.program(pair.0, cls: wantClass, era: wantEra) == nil || store.dataset(pair.1) == nil { prepareQueue.sync {} }
let sp: ServeProgram
if wantClass == "v3" {
guard let resident = store.program(pair.0, cls: wantClass, era: wantEra) else {
emit("need \(pair.0) \(pair.1)")
emit("error \(jobId) pack (metal): program class mismatch: no class v3 program for epoch \(pair.0.prefix(16)) is resident (this worker compiles v3 from a pack); send prepare with a pack directory")
continue
}
sp = resident
} else {
let (p, progMs) = try serveProgram(gpu, store, seedHex: pair.0, seed: epochSeed, datasetLog2: datasetLog2)
if progMs > 0 { emit("info program epoch \(pair.0.prefix(16)) loads/hash \(p.loadsPerHash) compiled inline in \(fmt(progMs, 1)) ms (not prepared)") }
sp = p
}
let (sd, dsMs) = serveDataset(gpu, store, dayHex: pair.1, day: daySeed, datasetLog2: datasetLog2)
if dsMs > 0 { emit("info dataset day \(pair.1) built inline in \(fmt(dsMs, 1)) ms (cache fill \(fmt(sd.ctx.cacheFillGPUms, 1)) ms, build \(fmt(sd.ctx.lastBuildGPUms, 1)) ms GPU; not prepared)") }
program = sp; dataset = sd

View file

@ -1 +1 @@
{"timestamp_deviation_tolerance": 132, "past_median_time_window_size": 27, "difficulty_window_size": 661, "min_difficulty_window_size": 150, "difficulty_rule": "igneum-dual", "coinbase_payload_script_public_key_max_len": 150, "max_coinbase_payload_len": 16384, "max_tx_inputs": 1000, "max_tx_outputs": 1000, "max_signature_script_len": 250000, "max_script_public_key_len": 10000, "mass_per_tx_byte": 1, "mass_per_script_pub_key_byte": 10, "mass_per_sig_op": 1000, "block_mass_limits": {"compute": 500000, "storage": 500000, "transient": 1000000}, "block_lane_limits": {"lanes_per_block": 50, "gas_per_lane": 1000000000}, "storage_mass_parameter": 1000000000000, "deflationary_phase_daa_score": 0, "pre_deflationary_phase_base_subsidy": 50000000000, "skip_proof_of_work": false, "max_block_level": 250, "pruning_proof_m": 1000, "blockrate": {"target_time_per_block": 1000, "ghostdag_k": 18, "past_median_time_sample_rate": 10, "difficulty_sample_rate": 4, "max_block_parents": 10, "mergeset_size_limit": 180, "merge_depth": 60, "finality_depth": 720, "pruning_depth": 13838, "coinbase_maturity": 2}, "pre_crescendo_target_time_per_block": 1000, "crescendo_activation": 0, "genesis_bits": 487587840, "finality": {"checkpoint_interval": 30, "checkpoint_depth": 20, "weight_window": 120, "dust": 5, "presence_window": 1, "aggregators": 8, "equivocation_ban": 120, "min_daa": 120, "aggregator_fallback": 1}, "pow_epoch_blocks": 60, "pow_epoch_lead": 10, "pow_day_ms": 1440000, "finality_v3_activation_daa": 0, "program_class_v3_activation_daa": 18446744073709551615}
{"timestamp_deviation_tolerance": 132, "past_median_time_window_size": 27, "difficulty_window_size": 661, "min_difficulty_window_size": 150, "difficulty_rule": "igneum-dual", "coinbase_payload_script_public_key_max_len": 150, "max_coinbase_payload_len": 16384, "max_tx_inputs": 1000, "max_tx_outputs": 1000, "max_signature_script_len": 250000, "max_script_public_key_len": 10000, "mass_per_tx_byte": 1, "mass_per_script_pub_key_byte": 10, "mass_per_sig_op": 1000, "block_mass_limits": {"compute": 500000, "storage": 500000, "transient": 1000000}, "block_lane_limits": {"lanes_per_block": 50, "gas_per_lane": 1000000000}, "storage_mass_parameter": 1000000000000, "deflationary_phase_daa_score": 0, "pre_deflationary_phase_base_subsidy": 50000000000, "skip_proof_of_work": false, "max_block_level": 250, "pruning_proof_m": 1000, "blockrate": {"target_time_per_block": 1000, "ghostdag_k": 18, "past_median_time_sample_rate": 10, "difficulty_sample_rate": 4, "max_block_parents": 10, "mergeset_size_limit": 180, "merge_depth": 60, "finality_depth": 720, "pruning_depth": 13838, "coinbase_maturity": 2}, "pre_crescendo_target_time_per_block": 1000, "crescendo_activation": 0, "genesis_bits": 487587840, "finality": {"checkpoint_interval": 30, "checkpoint_depth": 20, "weight_window": 120, "dust": 5, "presence_window": 1, "aggregators": 8, "equivocation_ban": 120, "min_daa": 120, "aggregator_fallback": 1}, "pow_epoch_blocks": 60, "pow_epoch_lead": 10, "pow_day_ms": 1440000, "finality_v3_activation_daa": 0, "program_class_v3_activation_daa": 18446744073709551615, "pow_genesis_dataset_log2": 28}