7.6 KiB
Project History
Origin
go-blockchain implements the Lethean blockchain protocol in pure Go, following
ADR-001 (Go Shell + C++ Crypto Library). The chain lineage is CryptoNote (2014)
to IntenseCoin (2017) to Lethean to a Zano rebase. All consensus parameters are
derived from the canonical C++ source files currency_config.h.in and
default.cmake.
The package was created as part of the broader effort to rewrite the Lethean node tooling in Go, keeping protocol logic in Go while deferring only the mathematically complex cryptographic primitives (ring signatures, bulletproofs, Zarcanum proofs) to a cleaned C++ library via CGo in later phases.
Phase 0 -- Scaffold
Commit: 4c0b7f2 -- feat: Phase 0 scaffold -- config, types, wire, difficulty
Phase 0 established the foundational four packages with complete test suites and full coverage of the consensus-critical configuration surface.
Packages implemented
-
config/ -- All chain constants from
currency_config.h.inanddefault.cmake: tokenomics (Coin, BlockReward, fees, premine), address prefixes (standard, integrated, auditable, auditable integrated), network ports (mainnet 36940-36942, testnet 46940-46942), difficulty parameters (window 720, lag 15, cut 60, targets 120s), block and transaction limits, version constants, PoS parameters, P2P constants, network identity, currency identity, and alias rules.ChainConfigstruct with pre-populatedMainnetandTestnetglobals. Hardfork schedule (HF0-HF6) withVersionAtHeight()andIsHardForkActive()lookup functions. -
types/ -- Fixed-size cryptographic types:
Hash(32 bytes),PublicKey(32 bytes),SecretKey(32 bytes),KeyImage(32 bytes),Signature(64 bytes). Hex encode/decode forHashandPublicKey. CryptoNote base58 address encoding with Keccak-256 checksums.Addressstruct withEncode()/DecodeAddress()round-trip.BlockHeader,Block,Transactionstructs. Input types (TxInputGenesis,TxInputToKey) and output types (TxOutputBare,TxOutputZarcanum) with wire type tags.TxInputandTxOutputinterfaces. -
wire/ -- CryptoNote varint encoding (7-bit LEB128 with MSB continuation).
EncodeVarint()andDecodeVarint()with sentinel errors for overflow and empty input. Maximum 10 bytes per uint64. -
difficulty/ -- LWMA difficulty adjustment algorithm.
NextDifficulty()examines a window of timestamps and cumulative difficulties to compute the next target. Handles insufficient data (returnsStarterDifficulty), zero time spans, and negative difficulty deltas.
Tests added
75 test cases across 5 test files, all passing with the race detector:
-
config/config_test.go-- 7 test functions validating every constant group against C++ source values: tokenomics, address prefixes, ports (mainnet and testnet), difficulty parameters, network identity,ChainConfigstruct fields, transaction limits, and transaction version constants. -
config/hardfork_test.go-- 7 test functions coveringVersionAtHeight()on both mainnet and testnet fork schedules,IsHardForkActive()for boundary conditions, unknown version queries, empty fork lists, single-element fork lists, and full fork schedule validation for both networks. -
types/address_test.go-- 8 test functions covering encode/decode round-trips for all four address types, deterministic encoding, auditable flag detection, integrated prefix detection, invalid input rejection (empty, invalid base58 characters, too short), checksum corruption detection, base58 round-trip, and base58 edge cases (empty encode/decode). -
difficulty/difficulty_test.go-- 7 test functions covering stable difficulty with constant intervals, empty input, single entry, fast blocks (difficulty increases), slow blocks (difficulty decreases), zero time span handling, and algorithm constants. -
wire/varint_test.go-- 5 test functions covering encoding known values, decoding known values, round-trip across all bit boundaries (0 throughMaxUint64), empty input errors, and overflow detection.
Coverage
| Package | Coverage |
|---|---|
| config | 100.0% |
| difficulty | 81.0% |
| types | 73.4% |
| wire | 95.2% |
go test -race ./... passed clean. go vet ./... produced no warnings.
Phase 1 -- Wire Serialisation (Planned)
Extend wire/ with full block and transaction binary serialisation matching the
C++ binary_archive format. Add Serialise() and Deserialise() methods to
Block, Transaction, and all input/output types. Validate against real
mainnet block blobs.
Phase 2 -- Crypto Bridge (Planned)
Create crypto/ package with CGo bridge to the cleaned C++ libcryptonote
library. Implement key derivation (generate_key_derivation,
derive_public_key), one-time address generation, and key image computation.
Follow the same CGo pattern used by the MLX backend in go-ai.
Phase 3 -- P2P Levin Protocol (Planned)
Implement the Levin binary protocol in p2p/ for peer-to-peer communication.
Handshake, ping, timed sync, and block/transaction relay. Integrate with
go-p2p for connection management.
Phase 4 -- RPC Layer (Planned)
Implement rpc/ with daemon JSON-RPC (get_block, get_transaction, submit_block)
and wallet JSON-RPC (transfer, get_balance, get_address). Provide both client
and server implementations.
Phase 5 -- Chain Storage and Validation (Planned)
Implement chain/ with blockchain storage (using go-store for persistence),
block validation, transaction verification, and mempool management. UTXO set
tracking with output index.
Phase 6 -- Wallet Core (Planned)
Implement wallet/ with key management, output scanning, transaction
construction, and balance calculation. Deterministic key derivation from seed
phrases. Support for all address types.
Phase 7 -- Consensus Rules (Planned)
Implement consensus/ with hardfork-aware block reward calculation, fee
policy enforcement, and full block/transaction validation rules per hardfork
version.
Phase 8 -- Mining (Planned)
PoW mining support with stratum protocol client. PoS staking with kernel hash computation and coinstake transaction construction.
Known Limitations
No wire serialisation. Block and transaction types are defined as Go structs but cannot yet be serialised to or deserialised from the CryptoNote binary format. This means the types cannot be used to parse real chain data until Phase 1 is complete.
No cryptographic operations. Key derivation, ring signatures, bulletproofs, and all other cryptographic primitives are deferred to Phase 2. Address encoding/decoding works but key generation and output scanning are not possible.
Base58 uses math/big. The CryptoNote base58 implementation converts each
8-byte block via big.Int arithmetic. This is correct but not optimised for
high-throughput scenarios. A future phase may replace this with a lookup-table
approach if profiling identifies it as a bottleneck.
Difficulty coverage at 81%. The window-capping branch in NextDifficulty()
that limits the window to BlocksCount (735) entries is not fully exercised by
the current test suite. Adding test vectors with 1,000+ block entries would
cover this path.
Types coverage at 73.4%. Unexported base58 helper functions have branches that are exercised indirectly through the public API but are not fully reached by the current test vectors. Additional edge-case address strings would improve coverage.
Future forks are placeholders. HF3 through HF6 are defined with activation height 999,999,999 on mainnet. These heights will be updated when each fork is scheduled for activation on the live network.