Local difficulty computation for P2P sync — replaces hardcoded
difficulty=0 with LWMA-based calculation from stored block history.
Co-Authored-By: Charon <charon@lethean.io>
LevinP2PConn wraps a levin.Connection to implement the P2PConnection
interface, handling timed_sync keep-alive responses automatically.
Integration test syncs the full testnet chain (2577 blocks) via P2P
in under 5 seconds.
Co-Authored-By: Charon <charon@lethean.io>
RESPONSE_CHAIN_ENTRY includes the fork-point block as its first
entry. The sync loop now skips blocks already stored to avoid
height validation failures on subsequent chain iterations.
Co-Authored-By: Charon <charon@lethean.io>
SparseChainHistory returned a zero hash when the chain was empty,
which the daemon could not resolve. Send the genesis hash instead
so the peer can locate the fork point and respond with chain entries.
Co-Authored-By: Charon <charon@lethean.io>
Performs handshake, REQUEST_CHAIN with genesis hash, reads
RESPONSE_CHAIN_ENTRY, then REQUEST_GET_OBJECTS with the first block
hash and verifies RESPONSE_GET_OBJECTS returns a non-empty block blob.
Also fixes the existing handshake test return code check — the C++
daemon handler returns 1 (not 0) on success.
Co-Authored-By: Charon <charon@lethean.io>
Three bugs found by integration testing against the C++ testnet daemon:
1. NetworkIDMainnet/Testnet had byte 10 swapped — the C++ #ifndef TESTNET
branch (mainnet) sets P2P_NETWORK_ID_TESTNET_FLAG=1, and the #else
(testnet) sets it to 0. Counter-intuitive but matches compiled binaries.
2. ClientVersion format "Lethean/go-blockchain 0.1.0" was rejected by the
daemon's parse_client_version which expects "major.minor.rev.build[commit]".
Changed to "6.0.1.2[go-blockchain]".
3. RequestChain, RequestGetObjects, and ResponseGetObjects used StringArrayVal
for hash fields, but the C++ daemon uses KV_SERIALIZE_CONTAINER_POD_AS_BLOB
which packs all 32-byte hashes into a single concatenated blob. Also,
ResponseChainEntry.m_block_ids is an object array of block_context_info
(hash + cumulative size), not a simple hash list.
Co-Authored-By: Charon <charon@lethean.io>
P2PSync() runs the REQUEST_CHAIN / REQUEST_GET_OBJECTS loop against
a P2PConnection interface. Reuses processBlockBlobs() for shared
validation logic.
Co-Authored-By: Charon <charon@lethean.io>
Encode/decode for NOTIFY_REQUEST_GET_OBJECTS (2003) and
NOTIFY_RESPONSE_GET_OBJECTS (2004), including BlockCompleteEntry
for block + transaction blob pairs.
Co-Authored-By: Charon <charon@lethean.io>
The block processing logic is now in processBlockBlobs() which takes
raw wire bytes. The RPC processBlock() becomes a thin hex-decode
wrapper. The P2P sync path will call processBlockBlobs() directly.
Co-Authored-By: Charon <charon@lethean.io>
The Zano daemon's get_blocks_details RPC does not populate the blob
field. This adds resolveBlockBlobs() which batch-fetches miner tx
blobs via /gettransactions and reconstructs block wire blobs from
the parsed header (object_in_json AGGREGATED section) and raw tx
bytes. Also fixes regular tx processing to skip the miner tx entry
that the daemon includes in transactions_details.
Co-Authored-By: Charon <charon@lethean.io>
TxInputZC (v2+) inputs have key images that must be tracked for
double-spend detection, same as TxInputToKey.
Co-Authored-By: Charon <charon@lethean.io>
Implements consensus.RingOutputsFn by looking up output public keys from
the chain's global output index and transaction store. Wired into the
sync loop so VerifySignatures=true uses real crypto verification.
Co-Authored-By: Charon <charon@lethean.io>
Connect crypto.CheckRingSignature() to verifyV1Signatures() so
pre-HF4 transactions have their ring signatures cryptographically
verified when a RingOutputsFn callback is provided.
Co-Authored-By: Charon <charon@lethean.io>
Three-part design: NLSAG signature verification, full RPC sync to tip,
and P2P block sync via REQUEST_CHAIN / REQUEST_GET_OBJECTS. 13-task
implementation plan with TDD steps.
Co-Authored-By: Charon <charon@lethean.io>
Fix three bugs in the v2+ wire format and add complete variant tag handlers
for Zarcanum proof and signature structures. Verified byte-identical
round-trip against a real post-HF4 coinbase transaction from testnet block
101 (1323 bytes, tx hash 543bc3c2...3b61e0).
Bugs fixed:
- V2 suffix order was attachment+proofs, corrected to attachment+signatures+proofs
- TransactionHash was hashing full blob, corrected to prefix-only (matching C++)
- tagSignedParts was reading 4 fixed bytes, corrected to two varints
New: TxInputZC type, SignaturesRaw field, tagZarcanumTxDataV1 handler,
proof tags 46-48, signature tags 42-45, crypto blob readers for BPP/BPPE/
BGE/CLSAG GGX/GGXXG/aggregation proof/double Schnorr structures.
Co-Authored-By: Charon <charon@lethean.io>
Add cn_bpp_verify for Bulletproofs++ (1 delta, bpp_crypto_trait_ZC_out)
used by zc_outs_range_proof in post-HF4 transactions. Distinguish from
cn_bppe_verify (2 deltas, bpp_crypto_trait_Zarcanum) used for Zarcanum
PoS proofs.
Key changes:
- Add deserialise_bpp() and cn_bpp_verify() to bridge.cpp
- Add VerifyBPP() Go wrapper in proof.go
- Wire BPPE and BGE stubs into real C++ verify functions
- Add try/catch to all proof verifiers (C++ throws on invalid points)
- Add nil/empty input guards to all Go proof functions
- Test with real BPP proof from testnet block 101 coinbase tx
The BPP proof from tx 543bc3c2... (first post-HF4 coinbase) verifies
successfully through the full CGo pipeline, confirming wire format
deserialisation matches the C++ daemon output.
Co-Authored-By: Charon <charon@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port of C++ get_block_header_mining_hash(). Computes BlockHashingBlob
with nonce=0, Keccak-256's it. CheckNonce wraps RandomX + difficulty.
Co-Authored-By: Charon <charon@lethean.io>
Solo PoW miner against C++ daemon via JSON-RPC. Single-threaded
RandomX nonce grinding with daemon-provided block templates.
Co-Authored-By: Charon <charon@lethean.io>
Add integration test, update architecture docs with consensus/ package
description, record Phase 7 in project history.
Co-Authored-By: Charon <charon@lethean.io>
Add SyncOptions with VerifySignatures flag and hardfork schedule.
ValidateMinerTx and ValidateTransaction called during block processing.
Co-Authored-By: Charon <charon@lethean.io>
VerifyTransactionSignatures with structural checks for v1 NLSAG and
v2+ CLSAG. Crypto bridge calls marked as TODO for wiring.
Co-Authored-By: Charon <charon@lethean.io>
CheckDifficulty compares a 256-bit LE hash against a difficulty target.
CheckPoWHash computes RandomX hash and checks against difficulty.
Co-Authored-By: Charon <charon@lethean.io>
ValidateBlock combines timestamp, miner tx, and reward checks into
a single entry point for block-level consensus validation.
Co-Authored-By: Charon <charon@lethean.io>
ValidateBlockReward checks miner tx output sum against expected reward
with size penalty and hardfork-aware fee treatment.
Co-Authored-By: Charon <charon@lethean.io>
ValidateMinerTx checks genesis input height, input count (1 for PoW,
2 for PoS), and stake input type per hardfork version.
Co-Authored-By: Charon <charon@lethean.io>
Add consensus/ package with doc.go and sentinel error types for all
validation failures. Add MaxTransactionBlobSize constant to config.
Co-Authored-By: Charon <charon@lethean.io>
Layered validation architecture (structural, economic, cryptographic)
in a standalone consensus/ package. Full hardfork coverage (HF0-HF6),
PoW via CGo bridge, optional signature verification during sync.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>