module Jolteon.Traces.Trace02 where

open import Prelude
open import Jolteon.Traces.Core

s₂′ : GlobalState
s₂′ =
  record
  { currentTime   = 24
  ; history       = v₃ 𝔹  p₃  h₂
  ; networkBuffer = []
  ; stateMap      =
     2 , 3 , qc₂ , nothing , Receiving , v₂ 𝔹  ldb₂ , [ v₁ 𝔹  p₃  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
    2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ] , [] , nothing , false , true 
    3 , 3 , qc₂ , nothing , EnteringRound , db₃ , [] , [ b₁ ] , nothing , false , true 
   []
  }

s₂″ : GlobalState
s₂″ =
  record s₂′
  { history       = v₃ 𝕃  v₃ 𝔹  p₃  h₂
  ; networkBuffer = [ 24 , 𝕃 , v₃ 𝕃 ]
  ; stateMap      =
     3 , 3 , qc₂ , nothing , AdvancingRound , ldb₃ , [ v₁ 𝔹 ] , [ b₁ ] , just 25 , false , false 
    2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
    3 , 3 , qc₂ , nothing , EnteringRound , db₃ , []  , [ b₁ ] , nothing , false , true 
   []
  }

opaque
  unfolding blockPayload chainPayload

  trace02 : s₂ —↠ s₂′
  trace02 =
    begin
      s₂
    —→⟨ 𝕃 :VoteBlockNoOp? 
      s₂  𝕃 %=  ls  record ls {phase = EnteringRound})
    —→⟨ 𝕃 :InitNoTC? 
      s₂  𝕃   2 , 3 , qc₂ , nothing , Proposing , ldb₂ , [ v₁ 𝔹  v₂ 𝔹 ] , [ b₁ ] , just 25 , false , false 
    —→⟨ 𝕃 :ProposeBlock? [] 
      record s₂
      { history       = p₃  h₂
      ; networkBuffer = [ 13 , 𝕃 , p₃  13 , 𝔸 , p₃  13 , 𝔹 , p₃ ]
      ; stateMap      = s₂ .stateMap
      [ 𝕃 ]≔  2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹 ] , [ b₁ ] , just 25 , false , false 
      }
    —→⟨ 𝔹 :InitNoTC? 
      record s₂
      { history       = p₃  h₂
      ; networkBuffer = [ 13 , 𝕃 , p₃  13 , 𝔸 , p₃  13 , 𝔹 , p₃ ]
      ; stateMap      = s₂ .stateMap
      [ 𝕃 ]≔  2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹 ] , [ b₁ ] , just 25 , false , false 
      [ 𝔹 ]≔  2 , 2 , qc₁ , nothing , Proposing , [ p₂  p₁ ] , [] , [] , just 25 , false , false 
      }
    —→⟨ 𝔹 :ProposeBlockNoOp? 
      record s₂
      { history       = p₃  h₂
      ; networkBuffer = [ 13 , 𝕃 , p₃  13 , 𝔸 , p₃  13 , 𝔹 , p₃ ]
      ; stateMap      = s₂ .stateMap
      [ 𝕃 ]≔  2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹 ] , [ b₁ ] , just 25 , false , false 
      [ 𝔹 ]≔  2 , 2 , qc₁ , nothing , Receiving , [ p₂  p₁ ] , [] , [] , just 25 , false , false 
      }
    —→⟨ Deliver? (13 , 𝕃 , p₃) 
      record s₂
      { history       = p₃  h₂
      ; networkBuffer = [ 13 , 𝔸 , p₃  13 , 𝔹 , p₃ ]
      ; stateMap      = s₂ .stateMap
      [ 𝕃 ]≔  2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹  p₃ ] , [ b₁ ] , just 25 , false , false 
      [ 𝔹 ]≔  2 , 2 , qc₁ , nothing , Receiving , [ p₂  p₁ ] , [] , [] , just 25 , false , false 
      }
    —→⟨ Deliver? (13 , 𝔸 , p₃) 
      record s₂
      { history       = p₃  h₂
      ; networkBuffer = [ 13 , 𝔹 , p₃ ]
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹  p₃ ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ] , [] , nothing , false , true 
        2 , 2 , qc₁ , nothing , Receiving , [ p₂  p₁ ] , [] , [] , just 25 , false , false 
       []
      }
    —→⟨ Deliver? (13 , 𝔹 , p₃) 
      record s₂
      { history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹  p₃ ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ] , [] , nothing , false , true 
        2 , 2 , qc₁ , nothing , Receiving , [ p₂  p₁ ] , [ p₃ ] , [] , just 25 , false , false 
       []
      }
    —→⟨ WaitUntil? 19 
      record
      { currentTime   = 19
      ; history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹  p₃ ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound  , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        2 , 2 , qc₁ , nothing , Receiving , [ p₂  p₁ ] , [ p₃ ]  , []  , just 25 , false , false 
       []
      }
    —→⟨ 𝔹 :RegisterProposal? 
      record
      { currentTime   = 19
      ; history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹  p₃ ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        2 , 2 , qc₁ , nothing , AdvancingRound , [ p₃  p₂  p₁ ] , []  , []  , just 25 , false , false 
       []
      }
    —→⟨ 𝔹 :AdvanceRoundQC? qc₂ 
      record
      { currentTime   = 19
      ; history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , _ , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        2 , 3 , qc₁ , nothing , AdvancingRound , db₃ , []  , []  , nothing , false , true 
       []
      }
    —→⟨ 𝔹 :AdvanceRoundNoOp? 
      record
      { currentTime   = 19
      ; history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , _ , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        2 , 3 , qc₁ , nothing , Locking , db₃ , []  , []  , nothing , false , true 
       []
      }
    —→⟨ 𝔹 :Lock? 
      record
      { currentTime   = 19
      ; history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , _ , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        2 , 3 , qc₂ , nothing , Committing , db₃ , []  , []  , nothing , false , true 
       []
      }
      -- note that as 𝔹 is about to commit using b₂, but the current proposal is b₃.
    —→⟨ 𝔹 :Commit? [ b₂  b₁ ] 
      record
      { currentTime   = 19
      ; history       = p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , _ , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        2 , 3 , qc₂ , nothing , Voting  , db₃ , []  , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝔹 :VoteBlock? b₃ 
      record
      { currentTime   = 19
      ; history       = v₃ 𝔹  p₃  h₂
      ; networkBuffer = [ 19 , 𝕃 , v₃ 𝔹 ]
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , _ , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound  , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound  , db₃ , []  , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ Deliver? (19 , 𝕃 , v₃ 𝔹) 
      _
    —→⟨ WaitUntil? 24 
      record
      { currentTime   = 24
      ; history       = v₃ 𝔹  p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Receiving , ldb₂ , [ v₁ 𝔹  v₂ 𝔹  p₃  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ] , [] , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , [] , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝕃 :RegisterVote? b₂ 
      record
      { currentTime   = 24
      ; history       = v₃ 𝔹  p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , AdvancingRound , v₂ 𝔹  ldb₂ , [ v₁ 𝔹  p₃  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ] , [] , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , [] , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝕃 :AdvanceRoundNoOp? 
      _
    —→⟨ 𝕃 :Lock? 
      record
      { currentTime   = 24
      ; history       = v₃ 𝔹  p₃  h₂
      ; networkBuffer = []
      ; stateMap      =
         2 , 3 , qc₂ , nothing , Committing , v₂ 𝔹  ldb₂ , [ v₁ 𝔹  p₃  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ] , [] , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , [] , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝕃 :CommitNoOp? 
      _
    —→⟨ 𝕃 :VoteBlockNoOp? 
      s₂′
    

  _ : s₂′ —↠ s₂″
  _ =
    begin
      s₂′
    —→⟨ 𝕃 :RegisterProposal? 
      record s₂′
      { stateMap      =
         2 , 3 , qc₂ , nothing , AdvancingRound , p₃  v₂ 𝔹  ldb₂ , [ v₁ 𝔹  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , []  , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝕃 :AdvanceRoundNoOp? 
      _
    —→⟨ 𝕃 :Lock? 
      record s₂′
      { stateMap      =
         2 , 3 , qc₂ , nothing , Committing , p₃  v₂ 𝔹  ldb₂ , [ v₁ 𝔹  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , []  , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝕃 :CommitNoOp? 
      _
    —→⟨ 𝕃 :VoteBlock? b₃ 
      record s₂′
      { history       = v₃ 𝕃  v₃ 𝔹  p₃  h₂
      ; networkBuffer = [ 24 , 𝕃 , v₃ 𝕃 ]
      ; stateMap      =
         3 , 3 , qc₂ , nothing , Receiving , p₃  v₂ 𝔹  ldb₂ , [ v₁ 𝔹  v₃ 𝔹 ] , [ b₁ ] , just 25 , false , false 
        2 , 2 , qc₁ , nothing , EnteringRound , [ p₂  p₁ ] , [ p₃ ]  , []  , nothing , false , true 
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , []  , [ b₁ ] , nothing , false , true 
       []
      }
    —→⟨ 𝕃 :RegisterVote? b₃ 
      s₂″
    

  _ : s₂″ —↠ s₃
  _ = begin
      s₂″
    —→⟨ 𝔸 :InitNoTC? 
      record s₂″
      { stateMap      =
        _
        2 , 2 , qc₁ , nothing , Proposing , [ p₂  p₁ ] , [ p₃ ] , [] , just 36 , false , false 
       _
       []
      }
    —→⟨ 𝔸 :ProposeBlockNoOp? 
      _
    —→⟨ 𝔸 :RegisterProposal? 
      record s₂″
      { stateMap      =
        _
        2 , 2 , qc₁ , nothing , AdvancingRound , [ p₃  p₂  p₁ ] , [] , [] , just 36 , false , false 
       _
       []
      }
    —→⟨ 𝔸 :AdvanceRoundQC? qc₂ 
      record s₂″
      { stateMap      =
        _
        2 , 3 , qc₁ , nothing , AdvancingRound , db₃ , [] , [] , nothing , false , true 
       _
       []
      }
    —→⟨ 𝔸 :AdvanceRoundNoOp? 
      record s₂″
      { stateMap      =
        _
        2 , 3 , qc₁ , nothing , Locking , db₃ , [] , [] , nothing , false , true 
       _
       []
      }
    —→⟨ 𝔸 :Lock? 
      record s₂″
      { stateMap      =
        _
        2 , 3 , qc₂ , nothing , Committing , db₃ , [] , [] , nothing , false , true 
       _
       []
      }
    —→⟨ 𝔸 :Commit? [ b₂  b₁ ] 
      record s₂″
      { stateMap      =
        _
        2 , 3 , qc₂ , nothing , Voting , db₃ , [] , [ b₁ ] , nothing , false , true 
       _
       []
      }
    —→⟨ 𝔸 :VoteBlock? b₃ 
      record s₂″
      { history       = v₃ 𝔸  v₃ 𝕃  v₃ 𝔹  p₃  h₂
      ; networkBuffer = [ 24 , 𝕃 , v₃ 𝕃  24 , 𝕃 , v₃ 𝔸 ]
      ; stateMap      =
        _
        3 , 3 , qc₂ , nothing , EnteringRound , db₃ , [] , [ b₁ ] , nothing , false , true 
       _
       []
      }