From 1d5b1c564ab6f08afa0170f1cfad5a90e93246e3 Mon Sep 17 00:00:00 2001 From: Gustavo Stingelin Date: Sat, 18 Jul 2026 15:30:49 -0300 Subject: [PATCH] fsm: make diagram generation deterministic --- fsm/example_fsm.md | 4 ++-- fsm/stateparser/stateparser.go | 18 ++++++++++++++++-- instantout/fsm.md | 32 +++++++++++++++++++------------- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/fsm/example_fsm.md b/fsm/example_fsm.md index 882d3404..7de06445 100644 --- a/fsm/example_fsm.md +++ b/fsm/example_fsm.md @@ -2,11 +2,11 @@ stateDiagram-v2 [*] --> InitFSM: OnRequestStuff InitFSM -InitFSM --> StuffSentOut: OnStuffSentOut InitFSM --> StuffFailed: OnError +InitFSM --> StuffSentOut: OnStuffSentOut StuffFailed StuffSentOut -StuffSentOut --> StuffSuccess: OnStuffSuccess StuffSentOut --> StuffFailed: OnError +StuffSentOut --> StuffSuccess: OnStuffSuccess StuffSuccess ``` \ No newline at end of file diff --git a/fsm/stateparser/stateparser.go b/fsm/stateparser/stateparser.go index cafedd7d..f1e78ab1 100644 --- a/fsm/stateparser/stateparser.go +++ b/fsm/stateparser/stateparser.go @@ -86,8 +86,11 @@ func writeMermaidFile(filename string, states fsm.States) error { state = "[*]" } // write transitions - for edge, target := range edges.Transitions { - fmt.Fprintf(&b, "%s --> %s: %s\n", state, target, edge) + for _, edge := range sortedTransitionKeys(edges.Transitions) { + fmt.Fprintf( + &b, "%s --> %s: %s\n", state, + edges.Transitions[fsm.EventType(edge)], edge, + ) } } @@ -110,3 +113,14 @@ func sortedKeys(m fsm.States) []string { sort.Strings(keys) return keys } + +func sortedTransitionKeys(m fsm.Transitions) []string { + keys := make([]string, len(m)) + i := 0 + for k := range m { + keys[i] = string(k) + i++ + } + sort.Strings(keys) + return keys +} diff --git a/instantout/fsm.md b/instantout/fsm.md index 4b90fb27..a709aa68 100644 --- a/instantout/fsm.md +++ b/instantout/fsm.md @@ -2,35 +2,41 @@ stateDiagram-v2 [*] --> Init: OnStart BuildHtlc +BuildHtlc --> InstantOutFailed: OnError BuildHtlc --> PushPreimage: OnHtlcSigReceived -BuildHtlc --> InstantFailedOutFailed: OnError -BuildHtlc --> InstantFailedOutFailed: OnRecover +BuildHtlc --> InstantOutFailed: OnRecover FailedHtlcSweep +FailedHtlcSweep --> PublishHtlcSweep: OnRecover +FinishedHtlcPreimageSweep FinishedSweeplessSweep Init +Init --> InstantOutFailed: OnError Init --> SendPaymentAndPollAccepted: OnInit -Init --> InstantFailedOutFailed: OnError -Init --> InstantFailedOutFailed: OnRecover -InstantFailedOutFailed +Init --> InstantOutFailed: OnRecover +InstantOutFailed PublishHtlc PublishHtlc --> FailedHtlcSweep: OnError +PublishHtlc --> PublishHtlcSweep: OnHtlcPublished PublishHtlc --> PublishHtlc: OnRecover -PublishHtlc --> WaitForHtlcSweepConfirmed: OnHtlcBroadcasted +PublishHtlcSweep +PublishHtlcSweep --> FailedHtlcSweep: OnError +PublishHtlcSweep --> WaitForHtlcSweepConfirmed: OnHtlcSweepPublished +PublishHtlcSweep --> PublishHtlcSweep: OnRecover PushPreimage +PushPreimage --> InstantOutFailed: OnError +PushPreimage --> PublishHtlc: OnErrorPublishHtlc PushPreimage --> PushPreimage: OnRecover PushPreimage --> WaitForSweeplessSweepConfirmed: OnSweeplessSweepPublished -PushPreimage --> InstantFailedOutFailed: OnError -PushPreimage --> PublishHtlc: OnErrorPublishHtlc SendPaymentAndPollAccepted +SendPaymentAndPollAccepted --> InstantOutFailed: OnError SendPaymentAndPollAccepted --> BuildHtlc: OnPaymentAccepted -SendPaymentAndPollAccepted --> InstantFailedOutFailed: OnError -SendPaymentAndPollAccepted --> InstantFailedOutFailed: OnRecover +SendPaymentAndPollAccepted --> InstantOutFailed: OnRecover WaitForHtlcSweepConfirmed +WaitForHtlcSweepConfirmed --> FailedHtlcSweep: OnError WaitForHtlcSweepConfirmed --> FinishedHtlcPreimageSweep: OnHtlcSwept WaitForHtlcSweepConfirmed --> WaitForHtlcSweepConfirmed: OnRecover -WaitForHtlcSweepConfirmed --> FailedHtlcSweep: OnError WaitForSweeplessSweepConfirmed -WaitForSweeplessSweepConfirmed --> FinishedSweeplessSweep: OnSweeplessSweepConfirmed -WaitForSweeplessSweepConfirmed --> WaitForSweeplessSweepConfirmed: OnRecover WaitForSweeplessSweepConfirmed --> PublishHtlc: OnError +WaitForSweeplessSweepConfirmed --> WaitForSweeplessSweepConfirmed: OnRecover +WaitForSweeplessSweepConfirmed --> FinishedSweeplessSweep: OnSweeplessSweepConfirmed ``` \ No newline at end of file