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

Keep ServerOutput type at the api boundary #1849

Closed
wants to merge 9 commits into from

Conversation

v0d1ch
Copy link
Contributor

@v0d1ch v0d1ch commented Feb 11, 2025

  • Rip the ServerOutput type out of HeadLogic that now deals only with StateChanged type. There is a mapping from StateChanged -> ServerOutput now so that we can output state events from Head logic but deal only with ServerOutput on the api boundary.

  • CHANGELOG updated or not needed
  • Documentation updated or not needed
  • Haddocks updated or not needed
  • No new TODOs introduced or explained herafter

@v0d1ch v0d1ch self-assigned this Feb 11, 2025
@v0d1ch v0d1ch linked an issue Feb 11, 2025 that may be closed by this pull request
@v0d1ch v0d1ch force-pushed the serveroutput-to-statechanged branch 2 times, most recently from df99bee to bc1bea1 Compare February 11, 2025 16:06
Copy link

github-actions bot commented Feb 11, 2025

Transaction cost differences

Script summary

Name Size (Bytes)
νInitial -
νCommit -
νHead -
μHead -
νDeposit -

Init transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
40 - - - -

Commit transaction costs

UTxO Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
54 - - - -

CollectCom transaction costs

Parties UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
1 - - - - -
2 - - - - -
3 - - - - -
4 - - - - -
5 - - - - -
6 - - - - -
7 - - - - -
8 - - - - -

Cost of Increment Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - $${\color{green}-0.39}$$ $${\color{green}-0.09}$$ -
10 - - - -
37 - - - -

Cost of Decrement Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
40 - - - -

Close transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
34 - - - -

Contest transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 - - - -
2 - - - -
3 - - - -
5 - - - -
10 - - - -
27 - - - -

FanOut transaction costs

UTxO, Parties UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
(0, 10) - - - - -
(1, 10) - - - - -
(5, 10) - - - - -
(10, 10) - - - - -
(20, 10) - - - - -
(37, 10) - - - - -

@v0d1ch v0d1ch force-pushed the serveroutput-to-statechanged branch 2 times, most recently from 4914fc7 to 47d9cf4 Compare February 12, 2025 15:06
@v0d1ch v0d1ch force-pushed the serveroutput-to-statechanged branch from 47d9cf4 to d8f8b61 Compare February 12, 2025 15:12
Copy link

github-actions bot commented Feb 12, 2025

Transaction costs

Sizes and execution budgets for Hydra protocol transactions. Note that unlisted parameters are currently using arbitrary values and results are not fully deterministic and comparable to previous runs.

Metadata
Generated at 2025-02-13 09:20:11.497602894 UTC
Max. memory units 14000000
Max. CPU units 10000000000
Max. tx size (kB) 16384

Script summary

Name Hash Size (Bytes)
νInitial c8a101a5c8ac4816b0dceb59ce31fc2258e387de828f02961d2f2045 2652
νCommit 61458bc2f297fff3cc5df6ac7ab57cefd87763b0b7bd722146a1035c 685
νHead 0e35115a2c7c13c68ecd8d74e4987c04d4539e337643be20bb3274bd 14756
μHead 57166715eadb8d3135964325c016eea546c21e1c0aae974ca67df9a5* 5541
νDeposit ae01dade3a9c346d5c93ae3ce339412b90a0b8f83f94ec6baa24e30c 1102
  • The minting policy hash is only usable for comparison. As the script is parameterized, the actual script is unique per head.

Init transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 6098 10.98 3.42 0.53
2 6294 13.47 4.19 0.57
3 6495 15.50 4.80 0.60
5 6897 20.25 6.27 0.66
10 7908 31.40 9.68 0.82
40 13935 98.57 30.28 1.78

Commit transaction costs

This uses ada-only outputs for better comparability.

UTxO Tx size % max Mem % max CPU Min fee ₳
1 558 2.44 1.16 0.20
2 740 3.38 1.73 0.22
3 915 4.36 2.33 0.24
5 1283 6.41 3.60 0.28
10 2176 12.13 7.25 0.40
54 10057 98.61 68.52 1.88

CollectCom transaction costs

Parties UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
1 57 525 25.64 7.39 0.43
2 114 636 33.79 9.72 0.52
3 169 747 45.82 12.98 0.65
4 227 858 56.00 15.82 0.75
5 282 974 62.09 17.66 0.82
6 339 1081 71.77 20.48 0.93
7 395 1192 82.26 23.31 1.04
8 450 1303 97.80 27.32 1.19
9 505 1414 93.73 26.96 1.16

Cost of Increment Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 1821 25.03 8.23 0.49
2 1983 27.83 9.81 0.53
3 2017 27.24 10.17 0.53
5 2330 31.61 12.91 0.60
10 3152 43.28 20.03 0.78
38 7425 98.19 56.49 1.68

Cost of Decrement Transaction

Parties Tx size % max Mem % max CPU Min fee ₳
1 636 23.99 7.62 0.43
2 733 24.85 8.49 0.44
3 879 26.90 9.76 0.48
5 1133 30.13 11.98 0.53
10 1981 41.17 18.32 0.70
37 5987 94.78 51.12 1.55

Close transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 681 29.19 9.21 0.48
2 866 31.60 10.72 0.52
3 925 34.74 12.17 0.56
5 1255 37.14 14.40 0.61
10 2135 51.75 22.50 0.82
32 5314 97.46 51.59 1.54

Contest transaction costs

Parties Tx size % max Mem % max CPU Min fee ₳
1 688 35.95 11.01 0.55
2 810 38.15 12.32 0.58
3 942 40.32 13.64 0.62
5 1245 45.25 16.54 0.69
10 2146 58.18 24.14 0.89
27 4628 98.98 48.19 1.50

Abort transaction costs

There is some variation due to the random mixture of initial and already committed outputs.

Parties Tx size % max Mem % max CPU Min fee ₳
1 5999 28.20 9.31 0.71
2 6090 37.31 12.30 0.81
3 6246 44.07 14.54 0.89
4 6320 50.05 16.46 0.95
5 6442 65.76 21.63 1.12
6 6700 79.13 26.20 1.27
7 6783 80.85 26.67 1.29
8 6962 93.38 30.77 1.43
9 6942 95.88 31.57 1.46

FanOut transaction costs

Involves spending head output and burning head tokens. Uses ada-only UTXO for better comparability.

Parties UTxO UTxO (bytes) Tx size % max Mem % max CPU Min fee ₳
10 0 0 6092 20.12 6.62 0.63
10 1 57 6126 20.87 6.98 0.64
10 20 1136 6767 62.26 22.99 1.12
10 30 1705 7109 83.76 31.32 1.37
10 38 2164 7384 99.70 37.55 1.55

End-to-end benchmark results

This page is intended to collect the latest end-to-end benchmark results produced by Hydra's continuous integration (CI) system from the latest master code.

Please note that these results are approximate as they are currently produced from limited cloud VMs and not controlled hardware. Rather than focusing on the absolute results, the emphasis should be on relative results, such as how the timings for a scenario evolve as the code changes.

Generated at 2025-02-13 09:23:14.653382791 UTC

Baseline Scenario

Number of nodes 1
Number of txs 300
Avg. Confirmation Time (ms) 4.681026186
P99 10.323488329999988ms
P95 5.8677638000000005ms
P50 4.4834115ms
Number of Invalid txs 0

Memory data

Time Used Free
2025-02-13 09:21:50.410163168 UTC 938M 5894M
2025-02-13 09:21:55.40995516 UTC 1049M 5688M
2025-02-13 09:22:00.409972504 UTC 1050M 5686M
2025-02-13 09:22:05.409970415 UTC 1062M 5674M
2025-02-13 09:22:10.409954265 UTC 1064M 5672M
2025-02-13 09:22:15.409909617 UTC 1062M 5673M

Three local nodes

Number of nodes 3
Number of txs 900
Avg. Confirmation Time (ms) 25.465739552
P99 120.88882986ms
P95 32.1110264ms
P50 22.492632999999998ms
Number of Invalid txs 0

Memory data

Time Used Free
2025-02-13 09:22:27.788427608 UTC 985M 5762M
2025-02-13 09:22:32.788570613 UTC 1159M 5588M
2025-02-13 09:22:37.788516687 UTC 1160M 5586M
2025-02-13 09:22:42.788473495 UTC 1165M 5580M
2025-02-13 09:22:47.789641814 UTC 1220M 5457M
2025-02-13 09:22:52.788583275 UTC 1248M 5347M
2025-02-13 09:22:57.788572923 UTC 1250M 5343M
2025-02-13 09:23:02.788577674 UTC 1258M 5336M
2025-02-13 09:23:07.788476273 UTC 1257M 5336M
2025-02-13 09:23:12.788455631 UTC 1266M 5327M

@v0d1ch v0d1ch force-pushed the serveroutput-to-statechanged branch 4 times, most recently from 4a3eac5 to 9a6f54a Compare February 12, 2025 17:10
@v0d1ch v0d1ch changed the title Remove ServerOutput type and instead use StateChanged type Keep ServerOutput type at the api boundary Feb 12, 2025
@v0d1ch v0d1ch requested a review from a team February 12, 2025 17:11
@v0d1ch v0d1ch marked this pull request as ready for review February 12, 2025 17:11
import Test.QuickCheck (oneof)
import Test.QuickCheck.Arbitrary.ADT (ToADTArbitrary)

-- | Analogous to inputs, the pure head logic "core" can have effects emited to
-- the "shell" layers and we distinguish the same: effects onto the client, the
-- network and the chain.
data Effect tx
= -- | Effect to be handled by the "Hydra.API", results in sending this 'ServerOutput'.
ClientEffect {serverOutput :: ServerOutput tx}
= -- | Effect to be handled by the "Hydra.API", results in sending this 'StateChanged'.
Copy link
Contributor

Choose a reason for hiding this comment

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

i think this comment is outdated.

= -- | Effect to be handled by the "Hydra.API", results in sending this 'ServerOutput'.
ClientEffect {serverOutput :: ServerOutput tx}
= -- | Effect to be handled by the "Hydra.API", results in sending this 'StateChanged'.
ClientEffect {serverOutput :: StateChanged tx}
Copy link
Contributor

Choose a reason for hiding this comment

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

The type and attribute names feel misleading to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would you call the field stateChanged ?

Copy link
Member

Choose a reason for hiding this comment

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

@ffakenz is right. It's not only misleading, but IMO we should not even have this ClientEffect anymore.

Copy link
Contributor

Choose a reason for hiding this comment

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

or eventToPersist

| CommandFailed {clientInput :: ClientInput tx, state :: HeadState tx}
| GetUTxOResponse {headId :: HeadId, utxo :: UTxOType tx}
| InvalidInput {reason :: String, input :: Text}
| Greetings
Copy link
Contributor

Choose a reason for hiding this comment

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

It feels misleading for these types to be considered StateChanged, as it seems to contradict this ADR.

IMO, a 1:1 mapping here isn’t feasible nor desirable, since ServerOutputs also represent responses from the node, not just state changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree the situation is not ideal. What do you propose? I see this pr just as a small step forward separating ServerOutput from the HeadLogic code. Next steps should improve situation and if you have a specific plan in mind please share it so that we end up with much nicer code/types to deal with.

Copy link
Contributor

Choose a reason for hiding this comment

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

to me there should be server outputs that are not part of state changes, even if that maintains some coupling.

in a next step i would think about how to deal with those (like CommandFailed/InvalidInput) but outputs like Greetings should definetly not be a StateChanged imo.

@@ -164,6 +234,9 @@ wait reason = Wait reason []
newState :: StateChanged tx -> Outcome tx
newState change = Continue [change] []

newStateWithEffect :: StateChanged tx -> Outcome tx
newStateWithEffect change = Continue [change] [ClientEffect change]
Copy link
Contributor

Choose a reason for hiding this comment

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

If ServerOutputs are being decoupled from HeadLogic, perhaps we could introduce an EventSink that generates API outputs on demand.

Not sure if this is within the scope of this PR, but we might consider running a separate thread to handle projecting server outputs instead of embedding this loop in the node logic.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

API should become just an EventSink for these effects, look at this one #1853
I think playing with threads is out of scope of this PR since it was supposed to be a simple thing that leads to changes we want here #1618

StateChanged.PeerHandshakeFailure{remoteHost, ourVersion, theirVersions} ->
Just $
PeerHandshakeFailure{remoteHost, ourVersion, theirVersions}
StateChanged.HeadInitialized{headId, parties} -> Just $ HeadIsInitializing{headId, parties}
Copy link
Contributor

@noonio noonio Feb 12, 2025

Choose a reason for hiding this comment

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

How do we feel abort RecordWildCards ?

At the minor cost of:

{-# LANGUAGE RecordWildCards #-}

this (and almost all the others) become:

  StateChanged.HeadInitialized{..} -> Just $ HeadIsInitializing{..}

I kind of prefer it here, because all this destructuring is just noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Our coding standards don't mention this extension and I am kinda loving/hating it since it sweeps some stuff under the carpet but is also handy. Here is how the diff looks, I could also change some field names to reduce the noise further 715f689

Copy link
Contributor

Choose a reason for hiding this comment

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

I vote we use it here; I think it's not good to turn on globally, but I think this is one of those places where we just get a strict improvement.

And indeed, as you point out, it hints to inconsistencies that can be resolved as we see fit.

@v0d1ch v0d1ch force-pushed the serveroutput-to-statechanged branch from 9a6f54a to 0735022 Compare February 13, 2025 08:55
Copy link
Member

@ch1bo ch1bo left a comment

Choose a reason for hiding this comment

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

Let's not do this right now, and instead focus on #1618 changes themselves. We might realize that most of these changes are not needed.

= -- | Effect to be handled by the "Hydra.API", results in sending this 'ServerOutput'.
ClientEffect {serverOutput :: ServerOutput tx}
= -- | Effect to be handled by the "Hydra.API", results in sending this 'StateChanged'.
ClientEffect {serverOutput :: StateChanged tx}
Copy link
Member

Choose a reason for hiding this comment

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

@ffakenz is right. It's not only misleading, but IMO we should not even have this ClientEffect anymore.

deriving anyclass (ToJSON, FromJSON)

instance Arbitrary HeadStatus where
arbitrary = genericArbitrary
Copy link
Member

Choose a reason for hiding this comment

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

This should not need to be here. It's an API specific type and not relevant for the HeadLogic at all.

{ time
, seq
, output = greetings
}
Copy link
Member

Choose a reason for hiding this comment

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

Why is this not just producing the Greetings message as before?

Consequently, there should not be a Greetings :: StateChanged

@noonio noonio closed this Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done ✔
Development

Successfully merging this pull request may close these issues.

Remove ServerOutput type and instead use StateChanged type
4 participants