From 37cc3d73425f43e9de72a78da00cccb8665130ca Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 20 Feb 2026 15:24:38 +0000 Subject: [PATCH] docs: graduate Phase 0 into production documentation Co-Authored-By: Charon --- CLAUDE.md | 53 +++------ README.md | 55 +++++++++ docs/architecture.md | 257 +++++++++++++++++++++++++++++++++++++++++++ docs/development.md | 202 ++++++++++++++++++++++++++++++++++ docs/history.md | 176 +++++++++++++++++++++++++++++ 5 files changed, 707 insertions(+), 36 deletions(-) create mode 100644 README.md create mode 100644 docs/architecture.md create mode 100644 docs/development.md create mode 100644 docs/history.md diff --git a/CLAUDE.md b/CLAUDE.md index aca249a..48aa60e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,46 +1,27 @@ -# go-blockchain +# CLAUDE.md -Go implementation of the Lethean blockchain protocol. Pure Go package providing -chain configuration, core data types, wire serialisation, and difficulty -calculation for the Lethean CryptoNote/Zano-fork chain. +Pure Go implementation of the Lethean blockchain protocol (config, types, wire, difficulty). -This package follows ADR-001: Go Shell + C++ Crypto Library. Protocol logic -lives in Go; only the mathematically complex cryptographic primitives (ring -signatures, bulletproofs, Zarcanum proofs) are delegated to a cleaned C++ -library via CGo in later phases. +Module: `forge.lthn.ai/core/go-blockchain` -Lineage: CryptoNote -> IntenseCoin (2017) -> Lethean -> Zano rebase. - -Licence: EUPL-1.2 - -## Build and Test +## Commands ```bash -go build ./... -go test -v -race ./... -go vet ./... +go test ./... # run all tests +go test -race ./... # race detector (required before commit) +go test -v -run Name ./... # single test +go vet ./... # vet check ``` -## Package Layout +## Standards -``` -config/ Chain parameters (mainnet/testnet), hardfork schedule -types/ Core data types: Hash, PublicKey, Address, Block, Transaction -wire/ Binary serialisation (CryptoNote varint encoding) -difficulty/ PoW + PoS difficulty adjustment (LWMA variant) -crypto/ (future) CGo bridge to libcryptonote -p2p/ (future) Levin TCP protocol -rpc/ (future) Daemon and wallet JSON-RPC -chain/ (future) Blockchain storage, validation, mempool -wallet/ (future) Key management, output scanning, tx construction -consensus/ (future) Hardfork rules, block reward, fee policy -``` +- UK English +- `go test -race ./...` and `go vet ./...` must pass before commit +- Conventional commits: `type(scope): description` +- Co-Author: `Co-Authored-By: Charon ` -## Coding Standards +## Docs -- **Language:** UK English in all comments and documentation (colour, organisation, centre) -- **Commits:** Conventional commits (`feat:`, `fix:`, `refactor:`, `test:`, `docs:`) -- **Co-Author:** All commits include `Co-Authored-By: Charon ` -- **Test naming:** `_Good` (happy path), `_Bad` (expected errors), `_Ugly` (panics/edge cases) -- **Imports:** stdlib, then `golang.org/x`, then `forge.lthn.ai`, each separated by a blank line -- **No emojis** in code or comments +- `docs/architecture.md` -- package structure, key types, design decisions, ADR-001 +- `docs/development.md` -- prerequisites, test patterns, coding standards +- `docs/history.md` -- completed phases with commit hashes, known limitations diff --git a/README.md b/README.md new file mode 100644 index 0000000..035cc75 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# go-blockchain + +Pure Go implementation of the Lethean blockchain protocol. Provides chain configuration, core cryptographic data types, CryptoNote wire serialisation, and LWMA difficulty adjustment for the Lethean CryptoNote/Zano-fork chain. Follows ADR-001: protocol logic in Go, cryptographic primitives deferred to a C++ bridge in later phases. Lineage: CryptoNote to IntenseCoin (2017) to Lethean to Zano rebase. + +**Module**: `forge.lthn.ai/core/go-blockchain` +**Licence**: EUPL-1.2 +**Language**: Go 1.25 + +## Quick Start + +```go +import ( + "forge.lthn.ai/core/go-blockchain/config" + "forge.lthn.ai/core/go-blockchain/types" + "forge.lthn.ai/core/go-blockchain/wire" + "forge.lthn.ai/core/go-blockchain/difficulty" +) + +// Query the active hardfork version at a given block height +version := config.VersionAtHeight(config.MainnetForks, 10081) // returns HF2 + +// Check if a specific hardfork is active +active := config.IsHardForkActive(config.MainnetForks, config.HF4Zarcanum, 50000) // false + +// Encode and decode a Lethean address +addr := &types.Address{SpendPublicKey: spendKey, ViewPublicKey: viewKey} +encoded := addr.Encode(config.AddressPrefix) +decoded, prefix, err := types.DecodeAddress(encoded) + +// Varint encoding for the wire protocol +buf := wire.EncodeVarint(0x1eaf7) +val, n, err := wire.DecodeVarint(buf) + +// Calculate next block difficulty +nextDiff := difficulty.NextDifficulty(timestamps, cumulativeDiffs, 120) +``` + +## Documentation + +- [Architecture](docs/architecture.md) -- package structure, key types, design decisions, ADR-001 +- [Development Guide](docs/development.md) -- prerequisites, test patterns, coding standards +- [Project History](docs/history.md) -- completed phases with commit hashes, known limitations + +## Build & Test + +```bash +go test ./... +go test -race ./... +go vet ./... +go build ./... +``` + +## Licence + +European Union Public Licence 1.2 -- see [LICENCE](LICENCE) for details. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..5b19203 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,257 @@ +# Architecture + +go-blockchain is a pure Go implementation of the Lethean blockchain protocol. It +provides chain configuration, core cryptographic data types, consensus-critical +wire serialisation, and difficulty adjustment for the Lethean CryptoNote/Zano-fork +chain. + +Module path: `forge.lthn.ai/core/go-blockchain` + +--- + +## Package Structure + +``` +config/ Chain parameters (mainnet/testnet), hardfork schedule +types/ Core data types: Hash, PublicKey, Address, Block, Transaction +wire/ Binary serialisation (CryptoNote varint encoding) +difficulty/ PoW + PoS difficulty adjustment (LWMA variant) +``` + +### config/ + +Defines every consensus-critical constant for the Lethean chain, derived directly +from the canonical C++ source files `currency_config.h.in` and `default.cmake`. +Constants cover tokenomics, address prefixes, network ports, difficulty parameters, +block and transaction limits, version numbers, PoS parameters, P2P constants, +network identity, currency identity, and alias rules. + +The `ChainConfig` struct aggregates all parameters into a single value. +Pre-populated `Mainnet` and `Testnet` variables are provided as package-level +globals. The hardfork schedule is defined in `hardfork.go` with lookup functions +for querying active versions at any block height. + +### types/ + +Fixed-size byte array types matching the CryptoNote specification: + +- `Hash` (32 bytes) -- Keccak-256 hash values +- `PublicKey` (32 bytes) -- Ed25519 public keys +- `SecretKey` (32 bytes) -- Ed25519 secret keys +- `KeyImage` (32 bytes) -- double-spend detection images +- `Signature` (64 bytes) -- cryptographic signatures + +Also contains the full address encoding/decoding implementation (CryptoNote +base58 with Keccak-256 checksums), block header and block structures, and all +transaction types across versions 0 through 3. + +### wire/ + +Consensus-critical binary serialisation primitives. Currently implements +CryptoNote varint encoding (7-bit LEB128 with MSB continuation). All encoding +must be bit-identical to the C++ reference implementation. + +### difficulty/ + +LWMA (Linear Weighted Moving Average) difficulty adjustment algorithm for both +PoW and PoS blocks. Examines a window of recent block timestamps and cumulative +difficulties to calculate the next target difficulty. + +--- + +## Key Types + +### ChainConfig + +```go +type ChainConfig struct { + Name string + Abbreviation string + IsTestnet bool + CurrencyFormationVersion uint64 + Coin uint64 + DisplayDecimalPoint uint8 + BlockReward uint64 + DefaultFee uint64 + MinimumFee uint64 + Premine uint64 + AddressPrefix uint64 + IntegratedAddressPrefix uint64 + AuditableAddressPrefix uint64 + AuditableIntegratedAddressPrefix uint64 + P2PPort uint16 + RPCPort uint16 + StratumPort uint16 + DifficultyPowTarget uint64 + DifficultyPosTarget uint64 + DifficultyWindow uint64 + DifficultyLag uint64 + DifficultyCut uint64 + DifficultyPowStarter uint64 + DifficultyPosStarter uint64 + MaxBlockNumber uint64 + TxMaxAllowedInputs uint64 + TxMaxAllowedOutputs uint64 + DefaultDecoySetSize uint64 + HF4MandatoryDecoySetSize uint64 + MinedMoneyUnlockWindow uint64 + P2PMaintainersPubKey string +} +``` + +Pre-populated globals `Mainnet` and `Testnet` contain the complete parameter +sets for each network. Mainnet uses ports 36940-36942; testnet uses 46940-46942. + +### HardFork + +```go +type HardFork struct { + Version uint8 + Height uint64 + Mandatory bool + Description string +} +``` + +Seven hardfork versions are defined (HF0 through HF6). On mainnet, HF0 is +active from genesis, HF1 and HF2 activate after block 10,080, and HF3 through +HF6 are scheduled at height 999,999,999 (effectively future). On testnet, most +forks activate early for testing. + +### Address + +```go +type Address struct { + SpendPublicKey PublicKey + ViewPublicKey PublicKey + Flags uint8 +} +``` + +Four address types are supported via distinct prefixes: + +| Type | Prefix | Leading chars | +|------|--------|---------------| +| Standard | `0x1eaf7` | `iTHN` | +| Integrated | `0xdeaf7` | `iTHn` | +| Auditable | `0x3ceff7` | `iThN` | +| Auditable integrated | `0x8b077` | `iThn` | + +### Block and Transaction + +```go +type BlockHeader struct { + MajorVersion uint8 + MinorVersion uint8 + Timestamp uint64 + PrevID Hash + Nonce uint64 +} + +type Block struct { + BlockHeader + MinerTx Transaction + TxHashes []Hash +} + +type Transaction struct { + Version uint8 + UnlockTime uint64 + Vin []TxInput + Vout []TxOutput + Extra []byte +} +``` + +Transaction versions progress through the hardfork schedule: + +| Version | Era | Description | +|---------|-----|-------------| +| 0 | Genesis | Coinbase transactions | +| 1 | Pre-HF4 | Standard transparent transactions | +| 2 | Post-HF4 | Zarcanum confidential transactions (CLSAG) | +| 3 | Post-HF5 | Confidential assets with surjection proofs | + +Input types: `TxInputGenesis` (coinbase, tag `0xFF`) and `TxInputToKey` (standard +spend with ring signature, tag `0x02`). + +Output types: `TxOutputBare` (transparent, tag `0x02`) and `TxOutputZarcanum` +(confidential with Pedersen commitments, tag `0x03`). + +--- + +## Design Decisions + +### Why CryptoNote Base58 + +CryptoNote uses its own base58 variant (not Bitcoin's base58check). The alphabet +omits `0`, `O`, `I`, and `l` to avoid visual ambiguity. Data is split into 8-byte +blocks, each encoded independently into 11 base58 characters. The final partial +block produces fewer characters according to a fixed mapping table +(`base58BlockSizes`). This block-based approach differs from Bitcoin's +whole-number division and produces different output for the same input bytes. + +The implementation uses `math/big` for block conversion rather than a lookup +table. This is correct for all uint64 ranges but is not optimised for +high-throughput address generation. Performance optimisation is deferred to a +later phase if profiling identifies it as a bottleneck. + +### Why Keccak-256 (Not SHA3-256) + +CryptoNote predates the NIST SHA-3 standard. It uses the original Keccak-256 +submission (`sha3.NewLegacyKeccak256()`), which differs from the finalised +SHA3-256 in padding. This is consensus-critical -- using SHA3-256 would produce +different checksums and break address compatibility with the C++ node. + +### Address Encoding Algorithm + +1. Encode the address prefix as a CryptoNote varint +2. Append the 32-byte spend public key +3. Append the 32-byte view public key +4. Append the 1-byte flags field +5. Compute Keccak-256 over bytes 1-4, take the first 4 bytes as checksum +6. Append the 4-byte checksum +7. Encode the entire blob using CryptoNote base58 + +Decoding reverses this process: base58 decode, extract and validate the varint +prefix, verify the Keccak-256 checksum, then extract the two keys and flags. + +### Varint Encoding + +The wire format uses 7-bit variable-length integers identical to protobuf +varints. Each byte carries 7 data bits in the low bits with the MSB set to 1 +if more bytes follow. A uint64 requires at most 10 bytes. The implementation +provides sentinel errors (`ErrVarintOverflow`, `ErrVarintEmpty`) for malformed +input. + +### Hardfork System (Reverse-Scan VersionAtHeight) + +`VersionAtHeight()` iterates all hardforks and returns the highest version whose +activation height has been passed. A fork with `Height=0` is active from genesis. +A fork with `Height=N` is active at heights strictly greater than N. + +This scan approach (rather than a sorted binary search) is deliberate: the fork +list is small (7 entries) and correctness is trivially verifiable. The same list +drives both `VersionAtHeight()` and `IsHardForkActive()`. + +### LWMA Difficulty Adjustment + +The difficulty algorithm uses the LWMA (Linear Weighted Moving Average) approach: + +``` +nextDiff = difficultyDelta * targetInterval / timeSpan +``` + +The window examines up to 735 blocks (720 window + 15 lag). When fewer blocks +are available (early chain), the algorithm uses whatever data exists. Division +by zero is prevented by clamping the time span to a minimum of 1 second. +`StarterDifficulty` (value 1) is returned when insufficient data is available. + +### ADR-001: Go Shell + C++ Crypto Library + +This package follows ADR-001. All protocol logic, data types, serialisation, +and configuration live in pure Go. Only the mathematically complex cryptographic +primitives (ring signatures, bulletproofs, Zarcanum proofs) will be delegated to +a cleaned C++ library via CGo in later phases. This boundary keeps the Go code +testable without a C toolchain while preserving access to battle-tested +cryptographic implementations. diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..87c7308 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,202 @@ +# Development Guide + +## Prerequisites + +- Go 1.25 or later (the module declares `go 1.25`) +- `golang.org/x/crypto` for Keccak-256 (legacy, pre-NIST) +- No CGO required + +No C toolchain, no system libraries, no external build tools. A plain +`go build ./...` is sufficient. + +--- + +## Build and Test + +```bash +# Run all tests +go test ./... + +# Run all tests with the race detector (required before every commit) +go test -race ./... + +# Run a single test by name +go test -v -run TestVersionAtHeight ./config/ + +# Run a single subtest +go test -v -run "TestVersionAtHeight_Good/genesis" ./config/ + +# Check for vet issues +go vet ./... + +# Tidy dependencies +go mod tidy +``` + +All three commands (`go test -race ./...`, `go vet ./...`, and `go mod tidy`) +must produce no errors or warnings before a commit is pushed. + +--- + +## Test Patterns + +### File Organisation + +Each package has a corresponding `_test.go` file in the same package (white-box +tests): + +- `config/config_test.go` -- constant validation against C++ source values +- `config/hardfork_test.go` -- hardfork schedule and version lookup +- `types/address_test.go` -- address encode/decode round-trips, base58, checksums +- `difficulty/difficulty_test.go` -- LWMA algorithm behaviour +- `wire/varint_test.go` -- varint encode/decode round-trips, boundary values + +### Naming Convention + +All tests follow the `_Good`, `_Bad`, `_Ugly` suffix pattern: + +- `_Good` -- happy path (correct inputs produce correct outputs) +- `_Bad` -- expected error conditions (invalid input, checksum corruption) +- `_Ugly` -- edge cases (empty slices, nil inputs, overflow, zero time spans) + +Examples: + +``` +TestAddressEncodeDecodeRoundTrip_Good +TestDecodeAddress_Bad +TestBase58Empty_Ugly +TestIsHardForkActive_Bad +TestVersionAtHeight_Ugly +TestNextDifficulty_Ugly +TestDecodeVarint_Ugly +``` + +### Table-Driven Subtests + +Most test functions use table-driven subtests with `t.Run()`: + +```go +tests := []struct { + name string + height uint64 + want uint8 +}{ + {"genesis", 0, HF0Initial}, + {"before_hf1", 10080, HF0Initial}, + {"at_hf1_hf2", 10081, HF2}, +} +for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := VersionAtHeight(MainnetForks, tt.height) + if got != tt.want { + t.Errorf("got %d, want %d", got, tt.want) + } + }) +} +``` + +### Test Helpers + +`makeTestAddress(flags uint8)` creates an address with deterministic byte +patterns (sequential values 0-31 for the spend key, 32-63 for the view key). +This produces reproducible base58 output for round-trip testing. + +### Assertion Style + +Tests use the standard library `testing` package directly with `t.Error`, +`t.Errorf`, and `t.Fatal`. Testify is not used in this package. Error messages +include both the got and want values with descriptive context. + +--- + +## Coverage + +Current coverage by package: + +| Package | Coverage | +|---------|----------| +| config | 100.0% | +| difficulty | 81.0% | +| types | 73.4% | +| wire | 95.2% | + +Total test functions: 75 (across 5 test files). + +The lower coverage in `types/` reflects unexported helper functions +(`encodeBlock`, `decodeBlock`, `base58CharIndex`) that are exercised indirectly +through the public API but have branches not fully reached by the current test +vectors. The lower coverage in `difficulty/` reflects the window-capping branch +that only triggers with more than 735 block entries. + +`go test -race ./...` passes clean across all packages. + +--- + +## Coding Standards + +### Language + +UK English throughout: colour, organisation, serialise, initialise, behaviour. +Do not use American spellings in identifiers, comments, or documentation. + +### Go Style + +- All exported types, functions, and fields must have doc comments +- Error strings use the `package: description` format (e.g. `types: invalid hex + for hash`) +- Error wrapping uses `fmt.Errorf("types: description: %w", err)` +- Every source file carries the EUPL-1.2 copyright header +- No emojis in code or comments +- Imports are ordered: stdlib, then `golang.org/x`, then `forge.lthn.ai`, each + separated by a blank line + +### Dependencies + +Direct dependencies are intentionally minimal: + +| Dependency | Purpose | +|------------|---------| +| `golang.org/x/crypto` | Keccak-256 (legacy, pre-NIST) for address checksums | +| `golang.org/x/sys` | Indirect, required by `golang.org/x/crypto` | + +No test-only dependencies beyond the standard library `testing` package. + +--- + +## Licence + +EUPL-1.2. Every source file carries the standard copyright header: + +``` +// Copyright (c) 2017-2026 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// SPDX-License-Identifier: EUPL-1.2 +``` + +--- + +## Commit Convention + +Format: `type(scope): description` + +Common types: `feat`, `fix`, `test`, `refactor`, `docs`, `perf`, `chore` + +Common scopes: `config`, `types`, `wire`, `difficulty`, `address`, `hardfork` + +Every commit must include: + +``` +Co-Authored-By: Charon +``` + +Example: + +``` +feat(types): add Zarcanum confidential output type + +Co-Authored-By: Charon +``` + +Commits must not be pushed unless `go test -race ./...` and `go vet ./...` both +pass. `go mod tidy` must produce no changes. diff --git a/docs/history.md b/docs/history.md new file mode 100644 index 0000000..6a4253c --- /dev/null +++ b/docs/history.md @@ -0,0 +1,176 @@ +# 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.in` and + `default.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. `ChainConfig` struct with pre-populated `Mainnet` + and `Testnet` globals. Hardfork schedule (HF0-HF6) with `VersionAtHeight()` + and `IsHardForkActive()` 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 for `Hash` and `PublicKey`. CryptoNote base58 + address encoding with Keccak-256 checksums. `Address` struct with + `Encode()`/`DecodeAddress()` round-trip. `BlockHeader`, `Block`, + `Transaction` structs. Input types (`TxInputGenesis`, `TxInputToKey`) and + output types (`TxOutputBare`, `TxOutputZarcanum`) with wire type tags. + `TxInput` and `TxOutput` interfaces. + +- **wire/** -- CryptoNote varint encoding (7-bit LEB128 with MSB continuation). + `EncodeVarint()` and `DecodeVarint()` 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 (returns `StarterDifficulty`), 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, `ChainConfig` struct fields, + transaction limits, and transaction version constants. + +- `config/hardfork_test.go` -- 7 test functions covering `VersionAtHeight()` + 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 through + `MaxUint64`), 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.