Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typed transitions #228

Merged
merged 14 commits into from
Feb 24, 2022
Merged

Typed transitions #228

merged 14 commits into from
Feb 24, 2022

Conversation

KtorZ
Copy link
Collaborator

@KtorZ KtorZ commented Feb 22, 2022

(Opening for the sake of discussion... the two last commits are probably salvageable but the first one is up to debate 😬).

  • 📍 Make transitions visible at the type-level.
    Not sure I want to commit that as this is venturing more and more in
    the lands of dependent-types... therefore adding complexity to the
    code for actually here little gain apart from a more descriptive
    module API.

    What motivated this change initially was an attempt at simplifying the
    underlying test-code where we do know exactly what transition we want
    to do. Thus, getting back an opaque 'SomeOnChainHeadState' forces some
    needless unwrapping via reify state. It ain't much, as we are really
    just talking about one case/pattern-match but still... that was the
    initial motivation. With this new approach, we can remove that extra
    pattern match on call-sites by using transition directly, with some
    type annotation as for the transition we expect and tada! Yet.. the
    definitions are a bit more complex now as I added a new type-class and
    some glue to make things work :/

  • 📍 write another property on commit transition.
    can only apply/observe the same commit once.

  • 📍 dry a bit the StateSpec: define forAllCommit.

  • 📍 Add property tests for 'init' at the Direct.State level.

  • 📍 Add property test for observing a CollectCom tx from the 'State' module perspective.

  • 📍 Rename 'transition' -> 'observeTx'

  • 📍 Minor cosmetic adjustments to StateSpec.

  • 📍 Write a generic property for observing all possible transitions.
    Instead of writing the same 'is observed' property for each individual transitions.

  • 📍 Provide Eq / Show instances for Transition to enable generic coverage via QuickCheck.
    This is slightly involved but we get automatic coverage generation for free, telling us what transitions aren't covered by tests.

  • 📍 Move 'forAll2' to the test prelude.

  • 📍 Add chain state tests for remaining transitions
    Enforced by code coverage!

    observeTx
      All valid transitions for all possible states can be observed.
        +++ OK, passed 400 tests.
    
        Transition (400 in total):
        19.0% StOpen -> StClosed
        18.2% StClosed -> StIdle
        17.0% StIdle -> StInitialized
        16.0% StInitialized -> StIdle
        15.0% StInitialized -> StInitialized
        14.8% StInitialized -> StOpen
    
  • 📍 Add classification for interesting scenarios to the generic state observation tests.

  • 📍 Remove now redundant/obsolete tests from TxSpec.

  • 📍 Also move the size specs to the chain state spec module.


Hydra.Chain.Direct.State
  observeTx
    All valid transitions for all possible states can be observed.
      +++ OK, passed 400 tests:
      17.0% Non-empty commit
      14.2% 2+ parties
      13.2% Abort after some (but not all) commits
       9.0% Close with initial snapshot
       8.5% Close with multi-signed snapshot
       1.8% 1 party
       1.0% Empty commit
       0.8% Abort immediately, after 0 commits
       0.5% Abort after all commits
      
      13.5% Fanout size: > 100
       4.0% Fanout size: 50-99
       0.8% Fanout size: 10-49
      
      Transition (400 in total):
      18.2% StClosed -> StIdle
      18.0% StInitialized -> StInitialized
      17.5% StOpen -> StClosed
      16.0% StIdle -> StInitialized
      15.8% StInitialized -> StOpen
      14.5% StInitialized -> StIdle
  init
    is not observed if not invited
      +++ OK, passed 100 tests; 86 discarded.
  commit
    is below the network size limit
      +++ OK, passed 100 tests:
      92% Non-empty commit
       8% Empty commit
      
      93% 6kB
       7% 7kB
    consumes all inputs that are committed
      +++ OK, passed 100 tests:
      92% Non-empty commit
       8% Empty commit
    can only be applied / observed once
      +++ OK, passed 100 tests:
      92% Non-empty commit
       8% Empty commit
  abort
    is below the network size limit
      +++ OK, passed 100 tests:
      76% Abort after some (but not all) commits
      13% Abort after all commits
      11% Abort immediately, after 0 commits
      
      41% 20kB
      24% 19kB
      12% 13kB
      12% 14kB
       7% 21kB
       4% 22kB
  collectCom
    is below the network size limit
      +++ OK, passed 100 tests:
      35% 13kB
      31% 15kB
      28% 14kB
       5% 16kB
       1% 12kB
  close
    is below the network size limit
      +++ OK, passed 100 tests:
      52% Close with multi-signed snapshot
      48% Close with initial snapshot
      
      78% 8kB
      19% 9kB
       2% 7kB
       1% 10kB
  fanout
    is below the network size limit
      +++ OK, passed 100 tests:
      61% Fanout size: > 100
      29% Fanout size: 50-99
      10% Fanout size: 10-49
      
      18% 16kB
      17% 17kB
      16% 18kB
      12% 13kB
       9% 14kB
       6% 19kB
       5% 12kB
       5% 15kB
       5% 21kB
       4% 20kB
       3% 11kB

@KtorZ KtorZ requested review from ch1bo and a user February 22, 2022 16:52
@KtorZ KtorZ self-assigned this Feb 22, 2022
@KtorZ KtorZ force-pushed the KtorZ/spike-on-chain-head-state branch from 60fe275 to be0a0e8 Compare February 23, 2022 15:56
@github-actions
Copy link

github-actions bot commented Feb 23, 2022

Unit Test Results

    6 files  ±0    76 suites  +3   6m 35s ⏱️ +52s
200 tests  - 5  198 ✔️  - 5  2 💤 ±0  0 ±0 

Results for commit ed7090d. ± Comparison against base commit ffd62cb.

This pull request removes 14 and adds 9 tests. Note that renamed tests count towards both.
Hydra.Chain.Direct.State/commit ‑ consumes all inputs that are committed.
Hydra.Chain.Direct.Tx/abortTx ‑ is observed
Hydra.Chain.Direct.Tx/abortTx ‑ transaction size below limit
Hydra.Chain.Direct.Tx/closeTx ‑ is observed
Hydra.Chain.Direct.Tx/closeTx ‑ transaction size below limit
Hydra.Chain.Direct.Tx/collectComTx ‑ is observed
Hydra.Chain.Direct.Tx/collectComTx ‑ transaction size below limit
Hydra.Chain.Direct.Tx/commitTx ‑ is observed
Hydra.Chain.Direct.Tx/commitTx ‑ transaction size for single commit utxo below limit
Hydra.Chain.Direct.Tx/fanoutTx ‑ is observed
…
Hydra.Chain.Direct.State/abort ‑ is below the network size limit
Hydra.Chain.Direct.State/close ‑ is below the network size limit
Hydra.Chain.Direct.State/collectCom ‑ is below the network size limit
Hydra.Chain.Direct.State/commit ‑ can only be applied / observed once
Hydra.Chain.Direct.State/commit ‑ consumes all inputs that are committed
Hydra.Chain.Direct.State/commit ‑ is below the network size limit
Hydra.Chain.Direct.State/fanout ‑ is below the network size limit
Hydra.Chain.Direct.State/init ‑ is not observed if not invited
Hydra.Chain.Direct.State/observeTx ‑ All valid transitions for all possible states can be observed.

♻️ This comment has been updated with latest results.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really "boring Haskell" anymore but I like how this could make it easier to define generators for sequence of transitions and how it makes the State machine explicit and encoded in types. As long as we don't overdo it and keep it in this module and for this use case, I think it's an improvement.

@KtorZ
Copy link
Collaborator Author

KtorZ commented Feb 23, 2022

I have to say, I exalt where this is taking the test code! I went through re-expressing the same properties as the ones we have in the Direct.TxSpec module (except the '< max tx size' ones) but using the higher-level state API instead and... I like it. I think the properties gives even more coverage actually since I am able to combine generators in quite arbitrary ways AND, more importantly, they don't feel at all like we are re-stating the implementation in a slightly different and applied way.

I'd make a case for actually deprecating (a.k.a removing) the tests in TxSpec in favor of this new form, which gives us the same (if not more?) coverage.

Tx ->
OnChainHeadState st ->
Maybe (OnChainTx Tx, SomeOnChainHeadState)
Maybe (OnChainTx Tx, OnChainHeadState st')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to have this named observeTransition

KtorZ added 14 commits February 24, 2022 15:14
  Not sure I want to commit that as this is venturing more and more in
  the lands of dependent-types... therefore adding complexity to the
  code for actually here little gain apart from a more descriptive
  module API.

  What motivated this change initially was an attempt at simplifying the
  underlying test-code where we do know exactly what transition we want
  to do. Thus, getting back an opaque 'SomeOnChainHeadState' forces some
  needless unwrapping via reify state. It ain't much, as we are really
  just talking about one case/pattern-match but still... that was the
  initial motivation. With this new approach, we can remove that extra
  pattern match on call-sites by using `transition` directly, with some
  type annotation as for the transition we expect and tada! Yet.. the
  definitions are a bit more complex now as I added a new type-class and
  some glue to make things work :/
  can only apply/observe the same commit once.
  Instead of writing the same 'is observed' property for each individual transitions.
… via QuickCheck.

  This is slightly involved but we get automatic coverage generation for free, telling us what transitions aren't covered by tests.
  Enforced by code coverage!

  ```
  observeTx
    All valid transitions for all possible states can be observed.
      +++ OK, passed 400 tests.

      Transition (400 in total):
      19.0% StOpen -> StClosed
      18.2% StClosed -> StIdle
      17.0% StIdle -> StInitialized
      16.0% StInitialized -> StIdle
      15.0% StInitialized -> StInitialized
      14.8% StInitialized -> StOpen
  ```
@KtorZ KtorZ force-pushed the KtorZ/spike-on-chain-head-state branch from 5ad0ed5 to ed7090d Compare February 24, 2022 18:51
@KtorZ KtorZ merged commit ac72d7b into master Feb 24, 2022
@KtorZ KtorZ deleted the KtorZ/spike-on-chain-head-state branch February 24, 2022 20:10
@KtorZ KtorZ mentioned this pull request Feb 25, 2022
6 tasks
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.

2 participants