Centralise handshake response validation so outbound sync checks both network identity and minimum peer build version through the p2p layer. Also record HTLC key images as spent during block processing, matching the HF1 input semantics and preventing those spends from being omitted from chain state.
Co-Authored-By: Charon <charon@lethean.io>
Update go.mod module line, all require/replace directives, and every
.go import path from forge.lthn.ai/core/go-blockchain to
dappco.re/go/core/blockchain. Add replace directives to bridge
dappco.re paths to existing forge.lthn.ai registry during migration.
Update CLAUDE.md, README, and docs to reflect the new module path.
Co-Authored-By: Virgil <virgil@lethean.io>
Converts the last 3 fmt.Errorf calls in production code (excluding
crypto/ CGo boundary) to coreerr.E() for conventions consistency.
Co-Authored-By: Charon <charon@lethean.io>
The conventions sweep (71f0a5c) overwrote HF5 code and removed HTLC/multisig
input handling. This commit restores:
- wire: HF5 asset wire tags (40/49/50/51) and reader functions for
asset_descriptor_operation, asset_operation_proof,
asset_operation_ownership_proof, and asset_operation_ownership_proof_eth
- wire: HTLC and multisig input encode/decode with string field helpers
- consensus: checkTxVersion enforcing version 3 after HF5 / rejecting before
- consensus: HF1-gated acceptance of HTLC and multisig input/output types
- consensus: HTLC key image deduplication in checkKeyImages
- consensus: HTLC ring signature counting in verifyV1Signatures
- chain: corrected error assertion in TestChain_GetBlockByHeight_NotFound
All 14 packages pass go test -race ./...
Co-Authored-By: Charon <charon@lethean.io>
Replace all fmt.Errorf and errors.New in production code with
coreerr.E("Caller.Method", "message", err) from go-log. Replace
os.MkdirAll with coreio.Local.EnsureDir from go-io. Sentinel errors
(consensus/errors.go, wire/varint.go) intentionally kept as errors.New
for errors.Is compatibility.
270 error call sites converted across 38 files. Test files untouched.
crypto/ directory (CGO) untouched.
Co-Authored-By: Virgil <virgil@lethean.io>
The 240s PoW target was incorrectly gated on HF2 (block 10,080), matching
the Zano upstream where HF2 coincides with the difficulty target change.
Lethean mainnet uses 120s blocks between HF2 and HF6 (999,999,999), so
the gate is corrected to HF6.
Also adds NextPoSDifficulty with the same HF6 gate using the PoS target
constants (DifficultyPosTarget / DifficultyPosTargetHF6). Both public
methods delegate to a shared nextDifficultyWith helper to avoid
duplicating the LWMA window logic.
Co-Authored-By: Charon <charon@lethean.io>
Prepares for HF1 output target types (TxOutMultisig, TxOutHTLC).
All call sites updated to type-assert TxOutToKey where needed.
Modified files:
- types/transaction.go: TxOutputBare.Target is now TxOutTarget
- wire/transaction.go: encode/decode use type switch on target
- chain/ring.go: type-assert target to TxOutToKey for key extraction
- wallet/scanner.go: type-assert target before key comparison
- tui/explorer_model.go: type-assert target for display
- wire/transaction_test.go: type-assert in assertions
- wallet/builder_test.go: type-assert in assertions
Co-Authored-By: Charon <charon@lethean.io>
Add full V2 transaction verification pipeline: parse SignaturesRaw variant
vector into structured ZC signature data, verify CLSAG GGX ring signatures
per ZC input, verify BPP range proofs, and verify BGE asset surjection
proofs with correct ring construction (mul8 point arithmetic).
Fix three wire format bugs that caused V2 parsing failures:
- RefTypeGlobalIndex (tag 0x1A) uses 8-byte LE, not varint
- Raw uint64_t variant (tagUint64) uses 8-byte LE, not varint
- zarcanum_tx_data_v1 fee uses FIELD() → 8-byte LE, not VARINT_FIELD()
Add cn_point_sub to C++ bridge and Go wrapper for BGE ring construction.
Add GetZCRingOutputs to chain for fetching ZC ring member data.
Co-Authored-By: Charon <charon@lethean.io>
Rewrites the LWMA difficulty algorithm to match the C++ daemon exactly:
- Uses N=60 window with linear weighting (position 1..n)
- Clamps solve times to [-6T, 6T]
- Excludes genesis block from the difficulty window
- Selects target based on hardfork: 120s pre-HF2, 240s post-HF2
On testnet, HF2 activates at height 10 (active from height 11),
doubling the target from 120s to 240s. The previous fixed 120s target
produced exactly half the expected difficulty from height 11 onward.
Integration test verifies all 2576 testnet blocks match the daemon.
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>
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>
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>
Add SyncOptions with VerifySignatures flag and hardfork schedule.
ValidateMinerTx and ValidateTransaction called during block processing.
Co-Authored-By: Charon <charon@lethean.io>
Add comprehensive tests exercising regular transaction processing through
the sync pipeline (key image marking, output indexing, cumulative
difficulty) and not-found error paths for all query methods. Coverage
rises from 65.8% to 80.1%.
Co-Authored-By: Charon <charon@lethean.io>