orchestrator

package module
v0.0.0-...-5a53b6d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultCoreVariantID = "patched"

DefaultCoreVariantID is the variant used when no settings file exists. "patched" is the only variant available on every network (including mainnet) so it's a safe default that won't get clamped to empty.

View Source
const PresyncMessagePrefix = "Pre-synchronizing blockheaders"

PresyncMessagePrefix is the prefix used in synthetic startup errors when bitcoind is in the headers-presync phase. The connection monitor's startup-pattern list includes this prefix so the message is classified as startupError rather than connectionError.

Variables

This section is empty.

Functions

func ActiveCoreBinaryPath

func ActiveCoreBinaryPath(dataDir, bitwindowDir string, configs []BinaryConfig, binaryName string) string

ActiveCoreBinaryPath returns the on-disk path for the bitcoind variant currently selected in orchestrator_settings.json. Used by CLI commands and the testharness to find the active build without constructing a full Orchestrator. Non-bitcoind names always resolve via the legacy flat layout.

func AddDescriptorChecksum

func AddDescriptorChecksum(desc string) (string, error)

AddDescriptorChecksum adds a checksum to a descriptor string.

func BinDir

func BinDir(dataDir string) string

BinDir returns the directory where binaries are stored.

func BinaryPath

func BinaryPath(dataDir, binaryName string) string

BinaryPath returns the full path to a binary executable.

func ConfigFilePath

func ConfigFilePath(dir string) string

ConfigFilePath returns the path to chains_config.json in the given directory.

func CoreBinaryPath

func CoreBinaryPath(dataDir string, _ CoreVariantSpec, binaryName string) string

CoreBinaryPath returns the on-disk path for the active Bitcoin Core daemon. All variants share a single `bin/bitcoind` location — switching variants re-downloads and overwrites whatever was there.

func CoreVariantInstalled

func CoreVariantInstalled(dataDir string, v CoreVariantSpec, binaryName string) bool

CoreVariantInstalled reports whether the variant's binary exists on disk.

func DefaultBitwindowDir

func DefaultBitwindowDir() string

DefaultBitwindowDir returns the default BitWindow data directory. Uses the BitWindow binary directory config loaded from chains_config.json.

func DefaultDataDir

func DefaultDataDir() string

DefaultDataDir returns the default data directory for the orchestrator. This is the same as the BitWindow data directory, since orchestrator stores its assets (binaries, configs) alongside BitWindow.

func DescriptorChecksum

func DescriptorChecksum(desc string) (string, error)

DescriptorChecksum computes the checksum for a Bitcoin Core descriptor string.

func LogDir

func LogDir(dataDir string) string

LogDir returns the directory where logs are stored.

func PidDir

func PidDir(dataDir string) string

PidDir returns the directory where PID files are stored.

func SaveSettings

func SaveSettings(bitwindowDir string, s OrchestratorSettings) error

SaveSettings writes orchestrator_settings.json atomically. Bytes hit disk before the rename and the parent directory is fsync'd on POSIX so a crash can't leave the file half-written or replace a valid file with a tmp that isn't yet durable.

func SettingsPath

func SettingsPath(bitwindowDir string) string

SettingsPath returns the path to orchestrator_settings.json.

func StripPlatformSuffix

func StripPlatformSuffix(name string) string

StripPlatformSuffix removes platform/architecture and version suffixes from extracted filenames to produce a clean binary name.

Examples:

"thunder-orchard-0.1.0-x86_64-apple-darwin" -> "thunder-orchard"
"grpcurl_1.9.1_linux_x86_64" -> "grpcurl"
"bip300301-enforcer-latest-x86_64-unknown-linux-gnu" -> "bip300301-enforcer-latest"

func TestSidechainBinaryPath

func TestSidechainBinaryPath(dataDir, binaryName string) string

TestSidechainBinaryPath resolves the launchable binary inside a test build's directory. Three shapes are supported:

  • Linux: `<dir>/<binaryName>` next to `lib/`+`data/`.
  • macOS: `<dir>/<TitleCase>.app/Contents/MacOS/<TitleCase>` (Flutter bundle). We walk the directory once to find the `.app` so the spec doesn't need to encode TitleCase mappings (`thunder` → `Thunder`, `bitassets` → `BitAssets`, etc.).
  • Windows: `<dir>/<binaryName>.exe` — single self-contained .exe.

func TestSidechainDir

func TestSidechainDir(dataDir, binaryName string) string

TestSidechainDir returns the per-binary directory that test/alternative sidechain builds extract into. Test builds are full Flutter app bundles with sibling lib/data trees (Linux) or `.app` packages (macOS); each sidechain therefore needs its own subfolder so libraries don't collide.

func WaitForHealthy

func WaitForHealthy(ctx context.Context, checker HealthChecker, interval time.Duration) error

WaitForHealthy polls the health checker until it succeeds or the context is canceled.

func WatchConfigFile

func WatchConfigFile(path string, onChange func([]BinaryConfig), log zerolog.Logger) (func(), error)

WatchConfigFile watches chains_config.json for changes and calls onChange.

Types

type AddressInfo

type AddressInfo struct {
	Address     string `json:"address"`
	IsMine      bool   `json:"ismine"`
	IsWatchOnly bool   `json:"iswatchonly"`
	IsScript    bool   `json:"isscript"`
	IsWitness   bool   `json:"iswitness"`
	HdKeyPath   string `json:"hdkeypath,omitempty"`
}

type BinaryConfig

type BinaryConfig struct {
	// Core identity — Dart: Binary constructor params (L61-72)
	Name        string // Dart: Binary.name (internal identifier, e.g. "bitcoind", "thunder")
	DisplayName string // Dart: Binary.name in subclass (e.g. "Bitcoin Core (Patched)")
	BinaryName  string // Dart: Binary.binary (executable name, from metadata.downloadConfig.binary)
	Version     string // Dart: Binary.version
	Description string // Dart: Binary.description
	RepoURL     string // Dart: Binary.repoUrl
	Port        int    // Dart: Binary.port
	ChainLayer  int    // Dart: Binary.chainLayer (0=utility, 1=L1, 2=sidechain)
	Slot        int    // Dart: Sidechain.slot (0 for non-sidechains)

	// Directory configuration — Dart: DirectoryConfig class
	DataDir        map[string]string // os -> subdir under AppDir() (default for all networks)
	DataDirMainnet map[string]string // os -> subdir (mainnet override, empty = use DataDir)
	IsBitcoinCore  bool              // Linux appdir exception: ~/ instead of ~/.local/share

	// Flutter frontend directory — Dart: flutterFrontendDir() extension (L1306-1353)
	// Per-OS subdir under the platform app support dir. Empty = no frontend.
	FlutterFrontendDir map[string]string

	// Primary download configuration — Dart: MetadataConfig.downloadConfig
	DownloadSource   DownloadSource
	DownloadURLs     map[string]string // network -> base URL ("default", "forknet", etc.)
	Files            map[string]string // os -> filename or regex pattern
	ForknetFiles     map[string]string // os -> forknet-specific filename (BitcoinCore only)
	ExtractSubfolder map[string]string // os -> subfolder to extract from zip (empty = root)

	// Core variant configuration — only populated for the bitcoincore entry.
	// Keys are variant IDs ("core", "patched", "knots").
	Variants map[string]CoreVariantSpec

	// Alternative download configuration — Dart: MetadataConfig.alternativeDownloadConfig
	// Used for test chain builds when SettingsProvider selects it.
	AltDownloadURLs     map[string]string // network -> base URL
	AltBinaryName       string            // Dart: alternativeDownloadConfig.binary
	AltFiles            map[string]string // os -> filename
	AltExtractSubfolder map[string]string // os -> subfolder

	// Dart: MetadataConfig.updateable
	Updateable bool

	// Dart: Binary.startupLogPatterns (regex strings)
	StartupLogPatterns []string

	// Dart: Binary.extraBootArgs
	ExtraBootArgs []string

	// Health check (Go-specific, not in Dart Binary)
	HealthCheckType HealthCheckType
	HealthCheckRPC  string // JSON-RPC method for health check

	// Dependencies: names of binaries that must be running before this one
	Dependencies []string
}

BinaryConfig is the 1:1 Go port of Dart's Binary abstract class + subclasses. Every field maps to a Dart property from binaries.dart / sidechains.dart.

func AllDefaults

func AllDefaults() []BinaryConfig

AllDefaults returns configs for every known binary, loaded from the embedded chains_config.json. This is the single source of truth.

func AllSidechains

func AllSidechains() []BinaryConfig

AllSidechains returns configs for all sidechain binaries (ChainLayer == 2). Dart: Sidechain.all (sidechains.dart L49-57)

func BinaryConfigByName

func BinaryConfigByName(name string) (BinaryConfig, bool)

BinaryConfigByName returns the default config for a binary by name. Dart: Sidechain.fromString (sidechains.dart L23-47)

func BinaryConfigBySlot

func BinaryConfigBySlot(slot int) (BinaryConfig, bool)

BinaryConfigBySlot returns the sidechain config for a given slot number. Dart: Sidechain.fromSlot (sidechains.dart L59-66)

func LoadConfigFile

func LoadConfigFile(path string, log zerolog.Logger) []BinaryConfig

LoadConfigFile loads binary configs from a chains_config.json file, overlaying it on top of the embedded defaults. Embedded fields fill in anything missing from the on-disk file — critical for fields the user has no business overriding (is_bitcoin_core, health_check) when their on-disk file pre-dates a schema bump.

Falls back to embedded only when the on-disk file is missing or unparseable.

func (BinaryConfig) AltBaseURL

func (c BinaryConfig) AltBaseURL(network string) string

AltBaseURL returns the alternative download base URL for a given network.

func (BinaryConfig) BaseURL

func (c BinaryConfig) BaseURL(network string) string

BaseURL returns the download base URL for a given network. Falls back to "default", then to the first available URL.

func (BinaryConfig) Downloadable

func (c BinaryConfig) Downloadable() bool

Downloadable returns true if this binary has download URLs configured.

func (BinaryConfig) FileForOS

func (c BinaryConfig) FileForOS() (string, error)

FileForOS returns the download filename for the current platform.

func (BinaryConfig) IsSidechain

func (c BinaryConfig) IsSidechain() bool

IsSidechain returns true if this binary is a sidechain (ChainLayer == 2).

type BinaryStatus

type BinaryStatus struct {
	Name            string
	DisplayName     string
	Running         bool
	Healthy         bool
	Pid             int
	Uptime          time.Duration
	ChainLayer      int
	Port            int
	Error           string
	Connected       bool   // from ConnectionMonitor
	StartupError    string // warmup message (e.g. "Loading block index...")
	ConnectionError string // real connection error
	Stopping        bool   // binary is being stopped
	Initializing    bool   // binary is starting up / restarting
	ConnectModeOnly bool   // willfully stopped, only watching for external restart
	Downloadable    bool   // binary has download URLs configured
	Description     string // short description of the binary
	Downloaded      bool   // binary file exists on disk
	BinaryPath      string // absolute path to the launchable binary (variant-aware), empty when not downloaded
	PortInUse       bool   // port is reachable (something is listening)
	Version         string // configured version string
	RepoURL         string // source code repository URL
	StartupLogs     []StartupLogLine
}

BinaryStatus represents the current state of a managed binary.

type BitcoindHealthCheck

type BitcoindHealthCheck struct {
	URL      string
	User     string
	Password string
	Timeout  time.Duration
}

BitcoindHealthCheck wraps the regular RPC ping with detection for the "Pre-synchronizing blockheaders" phase. During that phase, Bitcoin Core (BIP324, 22.0+) responds normally to RPC calls, but `getblockchaininfo` returns blocks=0 and headers=0 — so the UI sees no progress and looks frozen even though the daemon is actively downloading headers.

We surface presync as a synthetic startup error containing the highest `presynced_headers` value across `getpeerinfo`, which the connection monitor's bitcoind startup-pattern list catches and routes into BinaryStatus.StartupError. The Dart side already renders that field.

func (*BitcoindHealthCheck) Check

func (h *BitcoindHealthCheck) Check(ctx context.Context) error

type BumpFeeResult

type BumpFeeResult struct {
	Txid        string   `json:"txid"`
	OriginalFee float64  `json:"origfee"`
	NewFee      float64  `json:"fee"`
	Errors      []string `json:"errors,omitempty"`
}

type ChainSyncResult

type ChainSyncResult struct {
	Blocks        int64
	Headers       int64
	Time          int64
	Error         string
	IsDownloading bool
}

ChainSyncResult is one chain's tip snapshot. Error is set on failure; the numeric fields are best-effort zero in that case. While IsDownloading is true, Blocks/Headers carry MB downloaded / MB total instead of chain heights — the polled API reuses the same fields so adding download state didn't require new wire fields.

type ConnectRPCHealthCheck

type ConnectRPCHealthCheck struct {
	URL     string // e.g. "http://localhost:50051/cusf.mainchain.v1.ValidatorService/GetChainTip"
	Timeout time.Duration
}

ConnectRPCHealthCheck POSTs an empty JSON body to a Connect-JSON endpoint and inspects the response. On Connect-JSON, success is HTTP 200 with a JSON body that has no `code` field; failure is HTTP 4xx/5xx with `{"code":"...","message":"..."}`. Warmup errors (daemon up, not ready) come back here as an error message that the connection monitor pattern-matches into startupError — e.g. the enforcer returning "Validator is not synced" while still catching up to the mainchain tip.

func (*ConnectRPCHealthCheck) Check

type ConnectionMonitor

type ConnectionMonitor struct {
	Name    string // binary config name (e.g. "bitcoind")
	Checker HealthChecker
	// contains filtered or unexported fields
}

ConnectionMonitor is a 1:1 Go port of Dart's RPCConnection (rpc_connection.dart).

It manages:

  • A persistent 1-second health-check timer (Dart: connectionTimer)
  • A 500ms restart timer that auto-restarts crashed processes (Dart: restartTimer)
  • connectModeOnly: after a willful stop, the timer keeps pinging to detect externally started processes, but suppresses errors silently

Dart equivalents:

  • connectionTimer → connectionTicker
  • testConnection() → testConnection()
  • connectModeOnly → connectModeOnly
  • connected → connected
  • startConnectionTimer → StartConnectionTimer()
  • restartTimer → restartTicker
  • startRestartTimer → StartRestartTimer()
  • stop() → MarkStopped()
  • markDisconnected() → MarkDisconnected()
  • _pingEpoch → pingEpoch

func NewConnectionMonitor

func NewConnectionMonitor(name string, checker HealthChecker, startupPatterns []string, log zerolog.Logger) *ConnectionMonitor

NewConnectionMonitor creates a monitor for a binary. Does NOT start timers — call StartConnectionTimer() and StartRestartTimer().

func (*ConnectionMonitor) AddStartupLog

func (m *ConnectionMonitor) AddStartupLog(ts time.Time, msg string)

AddStartupLog appends a startup progress message. Keeps the last 20. Dart: Binary.addStartupLog

func (*ConnectionMonitor) ConnectModeOnly

func (m *ConnectionMonitor) ConnectModeOnly() bool

ConnectModeOnly returns whether the monitor is in connect-mode-only (willfully stopped, only watching for external restart).

func (*ConnectionMonitor) Connected

func (m *ConnectionMonitor) Connected() bool

Connected returns the current connection state. Dart: RPCConnection.connected

func (*ConnectionMonitor) ConnectionError

func (m *ConnectionMonitor) ConnectionError() string

ConnectionError returns the last connection error (empty if connected).

func (*ConnectionMonitor) InitializingBinary

func (m *ConnectionMonitor) InitializingBinary() bool

InitializingBinary returns whether the binary is currently starting up.

func (*ConnectionMonitor) MarkDisconnected

func (m *ConnectionMonitor) MarkDisconnected()

MarkDisconnected marks the connection as disconnected without sending a stop. Dart: RPCConnection.markDisconnected() (rpc_connection.dart L387-396) Used when the binary has already been stopped externally.

func (*ConnectionMonitor) MarkStopped

func (m *ConnectionMonitor) MarkStopped()

MarkStopped marks the connection as stopped. Dart: RPCConnection.stop() (rpc_connection.dart L356-383) Timer keeps running in connect-mode-only: it keeps pinging to detect externally started processes but suppresses errors silently.

func (*ConnectionMonitor) SetConnectionError

func (m *ConnectionMonitor) SetConnectionError(errMsg string)

SetConnectionError sets the connection error from an external source (e.g. process crash). This is how process exit errors flow into the UI. The error "sticks" — it won't be overwritten by generic "connection refused" from the next health check ping. It's only cleared when the process reconnects successfully.

func (*ConnectionMonitor) SetInitializing

func (m *ConnectionMonitor) SetInitializing(v bool)

SetInitializing flips the initializing flag and fires onChange so the frontend sees the transition immediately (before the next 1s ping). Orchestrator calls this around process.Start so the UI shows an "initializing" spinner instead of a red X during the fresh-boot window where testConnection is still failing.

func (*ConnectionMonitor) SetOnChange

func (m *ConnectionMonitor) SetOnChange(fn func())

SetOnChange sets the callback fired whenever connection state changes.

func (*ConnectionMonitor) SetStopping

func (m *ConnectionMonitor) SetStopping(v bool)

SetStopping flips the stopping flag and fires onChange so the frontend sees the transition immediately. Orchestrator calls SetStopping(true) right before signalling the process, so the UI can badge the binary as "stopping" during the shutdown window (between signal and exit). MarkStopped resets the flag to false once the process is actually gone.

func (*ConnectionMonitor) StartConnectionTimer

func (m *ConnectionMonitor) StartConnectionTimer(ctx context.Context)

StartConnectionTimer starts the 1-second periodic health check. Dart: RPCConnection.startConnectionTimer() (rpc_connection.dart L299-319)

1. Pings once immediately 2. Starts a 1-second periodic timer

Returns after the first ping completes (so caller knows if already connected).

func (*ConnectionMonitor) StartRestartTimer

func (m *ConnectionMonitor) StartRestartTimer(ctx context.Context, restartFunc func(ctx context.Context) error, exitedFunc func() (int, bool))

StartRestartTimer starts the 500ms restart timer that auto-restarts crashed processes. Dart: RPCConnection.startRestartTimer() (rpc_connection.dart L236-286)

Only call this if we STARTED the process ourselves (not for adopted processes). Dart: "only start restart timer if this process starts the binary!"

func (*ConnectionMonitor) StartupError

func (m *ConnectionMonitor) StartupError() string

StartupError returns the current startup/warmup message (e.g. "Loading block index..."). Dart: RPCConnection.startupError

func (*ConnectionMonitor) StartupLogs

func (m *ConnectionMonitor) StartupLogs() []StartupLogLine

StartupLogs returns a copy of the recent startup progress messages.

func (*ConnectionMonitor) StopAllTimers

func (m *ConnectionMonitor) StopAllTimers()

StopAllTimers stops both timers.

func (*ConnectionMonitor) StopConnectionTimer

func (m *ConnectionMonitor) StopConnectionTimer()

StopConnectionTimer stops the periodic health check timer.

func (*ConnectionMonitor) StopRestartTimer

func (m *ConnectionMonitor) StopRestartTimer()

StopRestartTimer stops the restart timer. Dart: restartTimer?.cancel() in stop()

func (*ConnectionMonitor) StoppingBinary

func (m *ConnectionMonitor) StoppingBinary() bool

StoppingBinary returns whether the binary is currently being stopped.

func (*ConnectionMonitor) WaitForConnected

func (m *ConnectionMonitor) WaitForConnected(ctx context.Context) error

WaitForConnected blocks until connected or context is cancelled. Dart: RPCConnection.waitForConnected() (rpc_connection.dart L293-296)

type CoreBalances

type CoreBalances struct {
	Mine struct {
		Trusted          float64 `json:"trusted"`
		UntrustedPending float64 `json:"untrusted_pending"`
		Immature         float64 `json:"immature"`
	} `json:"mine"`
	Watchonly *struct {
		Trusted          float64 `json:"trusted"`
		UntrustedPending float64 `json:"untrusted_pending"`
		Immature         float64 `json:"immature"`
	} `json:"watchonly,omitempty"`
}

type CoreStatusClient

type CoreStatusClient struct {
	// contains filtered or unexported fields
}

CoreStatusClient is a minimal Bitcoin Core JSON-RPC client for startup sequencing checks. It only implements the 2-3 calls needed to check wallet unlock and IBD status.

func NewCoreStatusClient

func NewCoreStatusClient(host string, port int, user, password string) *CoreStatusClient

func (*CoreStatusClient) BumpFee

func (c *CoreStatusClient) BumpFee(ctx context.Context, walletName, txid string) (*BumpFeeResult, error)

func (*CoreStatusClient) CreateBitcoinCoreWalletFromSeed

func (c *CoreStatusClient) CreateBitcoinCoreWalletFromSeed(ctx context.Context, walletName, seedHex, network string) error

CreateBitcoinCoreWalletFromSeed creates a Bitcoin Core descriptor wallet and imports BIP84 (wpkh) descriptors derived from the seed. Ported from bitwindow/server/engines/wallet_engine.go CreateBitcoinCoreWalletFromSeed.

func (*CoreStatusClient) CreateRawTransaction

func (c *CoreStatusClient) CreateRawTransaction(ctx context.Context, inputs []map[string]interface{}, outputs []map[string]interface{}) (string, error)

func (*CoreStatusClient) CreateWallet

func (c *CoreStatusClient) CreateWallet(ctx context.Context, walletName string, disablePrivateKeys, blank, descriptors bool) error

CreateWallet creates a new wallet in Bitcoin Core.

func (*CoreStatusClient) CreateWatchOnlyWalletInCore

func (c *CoreStatusClient) CreateWatchOnlyWalletInCore(ctx context.Context, walletName, descriptorOrXpub string) error

CreateWatchOnlyWalletInCore creates a watch-only wallet in Bitcoin Core from a descriptor or xpub.

func (*CoreStatusClient) GetAddressInfo

func (c *CoreStatusClient) GetAddressInfo(ctx context.Context, walletName, address string) (*AddressInfo, error)

func (*CoreStatusClient) GetBalances

func (c *CoreStatusClient) GetBalances(ctx context.Context, walletName string) (*CoreBalances, error)

func (*CoreStatusClient) GetBlockCount

func (c *CoreStatusClient) GetBlockCount(ctx context.Context) (int64, error)

GetBlockCount returns the current block height.

func (*CoreStatusClient) GetNewAddress

func (c *CoreStatusClient) GetNewAddress(ctx context.Context, walletName string) (string, error)

func (*CoreStatusClient) GetRawTransaction

func (c *CoreStatusClient) GetRawTransaction(ctx context.Context, txid string, verbose bool) (*RawTransaction, error)

func (*CoreStatusClient) GetTransaction

func (c *CoreStatusClient) GetTransaction(ctx context.Context, walletName, txid string) (*CoreTransactionDetail, error)

func (*CoreStatusClient) GetWalletInfo

func (c *CoreStatusClient) GetWalletInfo(ctx context.Context, walletName string) (*WalletInfo, error)

func (*CoreStatusClient) ImportDescriptorsRPC

func (c *CoreStatusClient) ImportDescriptorsRPC(ctx context.Context, walletName string, descriptors []map[string]interface{}) (json.RawMessage, error)

ImportDescriptorsRPC imports descriptors into a specific wallet using the /wallet/<name> endpoint.

func (*CoreStatusClient) IsHeaderSyncComplete

func (c *CoreStatusClient) IsHeaderSyncComplete(ctx context.Context) (bool, error)

IsHeaderSyncComplete reports whether Bitcoin Core has finished downloading headers — block IBD may still be in progress. Enforcer only needs headers to start validating BIP300/301 activity (it syncs blocks alongside Core), so gating on IBD forces users to wait for the full chain when they don't have to. Signal: headers > 0 AND headers >= blocks AND we're past the "still connecting / no chain" bootstrap phase (headers > 10).

func (*CoreStatusClient) IsWalletLoaded

func (c *CoreStatusClient) IsWalletLoaded(ctx context.Context) (bool, error)

IsWalletLoaded checks if a wallet is loaded in Bitcoin Core.

func (*CoreStatusClient) ListDescriptors

func (c *CoreStatusClient) ListDescriptors(ctx context.Context, walletName string) (*ListDescriptorsResult, error)

func (*CoreStatusClient) ListTransactionsWallet

func (c *CoreStatusClient) ListTransactionsWallet(ctx context.Context, walletName string, count int) ([]CoreTransaction, error)

func (*CoreStatusClient) ListUnspentForAddresses

func (c *CoreStatusClient) ListUnspentForAddresses(ctx context.Context, walletName string, minConf int, addresses []string) ([]CoreUnspent, error)

func (*CoreStatusClient) ListUnspentWallet

func (c *CoreStatusClient) ListUnspentWallet(ctx context.Context, walletName string) ([]CoreUnspent, error)

func (*CoreStatusClient) ListWallets

func (c *CoreStatusClient) ListWallets(ctx context.Context) ([]string, error)

ListWallets returns the list of currently loaded wallets.

func (*CoreStatusClient) LoadWallet

func (c *CoreStatusClient) LoadWallet(ctx context.Context, walletName string) error

LoadWallet loads an existing wallet in Bitcoin Core.

func (*CoreStatusClient) Send

func (c *CoreStatusClient) Send(ctx context.Context, walletName string, destinations map[string]float64, feeRate float64) (string, error)

Send uses the "send" RPC (Core 22+) with multiple destinations.

func (*CoreStatusClient) SendRawTransaction

func (c *CoreStatusClient) SendRawTransaction(ctx context.Context, hexString string) (string, error)

func (*CoreStatusClient) SendToAddress

func (c *CoreStatusClient) SendToAddress(ctx context.Context, walletName, address string, amountBTC float64) (string, error)

SendToAddress sends BTC from the given wallet. Returns txid.

func (*CoreStatusClient) SignRawTransactionWithWallet

func (c *CoreStatusClient) SignRawTransactionWithWallet(ctx context.Context, walletName, hexString string) (*SignRawResult, error)

func (*CoreStatusClient) Stop

func (c *CoreStatusClient) Stop(ctx context.Context) error

Stop acks immediately; the caller must wait for process exit for the flush.

func (*CoreStatusClient) UnloadWallet

func (c *CoreStatusClient) UnloadWallet(ctx context.Context, walletName string) error

UnloadWallet unloads a wallet from Bitcoin Core.

type CoreTransaction

type CoreTransaction struct {
	Txid          string  `json:"txid"`
	Amount        float64 `json:"amount"`
	Fee           float64 `json:"fee"`
	Confirmations int64   `json:"confirmations"`
	BlockHash     string  `json:"blockhash,omitempty"`
	BlockTime     int64   `json:"blocktime,omitempty"`
	Time          int64   `json:"time"`
	TimeReceived  int64   `json:"timereceived"`
	Category      string  `json:"category"` // send, receive, generate, immature, orphan
	Address       string  `json:"address,omitempty"`
	Label         string  `json:"label,omitempty"`
	Vout          uint32  `json:"vout"`
}

type CoreTransactionDetail

type CoreTransactionDetail struct {
	Txid          string  `json:"txid"`
	Amount        float64 `json:"amount"`
	Fee           float64 `json:"fee"`
	Confirmations int64   `json:"confirmations"`
	BlockHash     string  `json:"blockhash,omitempty"`
	BlockTime     int64   `json:"blocktime,omitempty"`
	Time          int64   `json:"time"`
	TimeReceived  int64   `json:"timereceived"`
	Hex           string  `json:"hex"`
	Details       []struct {
		Address  string  `json:"address"`
		Category string  `json:"category"`
		Amount   float64 `json:"amount"`
		Vout     uint32  `json:"vout"`
		Fee      float64 `json:"fee,omitempty"`
	} `json:"details"`
}

type CoreUnspent

type CoreUnspent struct {
	Txid          string  `json:"txid"`
	Vout          uint32  `json:"vout"`
	Address       string  `json:"address"`
	Amount        float64 `json:"amount"`
	Confirmations int64   `json:"confirmations"`
	ScriptPubKey  string  `json:"scriptPubKey"`
	Spendable     bool    `json:"spendable"`
	Solvable      bool    `json:"solvable"`
	Safe          bool    `json:"safe"`
}

type CoreVariantSpec

type CoreVariantSpec struct {
	ID                string
	Subfolder         string
	BaseURL           string
	Files             map[string]string // os -> filename
	AvailableNetworks []string
}

CoreVariantSpec describes a single Bitcoin Core build variant.

func FilterVariantsForNetwork

func FilterVariantsForNetwork(variants map[string]CoreVariantSpec, network string) []CoreVariantSpec

FilterVariantsForNetwork returns variants available for the given network. "patched" is available on every chain — including mainnet — so the dropdown always has at least one item the user can pick.

func (CoreVariantSpec) AvailableOn

func (v CoreVariantSpec) AvailableOn(network string) bool

AvailableOn reports whether the variant is offered for the given network.

func (CoreVariantSpec) FileForOS

func (v CoreVariantSpec) FileForOS() (string, error)

FileForOS returns the variant's download filename for the current platform.

type DownloadManager

type DownloadManager struct {

	// CoreVariant returns the active Bitcoin Core variant spec to use for
	// download/extract. It is consulted only when config.IsBitcoinCore. May
	// be left nil — in that case the download falls back to the legacy
	// per-network file selection (default vs. forknet).
	CoreVariant func() (CoreVariantSpec, bool)

	// SidechainVariant resolves the test/alternative download spec for a
	// layer-2 binary. ok=false means use the production fields. The "test"
	// suffix is also used to namespace the in-flight key and the on-disk
	// extract dir so prod and test builds can coexist without clobbering.
	SidechainVariant func(BinaryConfig) (sidechainVariantSpec, bool)
	// contains filtered or unexported fields
}

func NewDownloadManager

func NewDownloadManager(dataDir, configFilePath string, log zerolog.Logger) *DownloadManager

func (*DownloadManager) Download

func (d *DownloadManager) Download(ctx context.Context, config BinaryConfig, network string, force bool) (<-chan DownloadProgress, error)

Download downloads a binary to the bin directory with progress reporting. It determines the download strategy based on config (GitHub vs direct).

func (*DownloadManager) State

func (d *DownloadManager) State(binaryName string) (DownloadState, bool)

State returns the latest download progress snapshot for a binary, keyed by its logical name (e.g. "bitcoind", "thunder"). ok=false means no download is in flight for that name. Read by Orchestrator.GetSyncStatus so the polled API can report download progress without callers needing to subscribe to the DownloadBinary / StartWithL1 streams.

type DownloadProgress

type DownloadProgress struct {
	// Progress in megabytes — bytes are converted at the source (downloadFile)
	// so every consumer (UI, logs, tests) sees the same units.
	MBDownloaded int64
	MBTotal      int64 // -1 if unknown
	Message      string
	Done         bool
	Error        error
}

type DownloadSource

type DownloadSource int
const (
	DownloadSourceDirect DownloadSource = iota // Direct URL from releases.drivechain.info
	DownloadSourceGitHub                       // GitHub releases API (regex matching)
)

type DownloadState

type DownloadState struct {
	MBDownloaded int64
	MBTotal      int64
	Message      string
	Running      bool
}

DownloadState is the in-memory snapshot of the latest progress event for a binary. The orchestrator's GetSyncStatus reads from here so the polled API can carry download progress without a separate stream — frontends never need to subscribe to DownloadBinary / StartWithL1 just to draw a progress bar.

type HealthCheckOpts

type HealthCheckOpts struct {
	User     string
	Password string
}

HealthCheckOpts provides optional configuration for health checkers.

type HealthCheckType

type HealthCheckType int
const (
	HealthCheckTCP        HealthCheckType = iota
	HealthCheckJSONRPC                    // JSON-RPC call (e.g. getblockcount)
	HealthCheckConnectRPC                 // Connect-JSON POST (e.g. cusf.mainchain.v1.ValidatorService/GetChainTip)
)

type HealthChecker

type HealthChecker interface {
	Check(ctx context.Context) error
}

HealthChecker checks if a binary is healthy.

func NewHealthChecker

func NewHealthChecker(config BinaryConfig, opts ...HealthCheckOpts) HealthChecker

NewHealthChecker creates the appropriate health checker for a binary config.

type JSONRPCHealthCheck

type JSONRPCHealthCheck struct {
	URL      string
	Method   string
	User     string
	Password string
	Timeout  time.Duration
}

JSONRPCHealthCheck sends a JSON-RPC request to verify the service is responding.

func (*JSONRPCHealthCheck) Check

func (h *JSONRPCHealthCheck) Check(ctx context.Context) error

type ListDescriptorsResult

type ListDescriptorsResult struct {
	WalletName  string `json:"wallet_name"`
	Descriptors []struct {
		Desc   string `json:"desc"`
		Active bool   `json:"active"`
		Range  []int  `json:"range,omitempty"`
	} `json:"descriptors"`
}

type LogEntry

type LogEntry struct {
	Timestamp time.Time
	Stream    string // "stdout" or "stderr"
	Line      string
}

LogEntry represents a line of output from a managed process.

type MainchainBalance

type MainchainBalance struct {
	Confirmed   float64
	Unconfirmed float64
}

MainchainBalance holds confirmed + unconfirmed balances from bitcoind.

type MainchainBlockchainInfo

type MainchainBlockchainInfo struct {
	Chain                string  `json:"chain"`
	Blocks               int     `json:"blocks"`
	Headers              int     `json:"headers"`
	BestBlockHash        string  `json:"bestblockhash"`
	Difficulty           float64 `json:"difficulty"`
	Time                 int64   `json:"time"`
	MedianTime           int64   `json:"mediantime"`
	VerificationProgress float64 `json:"verificationprogress"`
	InitialBlockDownload bool    `json:"initialblockdownload"`
	ChainWork            string  `json:"chainwork"`
	SizeOnDisk           int64   `json:"size_on_disk"`
	Pruned               bool    `json:"pruned"`
}

MainchainBlockchainInfo holds the result of bitcoind's getblockchaininfo.

type ManagedProcess

type ManagedProcess struct {
	Config  BinaryConfig
	Pid     int
	Cmd     *exec.Cmd
	Started time.Time
	Adopted bool // true if this process was found from a previous session
	// contains filtered or unexported fields
}

ManagedProcess represents a running process managed by the orchestrator.

func (*ManagedProcess) ExitCh

func (p *ManagedProcess) ExitCh() <-chan struct{}

ExitCh returns a channel that is closed when the process exits.

func (*ManagedProcess) ExitCode

func (p *ManagedProcess) ExitCode() int

ExitCode returns the process exit code (only valid after exitCh is closed).

func (*ManagedProcess) ExitDetails

func (p *ManagedProcess) ExitDetails() string

ExitDetails returns the rich crash message extracted from stderr / last error log lines. Empty if the process is still running or exited cleanly. Prefer this over ExitErr() in user-facing surfaces — ExitErr only carries the Go cmd.Wait status (e.g. "exit status 1"), while ExitDetails carries the actual reason the binary printed before dying.

func (*ManagedProcess) ExitErr

func (p *ManagedProcess) ExitErr() string

ExitErr returns the exit error string (only valid after exitCh is closed).

func (*ManagedProcess) RecentLogs

func (p *ManagedProcess) RecentLogs(n int) []LogEntry

RecentLogs returns the most recent log entries.

func (*ManagedProcess) Subscribe

func (p *ManagedProcess) Subscribe() (<-chan LogEntry, func())

Subscribe returns a channel that receives new log entries and a cancel function.

type Orchestrator

type Orchestrator struct {
	DataDir      string
	Network      string
	BitwindowDir string

	BitcoinConf    *config.BitcoinConfManager
	EnforcerConf   *config.EnforcerConfManager
	SidechainConfs map[string]*config.SidechainConfManager
	WalletSvc      *wallet.Service // for seed injection into sidechain/enforcer args
	WalletEngine   *WalletEngine   // manages wallet→Core mapping, sync, backend routing
	Settings       *SettingsStore
	// contains filtered or unexported fields
}

Orchestrator coordinates binary download, process management, and health checking.

func New

func New(dataDir, network, bitwindowDir string, configs []BinaryConfig, log zerolog.Logger) *Orchestrator

New creates a new Orchestrator.

func (*Orchestrator) AdoptOrphans

func (o *Orchestrator) AdoptOrphans(ctx context.Context) error

AdoptOrphans reads PID files from a previous session and adopts any processes that are still alive. Layer-2 PID files are namespaced by mode (e.g. thunder.pid vs thunder-test.pid) so we can attribute the right owner when the user has flipped the test-sidechains toggle between runs.

func (*Orchestrator) BinaryWalletPaths

func (o *Orchestrator) BinaryWalletPaths() []string

BinaryWalletPaths returns the per-binary on-disk wallet locations that a "Delete Wallet Files" / "Fully Obliterate" reset must remove. Mirrors the path enumeration used by collectPaths/StreamResetData so the wallet service's pre-deletion sweep agrees with the file-by-file pass that runs after — without that agreement, the sweep can miss `<datadir>/<network>/ wallets/` while the second pass deletes blockchain data, leaving the user's wallet alive against an empty chain (issue #1627).

func (*Orchestrator) Configs

func (o *Orchestrator) Configs() map[string]BinaryConfig

Configs returns the binary configs.

func (*Orchestrator) CoreStatusClient

func (o *Orchestrator) CoreStatusClient() (*CoreStatusClient, error)

CoreStatusClient builds a CoreStatusClient from the current config.

func (*Orchestrator) CoreVariant

func (o *Orchestrator) CoreVariant() string

CoreVariant returns the currently selected Bitcoin Core variant ID.

func (*Orchestrator) CreateCoreWallet

func (o *Orchestrator) CreateCoreWallet(walletName string, seedHex string) error

CreateCoreWallet creates a Bitcoin Core wallet from a seed via BIP84 descriptor import. Ported from bitwindow/server/engines/wallet_engine.go. This is called for non-enforcer (bitcoinCore type) wallets.

func (*Orchestrator) CreateCoreWatchOnlyWallet

func (o *Orchestrator) CreateCoreWatchOnlyWallet(walletName string, descriptorOrXpub string) error

CreateCoreWatchOnlyWallet creates a watch-only wallet in Bitcoin Core.

func (*Orchestrator) Download

func (o *Orchestrator) Download(ctx context.Context, name string, force bool) (<-chan DownloadProgress, error)

Download downloads a binary if missing (or forces re-download).

func (*Orchestrator) DownloadStateForTest

func (o *Orchestrator) DownloadStateForTest(name string) (DownloadState, bool)

DownloadStateForTest exposes the DownloadManager's per-binary state to tests in sibling packages (e.g. api/) so they can poll for completion without subscribing to a stream. Returns ok=true while the download is in flight.

func (*Orchestrator) GetBTCPrice

func (o *Orchestrator) GetBTCPrice() (float64, time.Time, error)

GetBTCPrice returns the current BTC/USD price, caching for 10 seconds.

func (*Orchestrator) GetMainchainBalance

func (o *Orchestrator) GetMainchainBalance(ctx context.Context) (*MainchainBalance, error)

GetMainchainBalance proxies getbalance + getunconfirmedbalance from bitcoind.

func (*Orchestrator) GetMainchainBlockchainInfo

func (o *Orchestrator) GetMainchainBlockchainInfo(ctx context.Context) (*MainchainBlockchainInfo, error)

GetMainchainBlockchainInfo proxies getblockchaininfo from bitcoind. The result is cached for [blockchainInfoCacheTTL]; concurrent callers across that window share a single in-flight RPC and the same answer.

func (*Orchestrator) GetSyncStatus

func (o *Orchestrator) GetSyncStatus(ctx context.Context) (*SyncStatus, error)

GetSyncStatus fans out concurrent probes — mainchain bitcoind, enforcer ValidatorService, plus every known sidechain — and returns them as one atomic snapshot. For each slot, an in-flight download takes precedence: if DownloadManager.State reports Running, the slot is filled with MB downloaded / MB total and IsDownloading=true; otherwise the live RPC is queried for the chain tip.

Per-chain errors are surfaced inline on ChainSyncResult.Error — the overall call only errors out when no probe could even be dispatched.

func (*Orchestrator) ListAll

func (o *Orchestrator) ListAll() []BinaryStatus

ListAll returns the status of every configured binary, sorted by chain layer (L1 first) then name.

func (*Orchestrator) ListCoreVariants

func (o *Orchestrator) ListCoreVariants() []CoreVariantSpec

ListCoreVariants returns the variants offered for the current network. On mainnet the slice is empty (the UI hides the picker entirely).

func (*Orchestrator) Logs

func (o *Orchestrator) Logs(name string) (<-chan LogEntry, func(), error)

Logs returns a channel of log entries for a binary and a cancel function.

func (*Orchestrator) PreviewResetData

func (o *Orchestrator) PreviewResetData(cat ResetCategory) ([]ResetFileInfo, error)

PreviewResetData returns the list of files/directories that would be deleted for the given categories, without performing any deletions.

func (*Orchestrator) ProcessManager

func (o *Orchestrator) ProcessManager() *ProcessManager

ProcessManager returns the underlying process manager (for direct access if needed).

func (*Orchestrator) RecentLogs

func (o *Orchestrator) RecentLogs(name string, n int) ([]LogEntry, error)

RecentLogs returns the most recent log entries for a binary.

func (*Orchestrator) RestartDaemon

func (o *Orchestrator) RestartDaemon(ctx context.Context, name string) (<-chan StartupProgress, error)

RestartDaemon stops the named binary and starts it again — single-daemon scope. Unlike StartWithL1, this never touches sibling daemons: restarting "enforcer" only restarts the enforcer; it never tries to spawn or adopt bitcoind. Use it for the "Restart" button on per-daemon UI cards.

The returned channel emits StartupProgress events the same way StartWithL1 does and is closed when the restart completes (or fails).

func (*Orchestrator) SetCoreVariant

func (o *Orchestrator) SetCoreVariant(ctx context.Context, id string) error

SetCoreVariant stops bitcoind, persists the new variant, ensures the binary is on disk for it, and restarts bitcoind. The whole sequence is serialised behind coreVariantMu so concurrent callers can't race the on-disk state. On stop failure we escalate to SIGKILL; if even that fails we abort before touching settings.

func (*Orchestrator) SetTestSidechains

func (o *Orchestrator) SetTestSidechains(ctx context.Context, enabled bool) error

SetTestSidechains flips the persisted test-sidechains toggle. The flow is:

  1. Stop every running layer-2 (sidechain) binary, escalating to SIGKILL on graceful failure.
  2. Persist the new value before any wipe so a crash leaves coherent state.
  3. Wipe on-disk binaries for both production and test layouts so the next launch redownloads from the correct source.

We don't auto-restart anything: the frontend triggers redownload + start on the user's next StartWithL1.

func (*Orchestrator) ShutdownAll

func (o *Orchestrator) ShutdownAll(ctx context.Context, force bool) (<-chan ShutdownProgress, error)

ShutdownAll stops all running binaries in reverse dependency order.

func (*Orchestrator) Start

func (o *Orchestrator) Start(ctx context.Context, name string, args []string, env map[string]string) (int, error)

Start starts a binary with the given args and env.

func (*Orchestrator) StartWithL1

func (o *Orchestrator) StartWithL1(ctx context.Context, target string, opts StartOpts) (<-chan StartupProgress, error)

StartWithL1 starts a binary along with its dependency chain: Bitcoin Core -> wait for wallet/IBD -> Enforcer -> target binary.

func (*Orchestrator) Status

func (o *Orchestrator) Status(name string) BinaryStatus

Status returns the current status of a binary.

func (*Orchestrator) Stop

func (o *Orchestrator) Stop(ctx context.Context, name string, force bool) error

Stop stops a running binary and marks its monitor as stopped so the restart timer won't automatically bring it back.

func (*Orchestrator) StopAllMonitors

func (o *Orchestrator) StopAllMonitors()

StopAllMonitors stops all connection monitor timers.

func (*Orchestrator) StreamResetData

func (o *Orchestrator) StreamResetData(ctx context.Context, cat ResetCategory) (<-chan ResetEvent, error)

StreamResetData stops affected binaries, then deletes data file-by-file, sending each deletion event to the returned channel. The final event has Done=true with summary counts.

func (*Orchestrator) SwapNetwork

func (o *Orchestrator) SwapNetwork(ctx context.Context, n config.Network) error

SwapNetwork performs an atomic Bitcoin network swap: stop running L2 sidechains + enforcer + bitcoind in reverse-dependency order, persist the new network to bitwindow-bitcoin.conf, refresh in-memory state, then restart the L1 stack if bitcoind/enforcer was running. Sidechains are intentionally not auto-restarted — the user re-launches them when they want to.

func (*Orchestrator) UpdateConfigs

func (o *Orchestrator) UpdateConfigs(configs []BinaryConfig)

UpdateConfigs replaces the binary configs with new ones (e.g. from a reloaded JSON file). Preserves Go-specific runtime state (running processes, health checks).

func (*Orchestrator) UseTestSidechains

func (o *Orchestrator) UseTestSidechains() bool

UseTestSidechains reports the persisted test-sidechains preference.

type OrchestratorSettings

type OrchestratorSettings struct {
	CoreVariant       string `json:"core_variant"`
	UseTestSidechains bool   `json:"use_test_sidechains"`
}

OrchestratorSettings is the on-disk shape of orchestrator_settings.json.

func LoadSettings

func LoadSettings(bitwindowDir string) (OrchestratorSettings, error)

LoadSettings reads orchestrator_settings.json, returning defaults if absent.

type PidFileManager

type PidFileManager struct {
	// contains filtered or unexported fields
}

PidFileManager handles PID file read/write/validate operations. PID files are stored at {dataDir}/pids/{binaryName}.pid

func NewPidFileManager

func NewPidFileManager(dataDir string, log zerolog.Logger) *PidFileManager

func (*PidFileManager) DeletePidFile

func (m *PidFileManager) DeletePidFile(binaryName string) error

func (*PidFileManager) ListPidFiles

func (m *PidFileManager) ListPidFiles() map[string]int

ListPidFiles returns all PID files and their PIDs.

func (*PidFileManager) ReadPidFile

func (m *PidFileManager) ReadPidFile(binaryName string) (int, error)

func (*PidFileManager) ValidatePid

func (m *PidFileManager) ValidatePid(pid int, binaryName string) bool

ValidatePid checks if a PID is alive and belongs to the expected binary. Returns true only if the process is alive AND the process name matches.

func (*PidFileManager) WritePidFile

func (m *PidFileManager) WritePidFile(binaryName string, pid int) error

type ProcessExitInfo

type ProcessExitInfo struct {
	Name     string
	ExitCode int
	ErrMsg   string // stderr-based error message, empty if clean exit
}

ProcessExitInfo is passed to the onExit callback when a process dies.

type ProcessManager

type ProcessManager struct {

	// CoreVariant resolves the binary path for Bitcoin Core when set. If nil
	// (or it returns ok=false), the default flat BinaryPath is used.
	CoreVariant func(config BinaryConfig) (CoreVariantSpec, bool)

	// SidechainVariant resolves the on-disk binary name for layer-2 test
	// builds. ok=false means use the production BinaryName + flat BinaryPath.
	SidechainVariant func(config BinaryConfig) (sidechainVariantSpec, bool)

	// OnExit is called when a process exits. The orchestrator uses this to
	// pipe exit errors into ConnectionMonitor.connectionError for the UI.
	OnExit func(ProcessExitInfo)

	// OnStartupLog is called when a process line matches one of the binary's
	// startup_log_patterns. The orchestrator pushes these to the UI so users
	// see a timeline of startup progress messages.
	// Dart: ProcessManager._captureStartupLog (process_manager.dart L380-395)
	OnStartupLog func(StartupLogEntry)
	// contains filtered or unexported fields
}

ProcessManager handles spawning, monitoring, and killing processes.

func NewProcessManager

func NewProcessManager(dataDir string, pidManager *PidFileManager, log zerolog.Logger) *ProcessManager

func (*ProcessManager) AdoptProcess

func (pm *ProcessManager) AdoptProcess(config BinaryConfig, pid int)

AdoptProcess registers an externally-found process (from a PID file).

func (*ProcessManager) Get

func (pm *ProcessManager) Get(name string) *ManagedProcess

Get returns the managed process for a binary, or nil if not running.

func (*ProcessManager) IsAdopted

func (pm *ProcessManager) IsAdopted(name string) bool

IsAdopted returns true if the named process was adopted (not started by us).

func (*ProcessManager) IsRunning

func (pm *ProcessManager) IsRunning(name string) bool

IsRunning checks if a binary is currently running.

func (*ProcessManager) ListRunning

func (pm *ProcessManager) ListRunning() []string

ListRunning returns the names of all running processes.

func (*ProcessManager) Remove

func (pm *ProcessManager) Remove(name string)

Remove removes a process from tracking without stopping it. Used for adopted processes that we don't own.

func (*ProcessManager) Start

func (pm *ProcessManager) Start(_ context.Context, config BinaryConfig, args []string, env map[string]string) (int, error)

Start launches a binary and returns its PID.

func (*ProcessManager) Stop

func (pm *ProcessManager) Stop(_ context.Context, name string, force bool) error

func (*ProcessManager) StopAll

func (pm *ProcessManager) StopAll(ctx context.Context, force bool) error

StopAll stops all running processes.

func (*ProcessManager) WaitForExit

func (pm *ProcessManager) WaitForExit(name string, timeout time.Duration) bool

type RawTransaction

type RawTransaction struct {
	Txid     string `json:"txid"`
	Hash     string `json:"hash"`
	Size     int64  `json:"size"`
	Vsize    int64  `json:"vsize"`
	Weight   int64  `json:"weight"`
	Version  int32  `json:"version"`
	Locktime uint32 `json:"locktime"`
	Vin      []struct {
		Txid      string `json:"txid"`
		Vout      uint32 `json:"vout"`
		Coinbase  string `json:"coinbase,omitempty"`
		ScriptSig *struct {
			Asm string `json:"asm"`
			Hex string `json:"hex"`
		} `json:"scriptSig,omitempty"`
		Witness  []string `json:"txinwitness,omitempty"`
		Sequence uint32   `json:"sequence"`
	} `json:"vin"`
	Vout []struct {
		Value        float64 `json:"value"`
		N            uint32  `json:"n"`
		ScriptPubKey struct {
			Asm     string `json:"asm"`
			Hex     string `json:"hex"`
			Type    string `json:"type"`
			Address string `json:"address,omitempty"`
		} `json:"scriptPubKey"`
	} `json:"vout"`
	Blockhash     string `json:"blockhash,omitempty"`
	Confirmations int64  `json:"confirmations"`
	BlockTime     int64  `json:"blocktime,omitempty"`
}

type ResetCategory

type ResetCategory struct {
	DeleteBlockchainData bool
	DeleteNodeSoftware   bool
	DeleteLogs           bool
	DeleteSettings       bool
	DeleteWalletFiles    bool
	AlsoResetSidechains  bool
}

ResetCategory defines which data categories to delete.

type ResetEvent

type ResetEvent struct {
	Path         string
	Category     string
	Success      bool
	Error        string
	Done         bool
	DeletedCount int
	FailedCount  int
}

ResetEvent is emitted for each file deletion during a streaming reset.

type ResetFileInfo

type ResetFileInfo struct {
	Path        string
	Category    string
	SizeBytes   int64
	IsDirectory bool
}

ResetFileInfo describes a single file/directory that would be affected by a reset.

type SettingsStore

type SettingsStore struct {
	// contains filtered or unexported fields
}

SettingsStore is a thread-safe in-memory cache around orchestrator_settings.json.

func NewSettingsStore

func NewSettingsStore(bitwindowDir string) (*SettingsStore, error)

NewSettingsStore loads (or initialises) the on-disk settings.

func (*SettingsStore) CoreVariant

func (s *SettingsStore) CoreVariant() string

func (*SettingsStore) Get

func (*SettingsStore) SetCoreVariant

func (s *SettingsStore) SetCoreVariant(id string) (string, error)

SetCoreVariant persists a new variant ID and returns the previous value.

func (*SettingsStore) SetUseTestSidechains

func (s *SettingsStore) SetUseTestSidechains(v bool) (bool, error)

SetUseTestSidechains persists the new value and returns the previous one.

func (*SettingsStore) UseTestSidechains

func (s *SettingsStore) UseTestSidechains() bool

type ShutdownProgress

type ShutdownProgress struct {
	TotalCount     int
	CompletedCount int
	CurrentBinary  string
	Done           bool
	Error          error
}

ShutdownProgress reports progress during ShutdownAll.

type SignRawResult

type SignRawResult struct {
	Hex      string `json:"hex"`
	Complete bool   `json:"complete"`
}

type StartOpts

type StartOpts struct {
	TargetArgs   []string
	TargetEnv    map[string]string
	CoreArgs     []string
	EnforcerArgs []string
	Immediate    bool // start target without waiting for L1
}

StartOpts configures a StartWithL1 call.

type StartupLogEntry

type StartupLogEntry struct {
	Name      string
	Timestamp time.Time
	Message   string
}

StartupLogEntry is passed to the OnStartupLog callback when a process line matches one of the binary's startup_log_patterns. Used by the UI to show a timeline of startup progress messages.

type StartupLogLine

type StartupLogLine struct {
	Timestamp time.Time
	Message   string
}

StartupLogLine is a timestamped startup progress message.

type StartupProgress

type StartupProgress struct {
	Stage        string // e.g. "downloading-bitcoind", "starting-bitcoind", "waiting-ibd"
	Message      string
	Done         bool
	Error        error
	MBDownloaded int64
	MBTotal      int64
}

StartupProgress reports progress during StartWithL1. Download fields are in megabytes (matches DownloadProgress).

type SyncStatus

type SyncStatus struct {
	Mainchain  *ChainSyncResult
	Enforcer   *ChainSyncResult
	Sidechains map[string]*ChainSyncResult
}

SyncStatus is the atomic snapshot returned by GetSyncStatus. Mainchain + enforcer are always populated; Sidechains carries one entry per orchestrator-managed L2 sidechain binary, keyed by the binary's logical name. Frontends that aren't sidechains (e.g. bitwindow's own bitwindowd daemon) are NOT in this map — the orchestrator knows nothing about them.

type TCPHealthCheck

type TCPHealthCheck struct {
	Host    string
	Port    int
	Timeout time.Duration
}

TCPHealthCheck verifies a port is accepting connections.

func (*TCPHealthCheck) Check

func (h *TCPHealthCheck) Check(ctx context.Context) error

type WalletBackendType

type WalletBackendType string

WalletBackendType determines where wallet operations are routed.

const (
	WalletBackendEnforcer    WalletBackendType = "enforcer"
	WalletBackendBitcoinCore WalletBackendType = "bitcoinCore"
	WalletBackendWatchOnly   WalletBackendType = "watchOnly"
)

type WalletEngine

type WalletEngine struct {
	// contains filtered or unexported fields
}

WalletEngine manages the lifecycle of Bitcoin Core wallets created from wallet.json seeds.

func NewWalletEngine

func NewWalletEngine(
	walletSvc *wallet.Service,
	coreClient func() (*CoreStatusClient, error),
	network string,
	log zerolog.Logger,
) *WalletEngine

NewWalletEngine creates a new WalletEngine.

func (*WalletEngine) BumpCoreFee

func (e *WalletEngine) BumpCoreFee(ctx context.Context, walletID, txid string) (*BumpFeeResult, error)

BumpCoreFee bumps the fee for a transaction in a Bitcoin Core wallet.

func (*WalletEngine) ClearCache

func (e *WalletEngine) ClearCache()

ClearCache clears the Core wallet name cache. Called on wallet delete/wipe.

func (*WalletEngine) EnsureBitcoinCoreWallet

func (e *WalletEngine) EnsureBitcoinCoreWallet(ctx context.Context, walletID string) (string, error)

EnsureBitcoinCoreWallet ensures a Bitcoin Core wallet exists for walletID. Creates it from the seed if it doesn't exist (lazy loading). Returns the Core wallet name.

func (*WalletEngine) EnsureWatchOnlyWallet

func (e *WalletEngine) EnsureWatchOnlyWallet(ctx context.Context, walletID string) (string, error)

EnsureWatchOnlyWallet ensures a watch-only wallet exists for walletID. Creates it if it doesn't exist (lazy loading). Returns the Core wallet name.

func (*WalletEngine) GetBalance

func (e *WalletEngine) GetBalance(ctx context.Context, walletID string) (confirmedSats, pendingSats uint64, err error)

GetBalance returns the balance for a wallet, routing to the correct backend.

func (*WalletEngine) GetCoreWalletName

func (e *WalletEngine) GetCoreWalletName(ctx context.Context, walletID string) (string, error)

GetCoreWalletName returns the Bitcoin Core wallet name for a walletID. Calls EnsureBitcoinCoreWallet to lazy-create if needed.

func (*WalletEngine) GetNewCoreAddress

func (e *WalletEngine) GetNewCoreAddress(ctx context.Context, walletID string) (string, error)

GetNewCoreAddress gets a new address from Bitcoin Core for the given wallet.

func (*WalletEngine) GetWalletBackendType

func (e *WalletEngine) GetWalletBackendType(walletID string) (WalletBackendType, error)

GetWalletBackendType returns the backend type for a wallet.

func (*WalletEngine) ListCoreTransactions

func (e *WalletEngine) ListCoreTransactions(ctx context.Context, walletID string, count int) ([]CoreTransaction, error)

ListCoreTransactions lists transactions for a Bitcoin Core wallet.

func (*WalletEngine) ListCoreUnspent

func (e *WalletEngine) ListCoreUnspent(ctx context.Context, walletID string) ([]CoreUnspent, error)

ListCoreUnspent lists UTXOs for a Bitcoin Core wallet.

func (*WalletEngine) SendFromCoreWallet

func (e *WalletEngine) SendFromCoreWallet(ctx context.Context, walletID string, destinations map[string]float64, feeRate float64) (string, error)

SendFromCoreWallet sends BTC from a Bitcoin Core wallet.

func (*WalletEngine) SyncWallets

func (e *WalletEngine) SyncWallets(ctx context.Context) error

SyncWallets ensures all bitcoinCore wallets in wallet.json exist in Bitcoin Core. Called after wallet unlock. Errors are logged but do not fail the sync.

type WalletInfo

type WalletInfo struct {
	WalletName string `json:"walletname"`
	Format     string `json:"format"`
	TxCount    int64  `json:"txcount"`
}

Directories

Path Synopsis
cmd
orchestratorctl command
orchestratord command
gen
bitassets
Package bitassets provides a JSON-RPC client for the Bitassets sidechain.
Package bitassets provides a JSON-RPC client for the Bitassets sidechain.
bitnames
Package bitnames provides a JSON-RPC client for the BitNames sidechain.
Package bitnames provides a JSON-RPC client for the BitNames sidechain.
coinshift
Package coinshift provides a JSON-RPC client for the Coinshift sidechain.
Package coinshift provides a JSON-RPC client for the Coinshift sidechain.
photon
Package photon provides a JSON-RPC client for the Photon sidechain.
Package photon provides a JSON-RPC client for the Photon sidechain.
thunder
Package thunder provides a JSON-RPC client for the Thunder sidechain.
Package thunder provides a JSON-RPC client for the Thunder sidechain.
truthcoin
Package truthcoin provides a JSON-RPC client for the Truthcoin sidechain.
Package truthcoin provides a JSON-RPC client for the Truthcoin sidechain.
zside
Package zside provides a JSON-RPC client for the Zside sidechain.
Package zside provides a JSON-RPC client for the Zside sidechain.
Package testharness provides a reusable integration test harness for the wallet stack.
Package testharness provides a reusable integration test harness for the wallet stack.
bip47send
Package bip47send drives the orchestrator-side BIP47 send flow for bitcoinCore wallets: per-payment address derivation and notification transaction assembly.
Package bip47send drives the orchestrator-side BIP47 send flow for bitcoinCore wallets: per-payment address derivation and notification transaction assembly.
bip47state
Package bip47state persists the per-recipient BIP47 send state (notification txid, next per-payment derivation index) used by the orchestrator's send path.
Package bip47state persists the per-recipient BIP47 send state (notification txid, next per-payment derivation index) used by the orchestrator's send path.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL