New actions from specs:
- blockchain.escrow.{create,fund,release,refund,status} — trustless
service payments per RFC.escrow.md. In-memory state for now,
go-store persistence in production.
- blockchain.chain.difficulty — returns PoW/PoS difficulty
- blockchain.chain.transaction — lookup tx by hash
Total Core Actions: 55 (was 43).
Co-Authored-By: Charon <charon@lethean.io>
- Accept both id (hash) and height parameters
- Return all 22 fields the explorer block page expects
- Include transactions_details array with tx hashes
- Block type detection: genesis(0), PoW(1), PoS(2)
- Full explorer-compatible response format
Co-Authored-By: Charon <charon@lethean.io>
- getblockheaderbyheight: add depth, orphan_status, reward
- getlastblockheader: add all 11 C++ daemon fields
- getinfo: add performance_data, tx_pool_performance_data, outs_stat, mi stubs
The Go daemon now returns the exact field set the explorer frontend parses.
Co-Authored-By: Charon <charon@lethean.io>
The Go daemon now returns all fields the explorer expects:
- pow_difficulty, pos_difficulty, total_coins, block_reward
- default_fee, minimum_fee, last_block_hash/timestamp
- tx_count, alt_blocks_count, connection counts
- current_blocks_median, max_allowed_block_size
- network hashrate, synchronization state
Total getinfo response now has 40+ keys matching C++ daemon format.
Co-Authored-By: Charon <charon@lethean.io>
The Go daemon's get_blocks_details now returns 19 fields per block,
matching the C++ daemon's format that the explorer expects:
- id, type (genesis/PoW/PoS), actual_timestamp
- cumulative_diff_adjusted/precise, base_reward
- transactions_details with tx hashes
- already_generated_coins, is_orphan, miner_text_info
- block_cumulative_size, total_fee, total_txs_size
This makes the Go daemon a drop-in replacement for the explorer backend.
Co-Authored-By: Charon <charon@lethean.io>
blockchain.estimate.block_time — average from genesis to tip
blockchain.estimate.supply_at_height — premine + height*reward
blockchain.estimate.height_at_time — timestamp → estimated height
42 total Core actions. Pure calculations, no banned imports.
Co-Authored-By: Charon <charon@lethean.io>
blockchain.tx.relay — broadcast raw transaction hex via C++ daemon
blockchain.tx.pool — query tx pool size
hexDecode: pure Go hex decoder (no encoding/hex import needed).
38 total Core actions.
Co-Authored-By: Charon <charon@lethean.io>
BlockchainService now has an EventBus that emits:
- EventBlockNew on every synced block (with hash)
- EventAlias when a block contains an alias registration
Chain's BlockCallback → EventBus.Emit → subscribers.
Ready for core/stream SSEBroker integration.
Co-Authored-By: Charon <charon@lethean.io>
Chain.SetBlockCallback(func(height, hash, aliasName)) enables
event-driven architecture — the EventBus subscribes to block
storage and emits events without coupling chain to events.
Callback fires in processBlockBlobs after PutBlock succeeds.
Includes alias name if the block contains an alias registration.
Co-Authored-By: Charon <charon@lethean.io>
serve command now auto-detects HF activations:
- Logs HF activation with height
- On HF5: prints ITNS deployment command
New action: blockchain.hardfork.remaining — blocks until next HF.
Co-Authored-By: Charon <charon@lethean.io>
NewHardforkMonitor(chain, forks) with:
- OnActivation callback fires when new HF height reached
- RemainingBlocks() returns countdown to next HF
- Start(ctx) runs background monitor with 30s poll
- Context cancellation for clean shutdown
Tests: creation, remaining blocks, cancellation.
When HF5 activates, the Go daemon detects it automatically.
Co-Authored-By: Charon <charon@lethean.io>
blockchain.dns.resolve — name → A + TXT records via HSD
blockchain.dns.names — all aliases → resolved names with addresses
blockchain.dns.discover — chain aliases → HNS name list
36 total Core actions. DNS actions use chain aliases for discovery
and HSD client for record resolution — the full LNS pipeline
as Core actions.
Co-Authored-By: Charon <charon@lethean.io>
blockchain.hsd.info — sidechain chain/height/tree_root
blockchain.hsd.resolve — name → DNS records from sidechain
blockchain.hsd.height — sidechain block height
33 total Core actions. Ready for go-lns to call these
via c.Run("blockchain.hsd.resolve", opts).
Co-Authored-By: Charon <charon@lethean.io>
blockchain.crypto.hash — Keccak-256 via CGo
blockchain.crypto.generate_keys — Ed25519 keypair via CGo
blockchain.crypto.check_key — validate public key
blockchain.crypto.validate_address — check iTHN address format
23 total Core actions. All pure core.Options/Result.
Co-Authored-By: Charon <charon@lethean.io>
AX RFC-008 bans the "strings" stdlib import in consumer code.
Replaced strings.SplitN calls with core.SplitN and removed the import.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
102 endpoints across 3 categories (chain RPC, wallet proxy, REST).
Documents the banned import debt (encoding/json, net/http) and
the migration plan to core/api.
server.go is 2339 lines with 84 handlers — split plan documented
but deferred to avoid conflicts with parallel agent work.
Co-Authored-By: Charon <charon@lethean.io>
AX compliance: config/file.go now uses core.Env() instead of os.Getenv().
os still imported for ReadFile (no core equivalent without c.Fs()).
Honest AX debt remaining:
- daemon/server.go: encoding/json + net/http (needs core/api migration)
- daemon/wallet_rpc.go: encoding/json + net/http (same)
- cmd_wallet.go: encoding/json + net/http (same)
- chain/alias.go: strings (pure lib, acceptable per RFC-008 §8)
- chain/blockdata.go: os (pure lib, no Core instance)
The daemon is the biggest AX debt — 2300 lines of raw net/http
that should use core/api. Tracked for core/api integration.
Co-Authored-By: Charon <charon@lethean.io>
All 27 json.Unmarshal(req.Params, ¶ms) calls replaced with
parseParams() which handles nil and logs errors. Prevents silent
zero-value params on malformed input.
Co-Authored-By: Charon <charon@lethean.io>
New constants.go: AtomicUnit, StandardPrefix, IntegratedPrefix,
AuditablePrefix, HF5Height, HF4Height, DefaultFee, PremineAmount,
TestnetDaemonRPC, TestnetWalletRPC, etc.
Replaced hardcoded values in cmd_wallet.go, cmd_deploy_itns.go,
service.go. Audit found 33 magic numbers — this commit addresses
the command/service files. daemon/server.go still has ~20 to fix.
Co-Authored-By: Charon <charon@lethean.io>
ChainScanner reads from go-store instead of RPC — orders of magnitude
faster than the RPC scanner. Uses BlockGetter callback for decoupling.
ScanRange(start, end) scans a block range for owned outputs.
Foundation for native Go wallet balance computation.
Co-Authored-By: Charon <charon@lethean.io>
6 integration tests against live Go daemon:
- getinfo matches C++ daemon (alias count, height within 10)
- aliases match C++ (same names)
- block 11000 hash identical between Go and C++
- hardfork status (HF0-HF4 all active)
- chain stats (height > 11000, 14 aliases)
- REST /health returns ok
Co-Authored-By: Charon <charon@lethean.io>
get_total_coins had 3 extra handlers (sed debris): SendRawTransaction,
GetVersion, GetEstHeightFromDate all firing on same case.
get_votes had extra GetConnections handler.
New: TestServer_AllMethods_Good tests ALL 48 RPC methods in one pass.
Result: 48/48 methods working, 0 broken.
Total sed-corruption fixes this session: 15 broken routes found and
repaired through progressive testing. Without the coverage test,
these would have shipped as "100 working endpoints."
Co-Authored-By: Charon <charon@lethean.io>
Self-audit found:
- 17 empty switch cases (sed mutation damage) — 13 fixed
- safeTopBlock recursive call → fixed to call chain.TopBlock
- safeGenesis returning nil → returns zero Block
- Division by zero on empty chain → height guards
- 22 daemon tests passing (up from 8)
The sed-based method registration corrupted the switch statement
over multiple mutations. This is WHY tests matter — without the
20 new tests, these 13 broken routes would have shipped as "done".
Co-Authored-By: Charon <charon@lethean.io>
Self-audit found TOCTOU between Height() and TopBlock() — sync
could advance between calls giving inconsistent getinfo data.
Snapshot() reads both in sequence from the same chain state.
Also: added chain.go Snapshot method.
Co-Authored-By: Charon <charon@lethean.io>