From 78a203352f6d63ec5d5f550f27630de1051a18cd Mon Sep 17 00:00:00 2001 From: neverDefined Date: Sun, 26 Apr 2026 20:48:26 +0400 Subject: [PATCH] docs: post-Phase 6 audit fixes for README, doc.go, and rpc.go godoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sweep after PRs #111, #112, #113 to align library-level docs with what the package actually exposes today. doc.go - Headline expanded to "Bitcoin Core or Bitcoin Inquisition" so the package overview matches the README. - Configuration block documents the BinaryPath auto-detect chain (bitcoind-inquisition first, then bitcoind) and the bitcoin-cli sibling-derivation fallback. - New "Soft-fork Testing" section covers VBParams, MineUntilActive vs MineUntilActiveBIP, the curated BIPID registry, ListDeployments, the SupportsBIP skip-when-missing pattern, and Variant(). - Error Handling section: corrected the "bitcoind not found" message to mention both names tried; listed errNotConnected, ErrUnknownDeployment, and ErrUnknownBIP as errors.Is-compatible sentinels. - Prerequisites section: pointer to the README's Inquisition build recipe so doc.go and README stay coherent. README.md - Tagline updated to mention Inquisition alongside Core. - Soft-fork-testing snippet adds an inline note that MineUntilActive / MineUntilActiveBIP wrap the inlined polling loop, and signposts the typed BIPID variant as the preferred form for Inquisition deployments. - Fixed inaccurate description of ListDeployments — returns a []EnrichedDeployment sorted alphabetically by Deployment, not a map "keyed by deployment string." rpc.go - Filled out the Parameters/Returns/Example godoc on Client, GetBlockCount, GetBlockCountContext, HealthCheck, and HealthCheckContext to match the canonical voice used elsewhere in the package (see MineUntilActive in mining.go for reference). - Documented errNotConnected and ctx.Err() return paths so callers can errors.Is against them. No behavioral changes; ai-check green. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 10 ++++++---- doc.go | 46 +++++++++++++++++++++++++++++++++++++++---- rpc.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 102 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 36bbda3..3dd9b41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # go-regtest -A lightweight Go library for managing Bitcoin Core regtest environments. +A lightweight Go library for managing Bitcoin Core or Bitcoin Inquisition regtest environments. [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Go Version](https://img.shields.io/badge/Go-1.23%2B-blue.svg)](https://golang.org) @@ -167,7 +167,9 @@ rt, _ := regtest.New(®test.Config{ rt.Start(); defer rt.Stop() status, _ := rt.DeploymentStatus("testdummy") // SoftForkDefined / Started / ... -// Mine through retarget windows until ACTIVE. +// Mine through retarget windows until ACTIVE. The `MineUntilActive` / +// `MineUntilActiveBIP` helpers wrap this loop; the snippet inlines it +// here only to show the underlying state machine. miner, _ := rt.GenerateBech32("miner") for status != regtest.SoftForkActive { rt.Warp(144, miner) @@ -175,7 +177,7 @@ for status != regtest.SoftForkActive { } ``` -For a fully-narrated walkthrough, see [`TestExampleActivateTestdummy`](examples_test.go) — the same template applies to real future soft-forks (APO/eltoo, CTV, CSFS) once you point `bitcoind` in `$PATH` at a binary that knows the deployment. +For a fully-narrated walkthrough, see [`TestExampleActivateTestdummy`](examples_test.go) — the same template applies to real future soft-forks (APO/eltoo, CTV, CSFS) once you point `bitcoind` in `$PATH` at a binary that knows the deployment. For Inquisition-tracked BIPs, prefer the typed `rt.MineUntilActiveBIP(regtest.BIP119, addr, maxBlocks)` over the string-keyed `MineUntilActive` so deployment-name typos surface at compile time. #### Skip-when-missing pattern @@ -198,7 +200,7 @@ func TestMyCTVThing(t *testing.T) { } ``` -`rt.ListDeployments()` returns the merged registry-and-live view (`BIPID`, `BIPNumber`, `Name`, `DocURL`, `Status`, `Type`, `Active`, `Height`) keyed by deployment string, useful for diagnostics. See [`TestExampleActivateBIP119`](examples_inquisition_test.go) for the full template. +`rt.ListDeployments()` returns a `[]EnrichedDeployment` (joined registry + live view: `BIPID`, `BIPNumber`, `Name`, `DocURL`, `Status`, `Type`, `Active`, `Height`) sorted alphabetically by `Deployment`, useful for diagnostics. See [`TestExampleActivateBIP119`](examples_inquisition_test.go) for the full template. ### Multi-node and reorg testing diff --git a/doc.go b/doc.go index 65039fc..eed9c93 100644 --- a/doc.go +++ b/doc.go @@ -1,8 +1,12 @@ /* -Package regtest provides a lightweight Go library for managing Bitcoin Core regtest environments. +Package regtest provides a lightweight Go library for managing Bitcoin Core +or Bitcoin Inquisition regtest environments. Regtest mode creates a private blockchain for testing and development. This package simplifies -starting, managing, and interacting with regtest nodes programmatically. +starting, managing, and interacting with regtest nodes programmatically. The same Config works +against stock Bitcoin Core and against Bitcoin Inquisition (the experimental Core fork that +activates upcoming soft forks: BIP54, BIP118 ANYPREVOUT, BIP119 OP_CHECKTEMPLATEVERIFY, +BIP347 OP_CAT, BIP348 OP_CHECKSIGFROMSTACK, BIP349 OP_INTERNALKEY). Quick Start @@ -36,8 +40,11 @@ Default settings: - RPC user: user - RPC pass: pass - Data directory: ./bitcoind_regtest + - Binary: PATH auto-detect — bitcoind-inquisition first, then bitcoind -Customize via Config struct when creating instances. +Customize via Config struct when creating instances. Set Config.BinaryPath to point at a +non-default bitcoind build (absolute path, relative path, or bare name resolved via PATH). +The bitcoin-cli companion is derived from the same directory, falling back to PATH. # Examples @@ -82,6 +89,28 @@ Direct RPC Access: info, _ := client.GetBlockChainInfo() mempool, _ := client.GetRawMempool() +# Soft-fork Testing + +VBParams configure named BIP9 deployments via -vbparams. DeploymentStatus and +GetDeploymentInfo expose the current state machine; MineUntilActive (string-keyed) and +MineUntilActiveBIP (typed BIPID) drive a deployment to SoftForkActive over retarget windows. + +The curated registry maps typed BIPID constants to deployment names, BIP numbers, and doc +URLs: + + - BIPTestdummy, BIPTaproot — present on both Core and Inquisition + - BIP54, BIP118, BIP119, BIP347, BIP348, BIP349 — Inquisition-only + +ListDeployments returns the merged registry-and-live view; SupportsBIP is the canonical +skip-when-missing primitive for tests that need an Inquisition-only deployment: + + if ok, _ := rt.SupportsBIP(regtest.BIP119); !ok { + t.Skip("requires bitcoind-inquisition") + } + +Variant reports VariantCore or VariantInquisition (parsed from getnetworkinfo.subversion) +once Start has succeeded; the result is cached so repeat calls are free. + # Thread Safety All Regtest methods are thread-safe. Multiple goroutines can safely call Start(), Stop(), @@ -90,12 +119,17 @@ IsRunning(), and make RPC calls concurrently. Always use defer rt.Stop() for cle # Error Handling Check errors from all methods. Common errors: - - bitcoind not found in PATH + - bitcoind not found in PATH (tried bitcoind-inquisition, bitcoind) - Port already in use - RPC connection failures - Invalid addresses or parameters - Insufficient funds +Sentinels are errors.Is-compatible: + - errNotConnected — RPC method called before Start + - ErrUnknownDeployment — deployment name not in getdeploymentinfo + - ErrUnknownBIP — BIPID not in the curated registry + # Prerequisites Install Bitcoin Core: @@ -103,6 +137,10 @@ Install Bitcoin Core: - Ubuntu/Debian: sudo apt-get install bitcoind - Arch: sudo pacman -S bitcoin-core +For testing upcoming soft forks, build Bitcoin Inquisition from source — see the README +for the cmake recipe. The built bitcoind can be picked up via Config.BinaryPath, or by +symlinking it as bitcoind-inquisition on PATH so the auto-detect chain finds it. + # Port Considerations When running multiple instances, use widely spaced ports (e.g., 19000, 19100) because Bitcoin diff --git a/rpc.go b/rpc.go index 9440254..123440a 100644 --- a/rpc.go +++ b/rpc.go @@ -8,23 +8,53 @@ import ( "github.com/btcsuite/btcd/rpcclient" ) -// Client returns the RPC client for the Regtest instance. -// For advanced users that want to use the RPC client directly. +// Client returns the underlying btcsuite/rpcclient connection for callers +// that need an RPC the typed wrappers in this package don't cover. The +// returned client is shared with the wrappers; callers must not Shutdown it. // // Returns: -// - *rpcclient.Client: The RPC client instance, or nil if not connected +// - *rpcclient.Client: the live client, or nil before Start has succeeded +// (or after Stop). Prefer the typed wrappers on Regtest where available. +// +// Example: +// +// client := rt.Client() +// if client == nil { +// return errors.New("Start must be called first") +// } +// info, _ := client.GetBlockChainInfo() func (r *Regtest) Client() *rpcclient.Client { r.clientMu.RLock() defer r.clientMu.RUnlock() return r.client } -// GetBlockCount returns the current block count. +// GetBlockCount returns the chain tip height. Convenience wrapper around +// GetBlockCountContext using context.Background(). +// +// Returns: +// - int64: current block height (0 on a fresh regtest node before any +// blocks have been mined). +// - error: errNotConnected before Start; otherwise the wrapped RPC error. +// +// Example: +// +// h, err := rt.GetBlockCount() +// if err != nil { return err } +// fmt.Printf("tip at height %d\n", h) func (r *Regtest) GetBlockCount() (int64, error) { return r.GetBlockCountContext(context.Background()) } // GetBlockCountContext is the context-aware variant of GetBlockCount. +// +// Parameters: +// - ctx: cancellation / timeout. A pre-cancelled context returns ctx.Err(). +// +// Returns: +// - int64: current block height. +// - error: errNotConnected before Start; ctx.Err() on cancellation; +// otherwise the wrapped RPC error. func (r *Regtest) GetBlockCountContext(ctx context.Context) (int64, error) { client, err := r.lockedClient() if err != nil { @@ -35,12 +65,31 @@ func (r *Regtest) GetBlockCountContext(ctx context.Context) (int64, error) { }) } -// HealthCheck performs a health check by getting the block count. +// HealthCheck performs a minimal RPC round-trip (getblockcount) to confirm +// the node is reachable and responsive. Convenience wrapper around +// HealthCheckContext using context.Background(). +// +// Returns: +// - error: errNotConnected before Start; otherwise the wrapped RPC error +// from getblockcount. +// +// Example: +// +// if err := rt.HealthCheck(); err != nil { +// t.Fatalf("node not healthy: %v", err) +// } func (r *Regtest) HealthCheck() error { return r.HealthCheckContext(context.Background()) } // HealthCheckContext is the context-aware variant of HealthCheck. +// +// Parameters: +// - ctx: cancellation / timeout. A pre-cancelled context returns ctx.Err(). +// +// Returns: +// - error: errNotConnected before Start; ctx.Err() on cancellation; +// otherwise the wrapped RPC error. func (r *Regtest) HealthCheckContext(ctx context.Context) error { if _, err := r.GetBlockCountContext(ctx); err != nil { return fmt.Errorf("failed to get block count (health check): %w", err)