-
Notifications
You must be signed in to change notification settings - Fork 217
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
Light NetworkLayer: lightSync #3175
Conversation
49aedec
to
2a2030b
Compare
bors try |
tryBuild failed: |
-- or whether the chain has rolled back already. | ||
, getBlockHeaderAtHeight :: BlockHeight -> m (Maybe BlockHeader) | ||
-- ^ Get the 'BlockHeader' at a given block height. | ||
-- Returns 'Nothing' if there is no block at this height (anymore). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not better to return whatever is present up to block height?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also thinking about source abstraction. Maybe it would be worth to sketch the abtraction that would handle this light wallet source and node source? I think we can do it later, now we can demonstrate it just works. But maybe we can do something now. What do you think? Too soon? Or you see already silluette of this abstraction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also thinking about source abstraction.
I've had some discussion with Yura about this, and the conclusion was "too soon". I was thinking of some sort of general LightLayer
abstraction indeed, but the details seemed unclear. We decided to postpone a decision there, and I chose to introduce the smallest type that can be used to implement lightSync
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not better to return whatever is present up to block height?
In the lightSync procedure, getBlockHeaderAtHeight
is only used to move a pointer around, here to a block slightly older than the tip of the chain (by subtracting stabilityWindow
from the height).
The actual data for blocks is returned by getNextBlocks
and getAddressTxs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic of light syncing looks reasonable. Nice mocking tests (eval fullFollower === eval lightSyncFollower) . I think it begs to use state machine testing as we have well defined states and known transitions - could be done in next PRs if you finally are persuaded (I read your comment why you resign from using this approach). Maybe we could catch something. It would be good to introduce rollbacks distributions (probably scaled Poisson with lambda=1 with cutoff) to mimic what we have, so many 2-3 depth rollbacks, rare higher depth rollbacks, cut with security parameter. So we could defined chain evolution with this rollback influencer, apply very realistic blocks...and verify consensus. just food for thought
data Free f a | ||
= Free (f (Free f a)) | ||
| Pure a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why invent free monad?
https://hackage.haskell.org/package/free-5.1.7/docs/Control-Monad-Free.html#t:Free
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many reasons, actually. 😅
- Main reason: The wallet does not yet import use a
free
package or one of its many variants. I didn't want to introduce a package-level idiom without team discussion, but I felt comfortable introduce a local idiom. (My preference there would actually be my ownoperational
. 😅 ) - We already have another hand-baked monad, the
LSQ
monad. - The definition of
Free
is ~20, fairly simple lines. This is hard to beat.
Thanks for taking a look, Pawel, Yura. 😊
Using a Poission distribution to mimic the real chain is an interesting idea. 🤔 However, I figured that for the purpose of stress-testing the code, using a simple uniform distribution ( backward = do
m <- choose (0, min (NE.length chain1 - 1) mockStabilityWindow)
let chain2 = NE.fromList (NE.drop m chain1) For testing, we actually want the rollbacks to be worse than in the real world chain. 😂 |
Includes testing on a randomly evolving `MockChain` history with rollbacks.
Co-authored-by: paweljakubas <[email protected]> Co-authored-by: Yura Lazarev <[email protected]>
3ad6102
to
c95f444
Compare
bors merge |
3175: Light NetworkLayer: lightSync r=HeinrichApfelmus a=HeinrichApfelmus ### Issue number ADP-1422, ADP-1427 ### Overview [Light-mode][] (Epic ADP-1422) aims to make synchronisation to the blockchain faster by trusting an off-chain source of aggregated blockchain data. [light-mode]: https://input-output-hk.github.io/cardano-wallet/design/specs/light-mode In this pull request, we implement `lightSync`, the "crown jewel" 👑 of light-mode: * `lightSync` drives a `ChainFollower` with `LightBlocks` by polling an external blockchain data source (represented by `LightSyncSource`) as opposed to being pushed by a cardano-node. * `prop_followLightSync` tests this rigorously by simulating a randomly evolving blockchain with rollbacks. ### Details * `lightSync` is implemented and tested, but propagating it to `NetworkLayer` is left for a future pull request. * `secondsPerSlot` is currently hard-coded to 2 seconds; also left for the future when the shape of `LightLayer` becomes more clear. ### Comments * I have opted to *not* use [quickcheck-state-machine][qsm], as I felt that the trouble of setting up the `Reference` type machinery did not seem worth the benefit. * However, I have kept the principle of first generating a history (`genChainHistory`) and then driving a (monadic) state machine with it (`evalMockMonad`) — it was just easier to do it "by hand". * That said, *labelling* histories to check that interesting histories have been generated would be a good idea — but I'm sufficiently confident in the present implementation that I would like to postpone this for a future time, also because I envision some synergy between randomized history generation and `Delta` encodings. * By the same token, I have forgone shrinking — as long as they are no bugs, we don't need to shrink any. :) * `genChainHistory` generates random histories of `BlockHeader` with correct `parentHeaderHash`. Extending this to valid histories of `Block` in the future would allows us to test `UTxO` and address discovery state as well. [qsm]: https://well-typed.com/blog/2019/01/qsm-in-depth/ Co-authored-by: Heinrich Apfelmus <[email protected]>
Canceled. |
bors merge |
Build succeeded: |
Issue number
ADP-1422, ADP-1427
Overview
Light-mode (Epic ADP-1422) aims to make synchronisation to the blockchain faster by trusting an off-chain source of aggregated blockchain data.
In this pull request, we implement
lightSync
, the "crown jewel" 👑 of light-mode:lightSync
drives aChainFollower
withLightBlocks
by polling an external blockchain data source (represented byLightSyncSource
) as opposed to being pushed by a cardano-node.prop_followLightSync
tests this rigorously by simulating a randomly evolving blockchain with rollbacks.Details
lightSync
is implemented and tested, but propagating it toNetworkLayer
is left for a future pull request.secondsPerSlot
is currently hard-coded to 2 seconds; also left for the future when the shape ofLightLayer
becomes more clear.Comments
I have opted to not use quickcheck-state-machine, as I felt that the trouble of setting up the
Reference
type machinery did not seem worth the benefit.genChainHistory
) and then driving a (monadic) state machine with it (evalMockMonad
) — it was just easier to do it "by hand".Delta
encodings.genChainHistory
generates random histories ofBlockHeader
with correctparentHeaderHash
. Extending this to valid histories ofBlock
in the future would allows us to testUTxO
and address discovery state as well.