commit ddec082b0a70a0b9c4ccf337bda3db073719c78f Author: Claude Date: Fri Feb 20 15:12:17 2026 +0000 docs: populate wiki with architecture, chain params, and development roadmap Co-Authored-By: Claude Opus 4.6 diff --git a/Architecture.md b/Architecture.md new file mode 100644 index 0000000..d1276eb --- /dev/null +++ b/Architecture.md @@ -0,0 +1,104 @@ +# Architecture + +## Package Structure + +``` +go-blockchain/ + config/ Chain parameters (mainnet/testnet), hardfork schedule + crypto/ CGo bridge to libcryptonote (ring sigs, BP+, Zarcanum, stealth) + types/ Core data types: Block, Transaction, Address, KeyImage + wire/ Binary serialisation (consensus-critical, bit-identical to C++) + p2p/ Levin TCP protocol, peer discovery, handshake + rpc/ Daemon and wallet JSON-RPC client + server + chain/ Blockchain storage, block/tx validation, mempool + wallet/ Key management, output scanning, tx construction + difficulty/ PoW + PoS difficulty adjustment (LWMA variant) + consensus/ Hardfork rules, block reward, fee policy +``` + +## Dependency Diagram + +``` + +------------+ + | consensus | + +------+-----+ + | + +------------+------------+ + | | + +-----+-----+ +-----+-----+ + | chain | | difficulty | + +-----+------+ +-----------+ + | + +--------+---------+ + | | | ++----+--+ +---+---+ +---+---+ +| p2p | | rpc | | wallet| ++----+--+ +---+---+ +---+---+ + | | | + +--------+---------+ + | + +----+----+ + | wire | + +----+----+ + | + +-------+-------+ + | | + +---+---+ +-----+-----+ + | types | | config | + +---+---+ +-----------+ + | + +---+---+ + | crypto | <-- CGo boundary + +--------+ +``` + +### Key relationships + +- **config** and **types** are leaf packages with no internal dependencies (stdlib only). +- **wire** depends on **types** for struct definitions and **config** for version-specific serialisation rules. +- **crypto** wraps the C++ library via CGo; it is used by **wire** (for hashing), **chain** (for signature verification), and **wallet** (for key derivation and tx signing). +- **p2p**, **rpc**, and **wallet** are higher-level packages that depend on wire-level serialisation. +- **chain** is the central coordinator: it validates blocks using **consensus** rules, adjusts **difficulty**, and stores state. + +## CGo Bridge Boundary + +The `crypto/` package is the only package that crosses the CGo boundary. All other packages are pure Go. + +``` +Go side C++ side (libcryptonote) ++---------+ +------------------------+ +| crypto/ | --- CGo calls ---> | cn_fast_hash() | +| | | generate_key_derivation| +| | | derive_public_key | +| | | generate_key_image | +| | | check_ring_signature | +| | | CLSAG_GG_verify | +| | | CLSAG_GGX_verify | +| | | CLSAG_GGXXG_verify | +| | | bulletproof_plus_verify | +| | | zarcanum_verify | +| | | chacha8_encrypt | ++---------+ +------------------------+ +``` + +### Build tags + +The crypto package uses build tags to allow compilation without CGo for testing of non-crypto packages: + +```go +//go:build cgo + +package crypto +``` + +When CGo is disabled, stub implementations return errors, allowing the rest of the codebase to compile and run tests that do not require real cryptographic operations. + +## Design Principles + +1. **Consensus-critical code must be bit-identical** to the C++ implementation. The `wire/` package produces exactly the same binary output as the C++ serialisation for the same input. + +2. **No global state.** Chain parameters are passed via `config.ChainConfig` structs, not package-level globals. `Mainnet` and `Testnet` are pre-defined instances. + +3. **Interfaces at boundaries.** The `chain/` package defines interfaces for storage backends, allowing LMDB, Pebble, or in-memory stores to be swapped. + +4. **Test against real chain data.** Wherever possible, tests use actual mainnet block and transaction hex blobs as test vectors, ensuring compatibility with the C++ node. diff --git a/Chain-Parameters.md b/Chain-Parameters.md new file mode 100644 index 0000000..92c0d38 --- /dev/null +++ b/Chain-Parameters.md @@ -0,0 +1,206 @@ +# Chain Parameters + +All values sourced from `currency_config.h.in` and `default.cmake` in the C++ codebase. These are consensus-critical constants. + +## Tokenomics + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `COIN` | 1,000,000,000,000 (10^12) | Smallest unit to coin ratio | +| `CURRENCY_DISPLAY_DECIMAL_POINT` | 12 | Display precision | +| `CURRENCY_BLOCK_REWARD` | 1,000,000,000,000 | 1.0 LTHN per block | +| `TX_DEFAULT_FEE` | 10,000,000,000 | 0.01 LTHN | +| `TX_MINIMUM_FEE` | 10,000,000,000 | 0.01 LTHN | +| `PREMINE_AMOUNT` | 10,000,000,000,000,000,000 | 10,000,000 LTHN (10M) | +| `BASE_REWARD_DUST_THRESHOLD` | 1,000,000 | 10^6 atomic units | +| `DEFAULT_DUST_THRESHOLD` | 0 | No dust threshold | +| `CURRENCY_NAME` | Lethean | | +| `CURRENCY_NAME_ABR` | LTHN | Ticker symbol | + +### Supply model + +- **Block reward**: Fixed at 1 LTHN per block (no halving of reward, but see HF6 for block time doubling). +- **Premine**: 10,000,000 LTHN reserved at genesis. +- **Fee model**: Default and minimum fee of 0.01 LTHN. Fees are burned (sent to null address). + +## Address Prefixes + +| Type | Prefix (hex) | Base58 starts with | Description | +|------|-------------|-------------------|-------------| +| Standard | `0x1eaf7` | `iTHN` | Non-auditable address | +| Integrated | `0xdeaf7` | `iTHn` | Standard + payment ID | +| Auditable | `0x3ceff7` | `iThN` | Auditable address | +| Auditable integrated | `0x8b077` | `iThn` | Auditable + payment ID | + +Addresses are encoded using CryptoNote base58 with a 4-byte Keccak-256 checksum. The prefix is varint-encoded before the spend and view public keys (32 bytes each). + +## Block Timing + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `DIFFICULTY_POW_TARGET` | 120 seconds | PoW block target | +| `DIFFICULTY_POS_TARGET` | 120 seconds | PoS block target | +| `DIFFICULTY_TOTAL_TARGET` | 60 seconds | (POW + POS) / 4 | +| `CURRENCY_BLOCKS_PER_DAY` | ~1440 | 86400 / 60 | +| `POS_START_HEIGHT` | 0 | PoS active from genesis | + +### Post-HF6 timing (future) + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `DIFFICULTY_POW_TARGET_HF6` | 240 seconds | Doubled from 120s | +| `DIFFICULTY_POS_TARGET_HF6` | 240 seconds | Doubled from 120s | +| `DIFFICULTY_TOTAL_TARGET_HF6` | 120 seconds | (240 + 240) / 4 | +| `CURRENCY_BLOCKS_PER_DAY_HF6` | ~720 | Halved from ~1440 | + +## Difficulty + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `DIFFICULTY_WINDOW` | 720 | Blocks in calculation window | +| `DIFFICULTY_LAG` | 15 | Lag offset | +| `DIFFICULTY_CUT` | 60 | Timestamps cut after sorting | +| `DIFFICULTY_BLOCKS_COUNT` | 735 | WINDOW + LAG | +| `DIFFICULTY_POW_STARTER` | 1 | Initial PoW difficulty | +| `DIFFICULTY_POS_STARTER` | 1 | Initial PoS difficulty | + +## Transaction Limits + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `CURRENCY_TX_MAX_ALLOWED_INPUTS` | 256 | Limited by surjection proof | +| `CURRENCY_TX_MAX_ALLOWED_OUTS` | 2000 | Maximum outputs per tx | +| `CURRENCY_TX_MIN_ALLOWED_OUTS` | 2 | Effective from HF4 (Zarcanum) | +| `CURRENCY_DEFAULT_DECOY_SET_SIZE` | 10 | Ring size pre-HF4 | +| `CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE` | 15 | Ring size post-HF4 | +| `CURRENCY_HF4_MANDATORY_MIN_COINAGE` | 10 | Minimum blocks before spending | +| `CURRENCY_MINED_MONEY_UNLOCK_WINDOW` | 10 | Coinbase maturity (blocks) | +| `CURRENCY_MAX_TRANSACTION_BLOB_SIZE` | ~122,800 bytes | Full reward zone minus reserved | + +### Transaction versions + +| Version | Constant | Context | +|---------|----------|---------| +| 0 | `TRANSACTION_VERSION_INITAL` | Legacy format | +| 1 | `TRANSACTION_VERSION_PRE_HF4` | Pre-Zarcanum | +| 2 | `TRANSACTION_VERSION_POST_HF4` | Zarcanum confidential | +| 3 | `TRANSACTION_VERSION_POST_HF5` | Confidential assets | + +## Block Limits + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `CURRENCY_MAX_BLOCK_NUMBER` | 500,000,000 | Maximum block height | +| `CURRENCY_MAX_BLOCK_SIZE` | 500,000,000 | Header blob limit (unused) | +| `CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE` | 125,000 bytes | Penalty-free block size | +| `CURRENCY_COINBASE_BLOB_RESERVED_SIZE` | 1,100 bytes | Reserved in coinbase | +| `CURRENCY_REWARD_BLOCKS_WINDOW` | 400 blocks | Reward calculation window | + +## Block Versions + +| Constant | Value | Notes | +|----------|-------|-------| +| `BLOCK_MAJOR_VERSION_GENESIS` | 1 | Genesis block | +| `BLOCK_MAJOR_VERSION_INITIAL` | 0 | Initial version | +| `HF1_BLOCK_MAJOR_VERSION` | 1 | After HF1 | +| `HF3_BLOCK_MAJOR_VERSION` | 2 | After HF3 | +| `CURRENT_BLOCK_MAJOR_VERSION` | 3 | Current (HF4+) | + +## Timestamp Validation + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `CURRENCY_BLOCK_FUTURE_TIME_LIMIT` | 7,200 seconds | PoW: 2 hours into future | +| `CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT` | 1,200 seconds | PoS: 20 minutes into future | +| `BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW` | 60 blocks | Median timestamp window | + +## P2P Network + +### Ports + +| Network | P2P | RPC | Stratum | +|---------|-----|-----|---------| +| Mainnet | 36942 | 36941 | 36940 | +| Testnet | 46942 | 46941 | 46940 | + +### Network Identity + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `CURRENCY_FORMATION_VERSION` | 84 (mainnet), 100 (testnet) | Base formation version | +| `P2P_NETWORK_ID_VER` | `CURRENCY_FORMATION_VERSION + 0` | Network ID version byte | +| `CURRENCY_GENESIS_NONCE` | `CURRENCY_FORMATION_VERSION + 101011010121` | Genesis block nonce | + +### Peer Management + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `P2P_LOCAL_WHITE_PEERLIST_LIMIT` | 1,000 | Verified peers | +| `P2P_LOCAL_GRAY_PEERLIST_LIMIT` | 5,000 | Unverified peers | +| `P2P_DEFAULT_CONNECTIONS_COUNT` | 8 | Outgoing connections | +| `P2P_DEFAULT_HANDSHAKE_INTERVAL` | 60 seconds | | +| `P2P_DEFAULT_PACKET_MAX_SIZE` | 50,000,000 bytes | 50 MB | +| `P2P_DEFAULT_PEERS_IN_HANDSHAKE` | 250 | | +| `P2P_DEFAULT_CONNECTION_TIMEOUT` | 5,000 ms | | +| `P2P_DEFAULT_PING_CONNECTION_TIMEOUT` | 2,000 ms | | +| `P2P_DEFAULT_INVOKE_TIMEOUT` | 120,000 ms | 2 minutes | +| `P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT` | 10,000 ms | | +| `P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT` | 70% | Prefer verified peers | +| `P2P_IP_BLOCKTIME` | 86,400 seconds | 24 hours | +| `P2P_IP_FAILS_BEFOR_BLOCK` | 10 | Failures before blocking | +| `P2P_FAILED_ADDR_FORGET_SECONDS` | 300 seconds | 5 minutes | +| `P2P_IDLE_CONNECTION_KILL_INTERVAL` | 300 seconds | 5 minutes | + +### Sync Parameters + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT` | 2,000 | Block IDs per request | +| `BLOCKS_SYNCHRONIZING_DEFAULT_COUNT` | 200 | Blocks per download | +| `BLOCKS_SYNCHRONIZING_DEFAULT_SIZE` | 2,000,000 bytes | 2 MB packet limit | +| `CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT` | 500 | | +| `CURRENCY_PROTOCOL_MAX_TXS_REQUEST_COUNT` | 500 | | +| `COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT` | 4,000 | Fast sync batch | + +## PoS Parameters + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `POS_SCAN_WINDOW` | 600 seconds | 10 minutes | +| `POS_SCAN_STEP` | 15 seconds | | +| `POS_MODFIFIER_INTERVAL` | 10 | | +| `POS_MINIMUM_COINSTAKE_AGE` | 10 blocks | | +| `POS_STARTER_KERNEL_HASH` | `00000000...6e4b` | Initial kernel hash | +| `BLOCK_POS_STRICT_SEQUENCE_LIMIT` | 20 | Max consecutive PoS blocks | + +## Alias System + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `MAX_ALIAS_PER_BLOCK` | 1,000 | | +| `ALIAS_NAME_MAX_LEN` | 255 | | +| `ALIAS_MINIMUM_PUBLIC_SHORT_NAME_ALLOWED` | 6 | Minimum characters | +| `ALIAS_VALID_CHARS` | `0-9a-z-.` | Allowed characters | +| `ALIAS_COMMENT_MAX_SIZE_BYTES` | 400 | | + +## Mempool and Alt Blocks + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `CURRENCY_MEMPOOL_TX_LIVETIME` | 345,600 seconds | 4 days | +| `CURRENCY_ALT_BLOCK_LIVETIME_COUNT` | ~10,080 blocks | ~7 days | +| `CURRENCY_ALT_BLOCK_MAX_COUNT` | 43,200 | ~30 days | +| `CURRENCY_FREE_TX_MAX_BLOB_SIZE` | 1,024 bytes | Free tx size limit | +| `CURRENCY_RELAY_TXS_MAX_COUNT` | 5 | Per relay batch | + +## Wallet + +| Parameter | Value | Notes | +|-----------|-------|-------| +| `WALLET_FILE_SIGNATURE_V2` | `0x1111011201101011` | File magic | +| `WALLET_FILE_SERIALIZATION_VERSION` | 168 | Current | +| `WALLET_FILE_LAST_SUPPORTED_VERSION` | 165 | Minimum supported | +| `WALLET_BRAIN_DATE_OFFSET` | 1,543,622,400 | Seed phrase epoch | +| `WALLET_BRAIN_DATE_QUANTUM` | 604,800 | 1 week in seconds | +| `WALLET_BRAIN_DATE_MAX_WEEKS_COUNT` | 800 | ~15 years | +| `OFFER_MAXIMUM_LIFE_TIME` | 2,592,000 seconds | 30 days | diff --git a/Crypto-Primitives.md b/Crypto-Primitives.md new file mode 100644 index 0000000..d76f2eb --- /dev/null +++ b/Crypto-Primitives.md @@ -0,0 +1,210 @@ +# Crypto Primitives + +This page documents the cryptographic operations that the C++ bridge (`crypto/` package) provides to the Go codebase. Each primitive is described at a conceptual level: what it does, why the chain needs it, and which hardfork introduces or changes it. + +## Curve Operations + +### Ed25519 / Curve25519 + +**What it does**: Elliptic curve arithmetic on the Ed25519 curve (Twisted Edwards form of Curve25519). Point addition, scalar multiplication, point-scalar operations. + +**Why it is needed**: All public keys, key images, commitments, and ring signature operations are built on Ed25519 group elements. The curve provides 128-bit security. + +**Key types**: +- `PublicKey` (32 bytes) -- compressed Ed25519 point +- `SecretKey` (32 bytes) -- scalar modulo the group order l +- `KeyDerivation` (32 bytes) -- Diffie-Hellman shared secret point + +**Available from**: Genesis (HF0). + +## Hash Functions + +### Keccak-256 (`cn_fast_hash`) + +**What it does**: Computes Keccak-256 (the original Keccak, not SHA-3) of arbitrary data, producing a 32-byte hash. + +**Why it is needed**: The primary hash function throughout the protocol. Used for transaction hashes, block hashes, key derivations, address checksums, and proof construction. + +**Available from**: Genesis (HF0). + +### Tree Hash (`tree_hash`) + +**What it does**: Computes a Merkle tree hash over a set of transaction hashes within a block. Uses Keccak-256 as the leaf/node hash. + +**Why it is needed**: The block header commits to all transactions via a single 32-byte root hash. This allows SPV-style proofs of transaction inclusion. + +**Available from**: Genesis (HF0). + +### BLAKE2 + +**What it does**: BLAKE2b hash function, used in specific proof constructions (Bulletproofs+, Zarcanum). + +**Why it is needed**: Provides domain-separated hashing in zero-knowledge proof systems where Keccak is not used. + +**Available from**: HF4 (Zarcanum). + +## Stealth Addresses + +### Key Derivation + +**What it does**: Given a transaction public key R and the recipient's secret view key a, computes a shared secret `D = a * R`. This derivation is then hashed with an output index to produce per-output keys. + +**Why it is needed**: Enables unlinkable one-time addresses. Each output appears at a unique stealth address that only the recipient can identify and spend. + +### One-Time Key Generation + +**What it does**: For output index i, derives the one-time public key `P = Hs(D, i) * G + B` where B is the recipient's spend public key. The recipient can compute the corresponding secret key. + +**Why it is needed**: Ensures that outputs sent to the same address are indistinguishable from each other on the blockchain. + +**Available from**: Genesis (HF0). + +## Key Images + +**What it does**: For a one-time key pair (p, P), computes the key image `I = p * Hp(P)` where Hp is a hash-to-point function. + +**Why it is needed**: Double-spend prevention. Each output can only be spent once. When spent, its key image is revealed and recorded; any subsequent attempt to spend the same output would produce an identical key image, which the network rejects. + +**Properties**: Key images are deterministic (same output always produces the same image) and unlinkable (the image cannot be traced back to the output without the secret key). + +**Available from**: Genesis (HF0). + +## Ring Signatures + +Ring signatures allow a spender to prove ownership of one output within a set (the "ring") without revealing which specific output they own. The set of other outputs (decoys) provides anonymity. + +### Classic CryptoNote Ring Signatures (NLSAG) + +**What it does**: A Spontaneous Anonymous Group signature (SAG) scheme as described in the original CryptoNote whitepaper. For each input, the spender constructs a ring of public keys and signs a message such that any ring member could have been the signer. + +**Ring size**: 10 decoys + 1 real (pre-HF4). + +**Why it is needed**: Transaction input privacy. Observers cannot determine which output in the ring is being spent. + +**Available from**: Genesis (HF0). Used for transaction versions 0 and 1. + +### CLSAG-GG + +**What it does**: Compact Linkable Spontaneous Anonymous Group signature with two base points (G, G). A more efficient ring signature that produces smaller signatures and faster verification compared to the classic scheme. + +**Why it is needed**: Reduces transaction size and verification time while maintaining the same security guarantees. + +**Available from**: HF4 (Zarcanum). + +### CLSAG-GGX + +**What it does**: CLSAG variant with three base points (G, G, X). Used for Zarcanum confidential transactions where the signer must prove knowledge of the secret key and the amount commitment blinding factor simultaneously. + +**Why it is needed**: Enables confidential (hidden amount) transactions. The ring signature simultaneously proves spend authority and that the amount commitment is well-formed. + +**Available from**: HF4 (Zarcanum). Used in `ZC_sig` structures. + +### CLSAG-GGXXG + +**What it does**: CLSAG variant with five base points (G, G, X, X, G). The most complex variant, used in Zarcanum Proof-of-Stake block signing where the staker must prove knowledge of multiple secrets simultaneously. + +**Why it is needed**: Combines spend authority proof, amount commitment proof, and staking eligibility proof into a single compact ring signature for PoS blocks. + +**Available from**: HF4 (Zarcanum). Used in `zarcanum_sig` structures. + +## Range Proofs + +### Bulletproofs+ (BP+) + +**What it does**: Zero-knowledge range proofs that demonstrate a committed value lies within [0, 2^64) without revealing the value. Bulletproofs+ are an improved version of Bulletproofs with smaller proof size and faster verification. + +**Why it is needed**: When amounts are hidden in Pedersen commitments, the network must verify that no output has a negative amount (which would allow inflation). BP+ provides this guarantee. + +**Proof format**: `bpp_signature_serialized` with an associated `vector_UG_aggregation_proof` for commitment aggregation. + +**Available from**: HF4 (Zarcanum). Stored in `zc_outs_range_proof` attachments. + +### Bulletproofs++ (BP++) for Stake Proofs + +**What it does**: An extended Bulletproofs variant used specifically in Zarcanum PoS proofs. Proves that the stake amount meets the minimum threshold without revealing the exact amount. + +**Why it is needed**: PoS stakers must prove they hold sufficient stake without revealing their balance. + +**Proof format**: `bppe_signature_serialized` within `zarcanum_sig`. + +**Available from**: HF4 (Zarcanum). + +## Zarcanum PoS Proofs + +**What it does**: A composite proof structure for Proof-of-Stake block production under Zarcanum. Combines: +1. A stake commitment proof (scalar `d`, points `C`, `C'`, `E`) +2. Schnorr-like response scalars (`c`, `y0`-`y4`) +3. A BP++ range proof for the stake amount (`E_range_proof`) +4. A CLSAG-GGXXG ring signature (`clsag_ggxxg`) +5. A pseudo-output amount commitment + +**Why it is needed**: Allows PoS validators to prove they own a valid stake (with sufficient amount and coinage) and produce a valid block, all without revealing which specific output they are staking or how much it contains. + +**Available from**: HF4 (Zarcanum). + +## Asset Surjection Proofs + +### BGE Proofs (Bootle-Groth-Esgin) + +**What it does**: Proves that each output's blinded asset ID corresponds to one of the input asset IDs, without revealing which. One proof per output (non-aggregated). + +**Why it is needed**: When confidential assets are introduced (HF5), transactions can move multiple asset types. The surjection proof ensures that assets are not created or transmuted -- only the legitimate asset types present in the inputs can appear in the outputs. + +**Available from**: HF5 (confidential assets). Stored in `zc_asset_surjection_proof` attachments. + +## Balance Proofs + +### Double Schnorr Signature + +**What it does**: Proves that the transaction balances (sum of inputs = sum of outputs + fee) without revealing individual amounts. Implemented as a generic double Schnorr signature (`generic_double_schnorr_sig_s`). + +For transactions without Zarcanum inputs: proves the balance point is a linear combination of G. +For transactions with Zarcanum inputs: proves the balance point is a linear combination of X (the asset point), ensuring blinded asset tags cancel correctly. + +Also proves knowledge of the transaction secret key. + +**Why it is needed**: Conservation of value. Without this proof, a transaction could create or destroy coins. + +**Available from**: HF4 (Zarcanum). Stored in `zc_balance_proof` attachments. + +## Pedersen Commitments + +**What it does**: Commits to a value v with blinding factor r as `C = v * H + r * G` (or `C = v * U + r * G` in some Zarcanum contexts), where H and G are independent generator points. + +**Why it is needed**: Pedersen commitments are additively homomorphic: `C(a) + C(b) = C(a+b)`. This allows verification that inputs and outputs balance without revealing amounts. The blinding factor prevents observers from determining the committed value. + +**Available from**: HF4 (Zarcanum). The native coin asset ID `H` is a fixed curve point. + +## Wallet Encryption + +### ChaCha8 + +**What it does**: ChaCha stream cipher with 8 rounds, used to encrypt wallet files and sensitive in-memory data. + +**Why it is needed**: Protects wallet keys at rest. The wallet key file is encrypted with a key derived from the user's password via a KDF. + +**File signatures**: `0x1111011201101011` (wallet v2 format). + +**Available from**: Genesis (HF0). + +## Summary Table + +| Primitive | Purpose | Hardfork | Package constant | +|-----------|---------|----------|-----------------| +| Keccak-256 | Primary hash | HF0 | -- | +| Tree hash | Tx merkle root | HF0 | -- | +| BLAKE2 | Proof hashing | HF4 | -- | +| Ed25519 ops | Key arithmetic | HF0 | -- | +| Key derivation | Stealth addresses | HF0 | -- | +| Key images | Double-spend prevention | HF0 | -- | +| NLSAG ring sigs | Input privacy (classic) | HF0 | `CURRENCY_DEFAULT_DECOY_SET_SIZE = 10` | +| CLSAG-GG | Efficient ring sigs | HF4 | `CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE = 15` | +| CLSAG-GGX | Confidential tx sigs | HF4 | -- | +| CLSAG-GGXXG | PoS stake sigs | HF4 | -- | +| Bulletproofs+ | Amount range proofs | HF4 | -- | +| Bulletproofs++ | Stake range proofs | HF4 | -- | +| Zarcanum proofs | PoS composite proofs | HF4 | -- | +| BGE surjection | Asset type proofs | HF5 | -- | +| Double Schnorr | Balance proofs | HF4 | -- | +| Pedersen commitments | Hidden amounts | HF4 | -- | +| ChaCha8 | Wallet encryption | HF0 | -- | diff --git a/Data-Structures.md b/Data-Structures.md new file mode 100644 index 0000000..5cd1329 --- /dev/null +++ b/Data-Structures.md @@ -0,0 +1,343 @@ +# Data Structures + +Field-level documentation of the core blockchain data structures. All structures must be serialised in a consensus-critical, bit-identical manner matching the C++ implementation. + +## Block Header + +The block header is the fixed-size preamble of every block. + +```go +type BlockHeader struct { + MajorVersion uint8 // Block format version (0, 1, 2, 3) + MinorVersion uint64 // Minor version (varint) + Timestamp uint64 // Unix timestamp (varint) + PrevID Hash // Hash of the previous block (32 bytes) + Nonce uint64 // PoW nonce + Flags uint8 // Block flags (PoW=0, PoS=1) +} +``` + +| Field | Type | Serialisation | Description | +|-------|------|--------------|-------------| +| `major_version` | `uint8` | Fixed 1 byte | Block format version. 0=initial, 1=HF1, 2=HF3, 3=HF4+ | +| `nonce` | `uint64` | Fixed 8 bytes | Proof-of-Work nonce. Serialised immediately after major_version | +| `prev_id` | `[32]byte` | Fixed 32 bytes | Keccak-256 hash of the previous block | +| `minor_version` | `uint64` | Varint | Minor version, typically 0 | +| `timestamp` | `uint64` | Varint | Block timestamp in seconds since Unix epoch | +| `flags` | `uint8` | Fixed 1 byte | Bit 0: PoS flag (0=PoW, 1=PoS) | + +**Note**: The serialisation order differs from the struct field order. The canonical wire format is: `major_version`, `nonce`, `prev_id`, `minor_version`, `timestamp`, `flags`. + +## Block + +A block extends the header with a coinbase transaction and a list of transaction hashes. + +```go +type Block struct { + BlockHeader + MinerTx Transaction // Coinbase transaction (block reward + fees) + TxHashes []Hash // Hashes of included transactions +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `miner_tx` | `Transaction` | The coinbase transaction that pays the block reward | +| `tx_hashes` | `[]Hash` | Ordered list of transaction hashes included in this block | + +The block hash is computed by hashing the concatenation of: the block header hash, the miner transaction hash, and the Merkle tree root of `tx_hashes`. + +## Transaction + +Transactions transfer value between addresses. The format has evolved across hardforks. + +### Transaction Prefix + +```go +type TransactionPrefix struct { + Version uint64 // Transaction version (varint): 0, 1, 2, or 3 + HardforkID uint8 // Hardfork identifier (only for version >= 3) + Vin []TxInput // Inputs (variant type) + Extra []ExtraV // Extra data (variant type) + Vout []TxOutput // Outputs (variant type) +} +``` + +### Full Transaction + +```go +type Transaction struct { + TransactionPrefix + Attachment []AttachmentV // Service attachments + Signatures []SignatureV // Per-input signatures (variant: NLSAG, ZC_sig, zarcanum_sig) + Proofs []ProofV // Global proofs (range proofs, balance proofs, surjection proofs) +} +``` + +| Field | Type | Serialisation | Description | +|-------|------|--------------|-------------| +| `version` | `uint64` | Varint | 0=initial, 1=pre-HF4, 2=post-HF4, 3=post-HF5 | +| `hardfork_id` | `uint8` | Fixed (v3+ only) | Identifies the hardfork rules this tx follows | +| `vin` | `[]txin_v` | Variant array | Transaction inputs | +| `extra` | `[]extra_v` | Variant array | Extra fields (unlock times, payment IDs, aliases, asset ops) | +| `vout` | `[]tx_out_v` | Variant array | Transaction outputs | +| `attachment` | `[]attachment_v` | Variant array | Service attachments (comments, encrypted data) | +| `signatures` | `[]signature_v` | Variant array | One signature per input | +| `proofs` | `[]proof_v` | Variant array | Global proofs (BP+, balance, surjection) | + +### Version-specific serialisation + +- **Version 0-1**: Uses legacy `transaction_v1` format with separate fields for attachments and signatures. +- **Version 2**: Zarcanum format. Inputs are `txin_zc_input`, outputs are `tx_out_zarcanum`. Signatures are `ZC_sig` or `zarcanum_sig`. +- **Version 3**: Adds `hardfork_id` field after `vout`. Supports asset operations. + +## Input Types + +Transaction inputs are a variant (tagged union) of five possible types: + +### `txin_gen` -- Coinbase Input + +```go +type TxInGen struct { + Height uint64 // Block height (varint) +} +``` + +Used only in the miner (coinbase) transaction. Specifies the block height, which determines the block reward. + +### `txin_to_key` -- Standard Input + +```go +type TxInToKey struct { + Amount uint64 // Input amount (varint, 0 for confidential) + KeyOffsets []TxOutRef // Ring member references (global indices or tx_id:n) + KImage KeyImage // Key image (32 bytes) -- double-spend tag + EtcDetails []TxInEtcDetail // Optional: signed_parts, attachment_info +} +``` + +The standard transparent input type. References a set of outputs (the ring) by their global indices and proves ownership of one via a ring signature. The key image uniquely identifies the real output being spent. + +### `txin_multisig` -- Multisig Input + +```go +type TxInMultisig struct { + Amount uint64 // Input amount (varint) + MultisigOutID Hash // Hash identifying the multisig output (32 bytes) + SigsCount uint32 // Number of signatures (varint) + EtcDetails []TxInEtcDetail // Optional details +} +``` + +Spends a multisig output. Requires `SigsCount` signatures matching the threshold defined in the referenced multisig output. + +### `txin_htlc` -- HTLC Input + +```go +type TxInHTLC struct { + TxInToKey // Inherits all fields from txin_to_key + HLTCOrigin string // HTLC preimage or refund proof +} +``` + +Spends a hash time-locked contract output. Extends `txin_to_key` with an HTLC origin string that proves knowledge of the hash preimage (before expiry) or ownership of the refund key (after expiry). + +### `txin_zc_input` -- Zarcanum Confidential Input + +```go +type TxInZCInput struct { + KeyOffsets []TxOutRef // Ring member references + KImage KeyImage // Key image (32 bytes) + EtcDetails []TxInEtcDetail // Optional details +} +``` + +The confidential input type introduced in HF4 (Zarcanum). Unlike `txin_to_key`, there is no `amount` field -- the amount is hidden within a Pedersen commitment. The corresponding signature (in the `signatures` array) is a `ZC_sig` containing pseudo-output commitments and a CLSAG-GGX signature. + +## Output Types + +Transaction outputs are a variant of two types: + +### `tx_out_bare` -- Transparent Output + +```go +type TxOutBare struct { + Amount uint64 // Output amount in atomic units (varint) + Target TxOutTarget // Variant: txout_to_key, txout_multisig, or txout_htlc +} +``` + +The pre-Zarcanum output type with a visible amount. The target specifies the spending condition: + +#### `txout_to_key` + +```go +type TxOutToKey struct { + Key PublicKey // One-time public key (32 bytes) + MixAttr uint8 // Mixing attribute: 0=relaxed, 1=no mix, 2+=minimum ring size +} +``` + +Standard output payable to a one-time stealth address. + +#### `txout_multisig` + +```go +type TxOutMultisig struct { + MinimumSigs uint32 // Threshold (varint) + Keys []PublicKey // Participant public keys +} +``` + +M-of-N multisig output requiring `MinimumSigs` signatures from the `Keys` set. + +#### `txout_htlc` + +```go +type TxOutHTLC struct { + HTLCHash Hash // Hash lock (32 bytes) + Flags uint8 // Hash type: 0=SHA256, 1=RIPEMD160 + Expiration uint64 // Expiration height or timestamp (varint) + PkeyRedeem PublicKey // Redeemer's key (before expiry) + PkeyRefund PublicKey // Refunder's key (after expiry) +} +``` + +Hash time-locked contract output with dual spending paths. + +### `tx_out_zarcanum` -- Confidential Output + +```go +type TxOutZarcanum struct { + StealthAddress PublicKey // One-time stealth address (32 bytes) + ConcealingPoint PublicKey // Group element Q, premultiplied by 1/8 + AmountCommitment PublicKey // Pedersen commitment, premultiplied by 1/8 + BlindedAssetID PublicKey // Group element T, premultiplied by 1/8 + EncryptedAmount uint64 // Encrypted amount (XOR with shared secret) + MixAttr uint8 // Mixing attribute +} +``` + +The confidential output type introduced in HF4. The amount is hidden inside `AmountCommitment` (a Pedersen commitment). The `BlindedAssetID` hides which asset type the output contains. The `EncryptedAmount` allows the recipient (who can derive the shared secret) to decrypt the actual amount. + +All curve points are premultiplied by 1/8 for efficient batch verification. + +## Signature Types + +Signatures are a variant matching the input type: + +| Variant | Used with | Description | +|---------|-----------|-------------| +| `NLSAG_sig` | `txin_to_key` (v0-1) | Classic CryptoNote ring signature: vector of `(c, r)` pairs | +| `void_sig` | `txin_gen` | No signature needed for coinbase inputs | +| `ZC_sig` | `txin_zc_input` (v2) | Zarcanum sig: pseudo-out commitments + CLSAG-GGX | +| `zarcanum_sig` | `txin_zc_input` (PoS v2) | Full Zarcanum PoS proof: CLSAG-GGXXG + BP++ + Schnorr | + +### ZC_sig structure + +```go +type ZCSig struct { + PseudoOutAmountCommitment PublicKey // Premultiplied by 1/8 + PseudoOutBlindedAssetID PublicKey // Premultiplied by 1/8 + CLSAGs_GGX CLSAG_GGX_Signature // Ring signature +} +``` + +### zarcanum_sig structure + +```go +type ZarcanumSig struct { + D PublicKey // Scalar commitment + C PublicKey // Point C + CPrime PublicKey // Point C' + E PublicKey // Point E + ResponseC Scalar // Challenge scalar + Y0, Y1, Y2, Y3, Y4 Scalar // Response scalars + ERangeProof BPPE_Signature // BP++ for stake amount + PseudoOutAmountCommitment PublicKey // Premultiplied by 1/8 + CLSAG_GGXXG CLSAG_GGXXG_Signature // 5-base ring signature +} +``` + +## Proof Types + +Global proofs are stored in the transaction's `proofs` array: + +| Variant | Description | +|---------|-------------| +| `zc_asset_surjection_proof` | BGE proofs (one per output) proving asset type conservation | +| `zc_outs_range_proof` | BP+ range proof + aggregation proof for output amounts | +| `zc_balance_proof` | Double Schnorr signature proving input/output balance | +| `asset_operation_proof` | Proves asset operation commitment is well-formed | +| `asset_operation_ownership_proof` | Schnorr proof of asset ownership | +| `asset_operation_ownership_proof_eth` | ETH signature proof of asset ownership | + +## Address + +### Account Public Address + +```go +type AccountPublicAddress struct { + SpendPublicKey PublicKey // 32 bytes + ViewPublicKey PublicKey // 32 bytes + Flags uint8 // Bit 0: auditable flag +} +``` + +| Field | Size | Description | +|-------|------|-------------| +| `spend_public_key` | 32 bytes | Used to authorise spending | +| `view_public_key` | 32 bytes | Used to detect incoming outputs | +| `flags` | 1 byte | `0x01` = auditable address | + +### Address Encoding + +Addresses are encoded as: + +``` +base58(varint(prefix) || spend_public_key || view_public_key [|| flags] || checksum) +``` + +Where: +- `prefix` is the address type prefix (e.g. `0x1eaf7` for standard) +- `spend_public_key` and `view_public_key` are 32 bytes each +- `flags` is 1 byte, present only for auditable addresses (serialisation version >= 1) +- `checksum` is the first 4 bytes of `Keccak-256(prefix || keys [|| flags])` + +The CryptoNote base58 encoding splits the input into 8-byte blocks (last block may be shorter) and encodes each independently, producing 11 characters per 8-byte block. + +### Address Prefix Table + +| Type | Prefix | Starts with | Auditable | Integrated | +|------|--------|-------------|-----------|------------| +| Standard | `0x1eaf7` | `iTHN` | No | No | +| Integrated | `0xdeaf7` | `iTHn` | No | Yes | +| Auditable | `0x3ceff7` | `iThN` | Yes | No | +| Auditable integrated | `0x8b077` | `iThn` | Yes | Yes | + +Integrated addresses embed a payment ID within the address itself, eliminating the need for a separate payment ID field in the transaction. + +## Extra Field Types + +The `extra` array in a transaction can contain any of the following variant types: + +| Type | Description | +|------|-------------| +| `tx_service_attachment` | Service-specific data (ID, instruction, body, flags) | +| `tx_comment` | Human-readable comment | +| `tx_payer` | Sender's address (for receiver identification) | +| `tx_receiver` | Receiver's address | +| `tx_derivation_hint` | Hint for key derivation | +| `tx_crypto_checksum` | Encrypted key derivation for sender decryption | +| `extra_alias_entry` | Alias registration or update | +| `extra_user_data` | Arbitrary user data | +| `zarcanum_tx_data_v1` | Zarcanum-specific: explicit fee field | +| `asset_descriptor_operation` | Asset register/emit/update/burn | +| `etc_tx_details_unlock_time` | Per-tx unlock time | +| `etc_tx_details_unlock_time2` | Per-output unlock times | +| `etc_tx_details_expiration_time` | Transaction expiration | +| `etc_tx_details_flags` | Transaction flags (e.g. separate signature mode) | +| `etc_tx_time` | Real timestamp for PoS blocks | +| `crypto::public_key` | Transaction public key | +| `extra_attachment_info` | Attachment hash and size | +| `extra_padding` | Padding bytes | diff --git a/Development-Phases.md b/Development-Phases.md new file mode 100644 index 0000000..280116d --- /dev/null +++ b/Development-Phases.md @@ -0,0 +1,221 @@ +# Development Phases + +The `go-blockchain` package is being developed in 9 phases, from foundational types through to a fully operational node. Each phase builds on the previous and has clear deliverables and test criteria. + +## Phase 0: Config + Types + +**Status**: Active + +**Delivers**: +- `config/` package: `ChainConfig` struct with all chain parameters, `Mainnet` and `Testnet` pre-defined instances +- `config/` hardfork schedule: `HardFork` struct, `MainnetForks` and `TestnetForks` slices, `VersionAtHeight()` lookup +- `types/` package: Fundamental types (`Hash`, `PublicKey`, `SecretKey`, `KeyImage`, `Signature` as `[32]byte` / `[64]byte` aliases) +- `types/` address: `AccountPublicAddress` struct, base58 encode/decode with Keccak-256 checksum, prefix validation +- `types/` block and transaction structs: `BlockHeader`, `Block`, `TransactionPrefix`, `Transaction`, input/output variant types +- `wire/` varint: CryptoNote varint encoding (7-bit, MSB continuation) +- `difficulty/` initial: LWMA difficulty calculation stub with test vectors +- Wiki pages populated + +**Dependencies**: None (stdlib only). + +**Test criteria**: +- `go test ./...` passes with race detector +- `go vet ./...` clean +- Address encode/decode round-trips match C++ output +- Config constants match `currency_config.h.in` + `default.cmake` exactly +- Varint encoding matches CryptoNote reference vectors + +## Phase 1: Wire Format + Serialisation + +**Delivers**: +- `wire/` package: Consensus-critical binary serialisation for all block and transaction types +- Serialisation must be **bit-identical** to C++ output for the same input +- Variant type serialisation (tagged unions for inputs, outputs, signatures, extras) +- Block hash computation (header hash + miner tx hash + Merkle root) +- Transaction hash computation (prefix hash) + +**Dependencies**: Phase 0 (types, config). + +**Test criteria**: +- Serialise/deserialise actual mainnet block hex blobs and verify round-trip +- Serialise/deserialise actual mainnet transaction hex blobs +- Computed block and transaction hashes match C++ node output +- Tree hash for Merkle root matches reference vectors + +## Phase 2: CGo Crypto Bridge + +**Delivers**: +- Build system for `libcryptonote` from cleaned C++ source +- `crypto/` package with CGo wrappers: + - Hash functions: `cn_fast_hash` (Keccak-256), `tree_hash` + - Key derivation: `generate_key_derivation`, `derive_public_key`, `derive_secret_key` + - Stealth addresses: one-time key generation and detection + - Key images: `generate_key_image` + - Ring signature verification: classic CryptoNote (`check_ring_signature`) +- Build tags: `//go:build cgo` for real crypto, stubs without +- Memory-safe wrappers (no C pointers leak to Go heap) + +**Dependencies**: Phase 0 (types). + +**Test criteria**: +- Key derivation output matches C++ for known test vectors +- Key image generation matches C++ for known keypairs +- Ring signature verification accepts valid sigs, rejects invalid +- No memory leaks under `-race` and CGo sanitiser + +## Phase 3: RPC Client + +**Delivers**: +- `rpc/` package: JSON-RPC 2.0 client for daemon and wallet APIs +- Daemon client: `getinfo`, `getheight`, `getblocktemplate`, `submitblock`, `gettransactions`, `getblockheaderbyheight`, `getblockheaderbyhash` +- Wallet client: `getbalance`, `getaddress`, `transfer` +- Binary endpoint support for fast sync (`getblocks.bin`) +- Integration with the `core` CLI: `core chain status`, `core chain info` + +**Dependencies**: Phase 0 (types, config), Phase 1 (wire, for binary endpoints). + +**Test criteria**: +- Successful RPC calls against a running C++ testnet node +- Correct deserialisation of all response types +- Error handling for connection failures and invalid responses + +## Phase 4: Difficulty + Consensus Rules + +**Delivers**: +- `difficulty/` package: Full LWMA difficulty algorithm for both PoW and PoS +- `consensus/` package: + - Block reward calculation (fixed 1 LTHN) + - Fee policy (0.01 LTHN default, fee burn) + - Block validation rules per hardfork version + - Timestamp validation (median check, future limit) + - Transaction validation rules (input/output counts, version checks, decoy set size) + +**Dependencies**: Phase 0 (config, types), Phase 1 (wire), Phase 2 (crypto for hash verification). + +**Test criteria**: +- Difficulty calculation matches C++ output for first 1,000 mainnet blocks +- Block reward returns correct value at all hardfork boundaries +- Timestamp validation accepts/rejects correctly against median window +- Fee policy matches C++ node behaviour + +## Phase 5: P2P Protocol + +**Delivers**: +- `p2p/` package: Levin binary protocol implementation + - 33-byte header encoding/decoding + - Epee portable storage serialisation for payloads + - `COMMAND_HANDSHAKE` (1001): connection establishment with network ID and sync data + - `COMMAND_TIMED_SYNC` (1002): periodic state exchange + - `COMMAND_PING` (1003): connectivity verification + - `NOTIFY_NEW_BLOCK` (2001): block propagation + - `NOTIFY_OR_INVOKE_NEW_TRANSACTIONS` (2002): transaction propagation + - `NOTIFY_REQUEST_GET_OBJECTS` (2003) + `NOTIFY_RESPONSE_GET_OBJECTS` (2004): object fetch + - `NOTIFY_REQUEST_CHAIN` (2006) + `NOTIFY_RESPONSE_CHAIN_ENTRY` (2007): chain sync +- Peer list management (white list, grey list, 70% preference) +- IP blocking after 10 failures (24-hour block) +- Connection lifecycle management (timeouts, idle kill) + +**Dependencies**: Phase 0 (config, types), Phase 1 (wire). + +**Test criteria**: +- Successful handshake with a C++ node +- Receive and parse new block notifications +- Chain sync downloads at least 100 blocks from a C++ peer +- Peer list grows via handshake exchanges +- Invalid handshakes (wrong network ID) are rejected + +## Phase 6: Blockchain Storage + +**Delivers**: +- `chain/` package: Persistent blockchain database + - Block and transaction storage (LMDB or Pebble backend, behind interface) + - Output index: global output index mapping + - Key image tracking: spent/unspent state + - Chain state: current height, top block hash, cumulative difficulty + - Chain reorganisation: detect and switch to a heavier chain + - Checkpoint system for fast initial sync + - Alternative block tracking (max `CURRENCY_ALT_BLOCK_MAX_COUNT` = 43,200) + +**Dependencies**: Phase 0-2 (types, wire, crypto), Phase 4 (consensus for validation). + +**Test criteria**: +- Store and retrieve 10,000 blocks without data loss +- Key image double-spend detection works correctly +- Chain reorg correctly switches to a heavier fork +- Database survives crash recovery (write-ahead log) + +## Phase 7: Wallet + +**Delivers**: +- `wallet/` package: + - Account key generation: seed phrase (mnemonic) to spend key + view key derivation + - Output scanning: using view key to detect owned outputs in blocks + - Balance calculation: sum of unspent, owned outputs + - Transaction construction: + - Input selection (age-based, amount-based) + - Decoy ring construction (random output selection via RPC) + - Output generation (stealth addresses) + - Fee calculation + - Signing via CGo crypto bridge (NLSAG for v1, ZC_sig/CLSAG for v2+) + - Wallet file encryption (ChaCha8) + - Payment ID handling (standard and integrated addresses) + - Auditable wallet support + +**Dependencies**: Phase 0-2 (types, wire, crypto), Phase 3 (RPC for output selection), Phase 4 (consensus for fee policy). + +**Test criteria**: +- Seed phrase generates identical keys to C++ wallet +- Output scanning detects all owned outputs in test blocks +- Constructed transactions are accepted by a C++ node +- Wallet file encrypts and decrypts correctly + +## Phase 8: Full Node + +**Delivers**: +- Complete integration: P2P + chain storage + RPC server + mempool + wallet +- CLI commands: + - `core chain serve` -- Run a full node (P2P + RPC) + - `core chain mine` -- PoW mining + - `core chain stake` -- PoS staking + - `core wallet create` -- Create new wallet + - `core wallet balance` -- Show balance + - `core wallet transfer` -- Send funds + - `core wallet stake` -- Delegate stake +- Mempool management: + - Transaction validation before acceptance + - Expiration handling (`CURRENCY_MEMPOOL_TX_LIVETIME` = 4 days) + - Fee-based prioritisation +- Block template construction (for both PoW and PoS) +- Full chain sync from genesis against C++ network +- Checkpoint verification + +**Dependencies**: All prior phases. + +**Test criteria**: +- Go node syncs fully with the C++ testnet +- Go node mines a valid PoW block accepted by C++ peers +- Go node stakes a valid PoS block accepted by C++ peers +- Go wallet sends a transaction accepted by C++ nodes +- Go node serves RPC requests compatible with existing tooling + +## Phase Dependency Graph + +``` +Phase 0: Config + Types + | + +--- Phase 1: Wire Format + | | + | +--- Phase 3: RPC Client + | | | + | +--- Phase 5: P2P Protocol + | | + +--- Phase 2: CGo Crypto Bridge + | + +--- Phase 4: Difficulty + Consensus + | | + | +--- Phase 6: Blockchain Storage + | + +--- Phase 7: Wallet + | + +--- Phase 8: Full Node (integrates all) +``` diff --git a/Hardfork-Schedule.md b/Hardfork-Schedule.md new file mode 100644 index 0000000..3f2452b --- /dev/null +++ b/Hardfork-Schedule.md @@ -0,0 +1,54 @@ +# Hardfork Schedule + +The Lethean chain defines 7 hardforks (HF0 through HF6), totalling `ZANO_HARDFORKS_TOTAL = 7`. Heights are specified as "after height", meaning the hardfork activates at height N+1. + +## Genesis + +| Parameter | Value | +|-----------|-------| +| Genesis timestamp | 2026-02-12 12:00 UTC | +| Unix timestamp | `1770897600` | +| Genesis nonce | `CURRENCY_FORMATION_VERSION + 101011010121` | +| Genesis block major version | 1 | +| Genesis block minor version | 0 | + +## Hardfork Table + +| HF | ID | Mainnet height | Testnet height | Block major version | What changes | +|----|-----|---------------|----------------|--------------------:|-------------| +| HF0 | `ZANO_HARDFORK_00_INITAL` | 0 (genesis) | 0 | 0/1 | CryptoNote base protocol. Hybrid PoW/PoS consensus from block 0. Classic ring signatures (NLSAG). Transparent amounts. Transaction version 0-1. | +| HF1 | `ZANO_HARDFORK_01` | 10,080 | 0 | 1 | New transaction types. Enables HTLC (hash time-locked contracts), multisig inputs/outputs, and service attachments. ~7 days after launch. | +| HF2 | `ZANO_HARDFORK_02` | 10,080 | 10 | 1 | Block time adjustment. Activates alongside HF1 on mainnet. On testnet, activates independently at height 10 for testing. | +| HF3 | `ZANO_HARDFORK_03` | 999,999,999 | 0 | 2 | Block version 2. Increments `major_version` to 2 (`HF3_BLOCK_MAJOR_VERSION`). Preparation for Zarcanum. Future activation on mainnet. | +| HF4 | `ZANO_HARDFORK_04_ZARCANUM` | 999,999,999 | 100 | 3 | **Zarcanum privacy upgrade.** Confidential transactions (hidden amounts). Stealth outputs (`tx_out_zarcanum`). CLSAG ring signatures (GG, GGX, GGXXG variants). Bulletproofs+ range proofs. Mandatory decoy set increased from 10 to 15. Minimum 2 outputs per transaction. Transaction version 2. Minimum coinage of 10 blocks for staking. 60-block transaction freeze period before hardfork activation (from HF5 onwards). | +| HF5 | `ZANO_HARDFORK_05` | 999,999,999 | 200 | 3 | **Confidential assets.** Asset deployment, emission, update, and burn operations. Asset surjection proofs (BGE). Transaction version 3 with `hardfork_id` field. Minimum build version 601 (mainnet) / 2 (testnet). | +| HF6 | `ZANO_HARDFORK_06` | 999,999,999 | 999,999,999 | 3 | **Block time halving.** PoW and PoS targets double from 120s to 240s. Blocks per day halve from ~1440 to ~720. Effectively halves the emission rate without changing the per-block reward. Minimum build version 601 (mainnet) / 2 (testnet). Reserved for future activation. | + +## Transaction Version Progression + +| Transaction version | Constant | Introduced | Description | +|--------------------|----------|------------|-------------| +| 0 | `TRANSACTION_VERSION_INITAL` | Genesis | Original CryptoNote format | +| 1 | `TRANSACTION_VERSION_PRE_HF4` | HF1 | Extended format with HTLC, multisig | +| 2 | `TRANSACTION_VERSION_POST_HF4` | HF4 | Zarcanum confidential transactions | +| 3 | `TRANSACTION_VERSION_POST_HF5` | HF5 | Confidential assets, hardfork ID field | + +## Block Version Progression + +| Block major version | Constant | Hardfork | Description | +|--------------------|----------|----------|-------------| +| 0 | `BLOCK_MAJOR_VERSION_INITIAL` | Pre-HF1 | Initial version | +| 1 | `HF1_BLOCK_MAJOR_VERSION` | HF1 | After first hardfork | +| 2 | `HF3_BLOCK_MAJOR_VERSION` | HF3 | Block format v2 | +| 3 | `CURRENT_BLOCK_MAJOR_VERSION` | HF4+ | Current format | + +## Pre-Hardfork Transaction Freeze + +Starting from HF5, a transaction freeze period of `CURRENCY_PRE_HARDFORK_TX_FREEZE_PERIOD = 60` blocks applies before each hardfork activation. During this window, no new transactions (other than coinbase) are accepted into the mempool. This ensures the chain stabilises before consensus rule changes take effect. + +## Notes + +- Heights `999,999,999` indicate future activation. These hardforks are defined in code but not yet scheduled for mainnet. +- On testnet, HF1 and HF3 activate at genesis (height 0), allowing immediate testing of all features. +- HF4 (`ZANO_HARDFORK_04_TIMESTAMP_ACTUAL`) references the genesis timestamp `1770897600` for Zarcanum proof initialisation. +- HF1 and HF2 share the same mainnet activation height (10,080), activating simultaneously approximately 7 days after chain launch. diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..508f211 --- /dev/null +++ b/Home.md @@ -0,0 +1,58 @@ +# go-blockchain + +`go-blockchain` is a Go reimplementation of the Lethean blockchain protocol. It provides a pure-Go implementation of chain logic, data structures, and networking, delegating only mathematically complex cryptographic operations (ring signatures, Bulletproofs+, Zarcanum proofs) to a cleaned C++ library via CGo. + +## Architecture Decision: ADR-001 + +The project follows the **Go Shell + C++ Crypto Library** pattern (ADR-001): + +- **Protocol logic** (block validation, difficulty, P2P, RPC, chain storage) is written in pure Go. +- **Cryptographic primitives** (Ed25519 ops, stealth addresses, ring signatures, range proofs) are provided by a C++ library accessed through a CGo bridge. +- This is the same bridge pattern used by the project's native MLX backend (Go to C via CGo to Metal). + +## Lineage + +``` +CryptoNote (van Saberhagen, 2013) + | +IntenseCoin (2017) + | +Lethean (2017-present) + | +Zano rebase (2025) -- privacy upgrades: Zarcanum, CLSAG, Bulletproofs+, confidential assets + | +go-blockchain -- Go reimplementation of the Zano-fork protocol +``` + +The Lethean mainnet launched on **2026-02-12** with genesis timestamp `1770897600` (12:00 UTC). The chain runs a hybrid PoW/PoS consensus with 120-second block targets. + +## Licence + +[European Union Public Licence (EUPL) version 1.2](https://joinup.ec.europa.eu/software/page/eupl/licence-eupl) + +SPDX-License-Identifier: `EUPL-1.2` + +## Module Path + +``` +forge.lthn.ai/core/go-blockchain +``` + +## Wiki Contents + +| Page | Description | +|------|-------------| +| [Architecture](Architecture) | Package structure, dependency diagram, CGo boundary | +| [Chain Parameters](Chain-Parameters) | Full configuration reference (tokenomics, prefixes, timing, limits, ports) | +| [Hardfork Schedule](Hardfork-Schedule) | All 7 hardforks with heights, dates, and changes | +| [RPC Reference](RPC-Reference) | Daemon (~40 methods) and wallet (~35 methods) API documentation | +| [Crypto Primitives](Crypto-Primitives) | What the C++ bridge provides: signatures, proofs, hashes | +| [Data Structures](Data-Structures) | Field-level documentation of blocks, transactions, addresses | +| [P2P Protocol](P2P-Protocol) | Levin wire format, command IDs, peer management | +| [Development Phases](Development-Phases) | 9-phase roadmap from config through to full node | + +## Source References + +- **C++ chain**: [Lethean blockchain](https://github.com/letheanVPN/blockchain) (239 files, ~37K lines) +- **Upstream**: [Zano Project](https://zano.org) (privacy protocol basis) +- **CryptoNote**: Original protocol by Nicolas van Saberhagen diff --git a/P2P-Protocol.md b/P2P-Protocol.md new file mode 100644 index 0000000..b14abc7 --- /dev/null +++ b/P2P-Protocol.md @@ -0,0 +1,330 @@ +# P2P Protocol + +The Lethean P2P network uses the **Levin protocol**, a binary TCP protocol inherited from the CryptoNote/epee library. All peer-to-peer communication (handshakes, block/tx propagation, chain sync) uses this wire format. + +## Levin Wire Format + +Every message is prefixed with a 33-byte header (`bucket_head2`): + +``` +Offset Size Field Description +------ ---- ----- ----------- +0 8 m_signature Magic: 0x0101010101012101 (little-endian) +8 8 m_cb Payload length in bytes (little-endian) +16 1 m_have_to_return Boolean: expects a response +17 4 m_command Command ID (little-endian uint32) +21 4 m_return_code Return code (little-endian int32) +25 4 m_flags Packet type flags (little-endian uint32) +29 4 m_protocol_version Protocol version (little-endian uint32) +``` + +**Total header size: 33 bytes** (packed, no padding). + +### Constants + +``` +LEVIN_SIGNATURE = 0x0101010101012101 +LEVIN_PACKET_REQUEST = 0x00000001 +LEVIN_PACKET_RESPONSE = 0x00000002 +LEVIN_PROTOCOL_VER_0 = 0 +LEVIN_PROTOCOL_VER_1 = 1 +``` + +### Packet Types + +| Flag value | Meaning | +|------------|---------| +| `0x00000001` | Request (expects a response if `m_have_to_return` is true) | +| `0x00000002` | Response to a prior request | + +### Header validation + +On receiving a message, a node: +1. Reads the first 8 bytes and verifies they match `LEVIN_SIGNATURE`. +2. Reads the remaining 25 bytes of the header. +3. Validates `m_cb` does not exceed `P2P_DEFAULT_PACKET_MAX_SIZE` (50 MB). +4. Reads `m_cb` bytes of payload. +5. Dispatches based on `m_command`. + +## Payload Serialisation + +Payloads are serialised using the **epee portable storage** binary format (key-value serialisation). This is a TLV-style format supporting nested objects, arrays, integers, strings, and binary blobs. It is distinct from the consensus binary serialisation used for blocks and transactions. + +## Command IDs + +Commands are divided into two pools: + +### P2P Commands (base 1000) + +| Command | ID | Type | Description | +|---------|-----|------|-------------| +| `COMMAND_HANDSHAKE` | 1001 | Request/Response | Initial peer connection. Exchanges node data, sync payload, and peer lists | +| `COMMAND_TIMED_SYNC` | 1002 | Request/Response | Periodic sync. Exchanges current chain state and updated peer lists | +| `COMMAND_PING` | 1003 | Request/Response | Connectivity check. Verifies peer is reachable for inbound connections | +| `COMMAND_REQUEST_STAT_INFO` | 1004 | Request/Response | Debug: request node statistics (requires proof of trust) | + +### Blockchain Commands (base 2000) + +| Command | ID | Type | Description | +|---------|-----|------|-------------| +| `NOTIFY_NEW_BLOCK` | 2001 | Notification | Propagate a newly mined/staked block to peers | +| `NOTIFY_OR_INVOKE_NEW_TRANSACTIONS` | 2002 | Request/Response | Propagate new transactions. Can be notification or invoke | +| `NOTIFY_REQUEST_GET_OBJECTS` | 2003 | Notification | Request specific blocks and/or transactions by hash | +| `NOTIFY_RESPONSE_GET_OBJECTS` | 2004 | Notification | Response with requested blocks and transactions | +| `NOTIFY_REQUEST_CHAIN` | 2006 | Notification | Request chain skeleton (block IDs for sync) | +| `NOTIFY_RESPONSE_CHAIN_ENTRY` | 2007 | Notification | Response with chain block IDs and heights | + +**Note**: Command IDs 2005 is unused (gap in the sequence). + +## Handshake Protocol + +### Connection Establishment + +1. **Initiator** connects via TCP and sends `COMMAND_HANDSHAKE` (1001) request. +2. **Responder** validates the request and sends a response. +3. Both sides begin periodic `COMMAND_TIMED_SYNC` (1002) exchanges. + +### Handshake Request + +``` +COMMAND_HANDSHAKE request { + node_data { + network_id: uuid // 16-byte network identifier (derived from CURRENCY_FORMATION_VERSION) + peer_id: uint64 // Random peer identifier + local_time: int64 // Node's local Unix timestamp + my_port: uint32 // Listening port for inbound connections + } + payload_data { + current_height: uint64 // Chain height (top block + 1) + top_id: hash // Hash of the top block + last_checkpoint_height: uint64 // Height of the last known checkpoint + core_time: uint64 // Core time + client_version: string // Software version string + non_pruning_mode_enabled: bool // Whether full block data is available + } + maintrs_entry { + maintainers_info_buff: blob // Signed maintainer info + sign: signature // Ed25519 signature + } +} +``` + +### Handshake Response + +``` +COMMAND_HANDSHAKE response { + node_data { + network_id: uuid + peer_id: uint64 + local_time: int64 + my_port: uint32 + } + payload_data { + current_height: uint64 + top_id: hash + last_checkpoint_height: uint64 + core_time: uint64 + client_version: string + non_pruning_mode_enabled: bool + } + local_peerlist: []peerlist_entry // Known peers (as binary blob) + maintrs_entry { + maintainers_info_buff: blob + sign: signature + } +} +``` + +### Handshake Validation + +The responder rejects the handshake if: +- `network_id` does not match (different chain or testnet/mainnet mismatch) +- `client_version` is below minimum required version +- Maintainer entry signature is invalid +- The peer ID is already connected (duplicate connection) +- The connection is not inbound (handshake must come from the connecting side) + +## Timed Sync + +After handshake, peers exchange `COMMAND_TIMED_SYNC` (1002) every `P2P_DEFAULT_HANDSHAKE_INTERVAL` (60 seconds): + +``` +COMMAND_TIMED_SYNC request { + payload_data { ... } // Current chain state (same as handshake payload) + maintrs_entry { ... } // Maintainer entry +} + +COMMAND_TIMED_SYNC response { + local_time: int64 + payload_data { ... } + local_peerlist: []peerlist_entry + maintrs_entry { ... } +} +``` + +This keeps peers informed of each other's chain state and propagates peer list updates. + +## Block Propagation + +When a node mines or stakes a new block: + +``` +NOTIFY_NEW_BLOCK (2001) { + b { + block: blob // Serialised block + txs: []blob // Serialised transactions + coinbase_global_outs: []uint64 // Global output indices for coinbase + tx_global_outs: [][]uint64 // Global output indices per tx + } + current_blockchain_height: uint64 // Sender's chain height +} +``` + +This is a notification (no response expected). The receiving node validates the block and, if accepted, relays it to its own peers. + +## Transaction Propagation + +New transactions are propagated via: + +``` +NOTIFY_OR_INVOKE_NEW_TRANSACTIONS (2002) { + txs: []blob // Serialised transaction blobs +} +``` + +This command can function as both a notification and an invocation (request/response), as indicated by the `m_have_to_return` header flag. When invoked, the response contains a status code. + +Up to `CURRENCY_RELAY_TXS_MAX_COUNT` (5) transactions are relayed per message. + +## Chain Synchronisation + +### Requesting the Chain Skeleton + +To sync, a node sends its known block IDs in a sparse pattern: + +``` +NOTIFY_REQUEST_CHAIN (2006) { + block_ids: []hash // First 10 sequential, then 2^n offsets, genesis last +} +``` + +The block ID list follows the CryptoNote sparse sync pattern: +- The 10 most recent block hashes +- Then every 2nd, 4th, 8th, 16th, 32nd, etc. +- Always ending with the genesis block hash + +### Chain Response + +``` +NOTIFY_RESPONSE_CHAIN_ENTRY (2007) { + start_height: uint64 // Height of the first block in response + total_height: uint64 // Peer's total chain height + m_block_ids: []block_context_info // Block hashes with context +} +``` + +### Fetching Blocks and Transactions + +After receiving the chain skeleton, the syncing node requests full blocks: + +``` +NOTIFY_REQUEST_GET_OBJECTS (2003) { + txs: []hash // Transaction hashes to fetch + blocks: []hash // Block hashes to fetch +} + +NOTIFY_RESPONSE_GET_OBJECTS (2004) { + txs: []blob // Transaction blobs + blocks: []block_complete_entry // Full blocks with txs + missed_ids: []hash // Hashes not found + current_blockchain_height: uint64 // Sender's height +} +``` + +### Sync limits + +| Parameter | Value | Description | +|-----------|-------|-------------| +| `BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT` | 2,000 | Block IDs per chain request | +| `BLOCKS_SYNCHRONIZING_DEFAULT_COUNT` | 200 | Blocks per download batch | +| `BLOCKS_SYNCHRONIZING_DEFAULT_SIZE` | 2,000,000 | Max bytes per sync packet (2 MB) | +| `CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT` | 500 | Max blocks per get_objects | +| `CURRENCY_PROTOCOL_MAX_TXS_REQUEST_COUNT` | 500 | Max txs per get_objects | + +## Peer Management + +### Peer Lists + +Nodes maintain two peer lists: + +| List | Max size | Description | +|------|----------|-------------| +| **White list** | 1,000 (`P2P_LOCAL_WHITE_PEERLIST_LIMIT`) | Verified peers that have completed a successful handshake and responded to a ping | +| **Grey list** | 5,000 (`P2P_LOCAL_GRAY_PEERLIST_LIMIT`) | Peers received from other nodes' peer lists but not yet verified | + +### Peer List Entry + +``` +peerlist_entry { + adr { + ip: uint32 // IPv4 address (network byte order) + port: uint32 // Port number + } + id: uint64 // Peer ID + last_seen: int64 // Unix timestamp of last contact +} +``` + +### Connection Strategy + +| Parameter | Value | Description | +|-----------|-------|-------------| +| `P2P_DEFAULT_CONNECTIONS_COUNT` | 8 | Target outbound connections | +| `P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT` | 70% | Fraction from white list | +| `P2P_DEFAULT_PEERS_IN_HANDSHAKE` | 250 | Max peers exchanged in handshake | + +When establishing outbound connections: +- 70% of connections are made to white list peers (verified) +- 30% of connections are made to grey list peers (unverified) +- Each successful connection promotes the peer from grey to white list + +### Failure Handling + +| Parameter | Value | Description | +|-----------|-------|-------------| +| `P2P_IP_FAILS_BEFOR_BLOCK` | 10 | Connection failures before blocking | +| `P2P_IP_BLOCKTIME` | 86,400 seconds | Block duration (24 hours) | +| `P2P_FAILED_ADDR_FORGET_SECONDS` | 300 seconds | Forget failed address after 5 minutes | +| `P2P_IDLE_CONNECTION_KILL_INTERVAL` | 300 seconds | Kill idle connections every 5 minutes | + +After 10 consecutive connection failures to the same IP address, that IP is blocked for 24 hours. Failed addresses are forgotten after 5 minutes, allowing retry. Idle connections with no traffic are terminated every 5 minutes. + +### Ping Verification + +Before adding a peer to the white list, the node performs a ping check: + +1. Connect to the peer's advertised IP:port. +2. Send `COMMAND_PING` (1003). +3. Verify the response contains `status: "OK"` and a matching `peer_id`. +4. Only then promote the peer from grey to white list. + +This prevents nodes from advertising unreachable addresses. + +## Network Identity + +The network ID is a 16-byte UUID derived from `CURRENCY_FORMATION_VERSION`: + +- **Mainnet**: Formation version 84, network ID version `84 + 0 = 84` +- **Testnet**: Formation version 100, with `P2P_NETWORK_ID_TESTNET_FLAG = 0` + +Nodes reject handshakes from peers with a different network ID, preventing mainnet/testnet cross-contamination. + +## Connection Timeouts + +| Parameter | Value | Description | +|-----------|-------|-------------| +| `P2P_DEFAULT_CONNECTION_TIMEOUT` | 5,000 ms | TCP connection timeout | +| `P2P_DEFAULT_PING_CONNECTION_TIMEOUT` | 2,000 ms | Ping-specific timeout | +| `P2P_DEFAULT_INVOKE_TIMEOUT` | 120,000 ms | Command invoke timeout (2 min) | +| `P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT` | 10,000 ms | Handshake-specific timeout | +| `P2P_DEFAULT_PACKET_MAX_SIZE` | 50,000,000 | Maximum packet size (50 MB) | diff --git a/RPC-Reference.md b/RPC-Reference.md new file mode 100644 index 0000000..8e5fbf3 --- /dev/null +++ b/RPC-Reference.md @@ -0,0 +1,270 @@ +# RPC Reference + +The Lethean node exposes two RPC interfaces: a **daemon** API for blockchain queries and node control, and a **wallet** API for account management and transactions. Both use JSON-RPC 2.0 over HTTP. + +- **Daemon RPC** default ports: 36941 (mainnet), 46941 (testnet) +- **Wallet RPC** runs on a user-configured port alongside the wallet process + +## Daemon RPC Methods + +### Node Information + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `getinfo` | Comprehensive node status | `flags` (bitmask for optional fields) | `height`, `difficulty`, `tx_count`, `outgoing_connections_count`, `incoming_connections_count`, `synchronized`, `top_block_hash`, `total_coins`, `block_reward` | +| `getheight` | Current blockchain height | (none) | `height` | +| `getblockcount` | Alias for block count | (none) | `count` | + +### Block Queries + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `getblockhash` | Hash of block at height | `[height]` | block hash string | +| `getblocktemplate` | Template for mining | `wallet_address`, `extra_text` | `blocktemplate_blob`, `difficulty`, `height`, `seed` | +| `submitblock` | Submit mined block | `[block_blob]` | `status` | +| `submitblock2` | Extended block submission | `block_blob` + PoS data | `status`, `block_id` | +| `get_last_block_header` | Most recent block header | (none) | `block_header` (hash, height, timestamp, major/minor version, nonce, reward, depth, difficulty) | +| `get_block_header_by_hash` | Block header by hash | `hash` | `block_header` | +| `get_block_header_by_height` | Block header by height | `height` | `block_header` | +| `get_blocks_details` | Detailed block info (range) | `height_start`, `count` | `blocks[]` with full details | +| `get_block_details` | Single block details | `id` (hash) | `block_details` | +| `get_alt_blocks_details` | Alternative chain blocks | `offset`, `count` | `blocks[]` | + +### Transaction Queries + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `gettransactions` | Fetch txs by hash | `txs_hashes[]` | `txs_as_hex[]`, `missed_tx[]` | +| `get_tx_details` | Detailed tx information | `tx_hash` | `tx_info` (inputs, outputs, extra, fee, size) | +| `decrypt_tx_details` | Decrypt private tx data | `tx_id` or `tx_blob`, `tx_secret_key`, `outputs_addresses[]` | `decoded_outputs[]` (amount, address, asset_id) | +| `get_tx_global_outputs_indexes` | Global output indices | `txids[]` | output index arrays | +| `get_tx_global_outputs_indexes_by_amount` | Indices by amount | `amount`, `i` | output indices | +| `search_by_id` | Search blocks/txs by hash | `id` | matching block or tx details | +| `get_est_height_from_date` | Estimate height from timestamp | `timestamp` | `h` (estimated height) | + +### Transaction Pool + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `get_pool_info` | Pool status and pending aliases | (none) | `aliases_que[]` | +| `get_tx_pool` | All pool transactions | (none) | `txs[]` (blobs), `tx_expiration_ts_median` | +| `get_pool_txs_details` | Detailed pool tx info | `ids[]` | `txs[]` with full details | +| `get_pool_txs_brief_details` | Brief pool tx summaries | `ids[]` | `txs[]` brief info | +| `get_all_pool_tx_list` | List all pool tx hashes | (none) | `ids[]` | +| `get_current_core_tx_expiration_median` | Expiration median timestamp | (none) | `expiration_median` | + +### Key Images + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `check_keyimages` | Check spent status | `images[]` | `images_stat[]` (1=unspent, 0=spent) | + +### Output Selection + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `get_random_outs` | Random outputs for mixing | `amounts[]`, `outs_count` | `outs[]` with global indices and keys | +| `get_random_outs3` | Version 3 random outputs | `amounts[]`, `outs_count`, `use_forced_mix_outs` | `outs[]` | +| `get_multisig_info` | Multisig output details | `ms_id` | multisig output info | +| `get_global_index_info` | Global output index stats | `asset_id` | `amount_and_count[]` | + +### Address and Alias Operations + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `get_alias_details` | Resolve alias to address | `alias` | `alias_details` (address, comment) | +| `get_alias_reward` | Cost to register alias | `alias` | `reward` | +| `get_all_aliases` | List all registered aliases | (none) | `aliases[]` | +| `get_aliases` | Paginated alias list | `offset`, `count` | `aliases[]` | +| `get_aliases_by_address` | Aliases for an address | `address` | `alias` | +| `get_integrated_address` | Create integrated address | `payment_id`, `regular_address` | `integrated_address`, `payment_id` | + +### Asset Operations + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `get_asset_info` | Asset details by ID | `asset_id` | `asset_descriptor` (ticker, name, supply, owner) | +| `get_assets_list` | List registered assets | `offset`, `count` | `assets[]` | + +### Mining Control + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `start_mining` | Start PoW mining | `miner_address`, `threads_count` | `status` | +| `stop_mining` | Stop PoW mining | (none) | `status` | +| `get_pos_mining_details` | PoS staking details | stake entries | `pos_basic_data` | + +### Voting + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `get_votes` | Vote results in block range | `h_start`, `h_end` | `votes` | + +### Pool Management + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `reset_tx_pool` | Clear transaction pool | (none) | `status` | +| `remove_tx_from_pool` | Remove specific tx | `tx_id` | `status` | + +### Raw Transaction + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `sendrawtransaction` | Broadcast raw tx | `tx_as_hex` | `status` | +| `force_relay` | Force relay tx blobs | `txs_as_hex[]` | `status` | + +### Block Sync (Fast) + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `getblocks.bin` | Fast block sync (binary) | `block_ids[]`, `minimum_height` | `blocks[]`, `start_height`, `current_height` | +| `find_outs_in_recent_blocks` | Scan recent blocks for outputs | `address`, `viewkey`, `blocks_limit` | `outputs[]` | + +### Marketplace + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `get_offers_ex` | Query marketplace offers | filter criteria | `offers[]` | + +## Wallet RPC Methods + +### Wallet State + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `getbalance` | Account balance | (none) | `balance`, `unlocked_balance` | +| `getaddress` | Wallet address | (none) | `address` | +| `get_wallet_info` | Wallet metadata | (none) | wallet info (address, path, height, etc.) | +| `get_wallet_restore_info` | Seed phrase for backup | (none) | `seed_phrase` | +| `get_seed_phrase_info` | Validate a seed phrase | `seed_phrase` | validation result | +| `store` | Save wallet to disk | (none) | `status` | +| `force_rescan_tx_pool` | Rescan pool for wallet | (none) | `status` | + +### Transfers and Payments + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `transfer` | Send LTHN | `destinations[]` (address, amount), `fee`, `mixin_count`, `payment_id`, `comment` | `tx_hash`, `tx_unsigned_hex` | +| `get_payments` | Payments by payment ID | `payment_id` | `payments[]` | +| `get_bulk_payments` | Payments for multiple IDs | `payment_ids[]`, `min_block_height` | `payments[]` | +| `get_recent_txs_and_info` | Recent transaction history | `offset`, `count`, `update_provision_info` | `transfers[]`, `total_transfers` | +| `search_for_transactions` | Search wallet transactions | `tx_id`, `in`, `out`, `pool`, `filter_by_height` | `in[]`, `out[]`, `pool[]` | +| `get_mining_history` | Staking/mining rewards | (none) | mining history | + +### Address Utilities + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `make_integrated_address` | Create integrated address | `payment_id` | `integrated_address`, `payment_id` | +| `split_integrated_address` | Decode integrated address | `integrated_address` | `standard_address`, `payment_id` | + +### Alias Management + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `register_alias` | Register new alias | `alias`, `address` | `tx_hash` | +| `update_alias` | Update alias details | `alias`, `address` | `tx_hash` | + +### Offline Signing + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `sign_transfer` | Sign an unsigned tx | `tx_unsigned_hex` | `tx_signed_hex`, `tx_hash` | +| `submit_transfer` | Broadcast signed tx | `tx_signed_hex` | `tx_hash` | + +### Output Management + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `sweep_below` | Consolidate small outputs | `address`, `amount`, `fee` | `tx_hash`, `amount_swept` | +| `get_bare_outs_stats` | Statistics of bare outputs | (none) | output stats | +| `sweep_bare_outs` | Convert bare outputs | (none) | `tx_hash` | + +### HTLC (Hash Time-Locked Contracts) + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `create_htlc_proposal` | Create HTLC proposal | `destination`, `amount`, `lock_blocks`, `htlc_hash` | `tx_hash` | +| `get_list_of_active_htlc` | List active HTLCs | (none) | `htlcs[]` | +| `redeem_htlc` | Redeem HTLC with preimage | `tx_id`, `origin` | `tx_hash` | +| `check_htlc_redeemed` | Check HTLC redemption | `tx_id` | redeemed status | + +### Ionic Swaps + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `ionic_swap_generate_proposal` | Create swap proposal | `destination`, `amount`, `desired_amount`, `desired_asset_id` | `hex_raw_proposal` | +| `ionic_swap_get_proposal_info` | Decode swap proposal | `hex_raw_proposal` | proposal details | +| `ionic_swap_accept_proposal` | Accept and execute swap | `hex_raw_proposal` | `tx_hash` | + +### Asset Operations + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `assets_deploy` | Register new asset | `asset_descriptor` (ticker, name, supply, decimal_point) | `tx_hash`, `asset_id` | +| `assets_emit` | Emit additional supply | `asset_id`, `amount` | `tx_hash` | +| `assets_update` | Update asset metadata | `asset_id`, `asset_descriptor` | `tx_hash` | +| `assets_burn` | Burn asset supply | `asset_id`, `amount` | `tx_hash` | +| `assets_whitelist_get` | Get whitelisted assets | (none) | `assets[]` | +| `assets_whitelist_add` | Whitelist an asset | `asset_id` | `status` | +| `assets_whitelist_remove` | Remove from whitelist | `asset_id` | `status` | + +### Escrow Contracts + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `contracts_send_proposal` | Send escrow proposal | contract details | `tx_hash` | +| `contracts_accept_proposal` | Accept escrow proposal | `contract_id` | `tx_hash` | +| `contracts_get_all` | List all contracts | (none) | `contracts[]` | +| `contracts_release` | Release escrow funds | `contract_id` | `tx_hash` | +| `contracts_request_cancel` | Request cancellation | `contract_id` | `tx_hash` | +| `contracts_accept_cancel` | Accept cancellation | `contract_id` | `tx_hash` | + +### Marketplace + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `marketplace_get_my_offers` | List own offers | filter criteria | `offers[]` | +| `marketplace_push_offer` | Create offer | offer details | `tx_hash` | +| `marketplace_push_update_offer` | Update offer | offer details | `tx_hash` | +| `marketplace_cancel_offer` | Cancel offer | `offer_id` | `tx_hash` | + +### Cryptographic Utilities + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `sign_message` | Sign arbitrary message | `buff` | `sig` | +| `encrypt_data` | Encrypt data | `buff` | `encrypted_buff` | +| `decrypt_data` | Decrypt data | `encrypted_buff` | `buff` | + +### Multi-Wallet + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `mw_get_wallets` | List managed wallets | (none) | `wallets[]` | +| `mw_select_wallet` | Switch active wallet | `wallet_id` | `status` | + +### Proxy + +| Method | Description | Key parameters | Key returns | +|--------|-------------|---------------|-------------| +| `proxy_to_daemon` | Forward request to daemon | `body` | daemon response | + +## Binary Endpoints + +Some daemon methods use binary (non-JSON) serialisation for performance. These use the epee portable storage format: + +| Endpoint | Description | +|----------|-------------| +| `/getblocks.bin` | Fast block sync | +| `/get_o_indexes.bin` | Output global indices | +| `/getrandom_outs.bin` | Random outputs for ring construction | +| `/get_random_outs3.bin` | Version 3 random outputs | + +## Wire Format Notes + +- **Daemon JSON-RPC**: Standard JSON-RPC 2.0 at `/json_rpc`. Methods are called via `{"method": "getinfo", "params": {...}}`. +- **Wallet JSON-RPC**: Same format at `/json_rpc` on the wallet RPC port. +- **P2P protocol**: Uses the Levin binary protocol (see [P2P Protocol](P2P-Protocol)), not JSON-RPC. +- **Binary endpoints**: Use epee portable storage binary serialisation, accessed via direct HTTP POST to the endpoint path.