Skip to content

LAUNCHING FSM state#462

Open
freemans13 wants to merge 6 commits intobsv-blockchain:mainfrom
freemans13:stu/launching-fsm-state
Open

LAUNCHING FSM state#462
freemans13 wants to merge 6 commits intobsv-blockchain:mainfrom
freemans13:stu/launching-fsm-state

Conversation

@freemans13
Copy link
Collaborator

@freemans13 freemans13 commented Jan 30, 2026

Summary

Adds a new LAUNCHING FSM state to fix a race condition where subtree validation could process transactions for future blocks during node catchup, causing "Coinbase UTXO can only be spent when it matures" errors.

Problem

During node catchup, the following race condition occurred:

  1. Operator transitions node from IDLE → RUNNING
  2. Subtree validation immediately starts processing Kafka messages
  3. Block validation checks sync status (takes time)
  4. Block validation finds we're behind peers, switches to CATCHINGBLOCKS
  5. But subtree validation already has in-flight validations with wrong height context

Solution

Add a new intermediate LAUNCHING state that:

  • Is entered when operator triggers node to start (instead of going directly to RUNNING)
  • Blocks subtree validation (like CATCHINGBLOCKS and IDLE)
  • Allows block validation to perform sync check
  • Auto-transitions to RUNNING (if synced) or CATCHINGBLOCKS (if behind)

New FSM Flow

IDLE → LAUNCHING → RUNNING (if synced with peers)
              ↘ CATCHINGBLOCKS (if behind peers) → RUNNING

RUNNING → CATCHINGBLOCKS (normal mid-operation catchup)

LEGACYSYNC Path (Unchanged)

LEGACYSYNC is a separate path that bypasses LAUNCHING entirely:

IDLE → LEGACYSYNCING → RUNNING

This is intentional because legacy sync connects to old Bitcoin SV nodes and has its own sync mechanism built-in.

Changes

Core FSM Changes

  • blockchain_api.proto: Added LAUNCHING state (value 4) and LAUNCH event (value 4)
  • fsm.go: Added LAUNCHING transitions; RUN no longer valid from IDLE
  • Server.go: Added Launch() gRPC handler; auto-transition LAUNCHING→RUNNING in test mode
  • Interface.go: Added Launch() to ClientI interface
  • Client.go: Added FSMStateLAUNCHING, FSMEventLAUNCH constants and Launch() method
  • mock.go, LocalClient.go: Added Launch() implementations

Service Updates

  • asset/httpimpl/fsm_handler.go: Returns LAUNCH (not RUN) for IDLE state
  • subtreevalidation/subtreeHandler.go: Skips processing in LAUNCHING and IDLE states

Test Infrastructure

  • daemon/test_daemon.go, daemon_test.go: Changed LocalTestStartFromState to "LAUNCHING"
  • test/nodeHelpers/blockchainDaemon.go: Calls Launch() then Run() for proper FSM transitions
  • fsm_test.go: Updated tests for new IDLE → LAUNCHING → RUNNING flow
  • blockpersister/Server_test.go, blockvalidation/InvalidBlocksKafkaProducer_test.go: Added Launch() to mock clients

Dashboard UI

  • admin/+page.svelte: Added LAUNCHING state display, LAUNCH event button with 🚀 icon
  • api/index.ts: Added LAUNCH event value mapping
  • connected-nodes-card/data.ts: Added LAUNCHING emoji (🚀) for node status

Testing

  • All FSM unit tests pass
  • All 56 smoke tests pass (15 skipped as expected)
  • Lint passes with 0 issues

Test Mode Behavior

When LocalTestStartFromState = "LAUNCHING", the blockchain service:

  1. Sets FSM to LAUNCHING state
  2. Auto-fires RUN event to transition to RUNNING state
  3. Stores final RUNNING state in database

This ensures tests run with FSM in RUNNING state while still validating the LAUNCHING→RUNNING transition.

Breaking Changes

  • Run() is no longer valid from IDLE state - must use Launch() first
  • LocalTestStartFromState can only be "IDLE" or "LAUNCHING", not "RUNNING"

🤖 Generated with Claude Code

@freemans13 freemans13 self-assigned this Jan 30, 2026
@freemans13 freemans13 marked this pull request as draft January 30, 2026 20:38
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
50.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@freemans13 freemans13 marked this pull request as ready for review January 31, 2026 02:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant