Skip to content

Commit 599b852

Browse files
committed
chore: add docstrings to chainsegment
1 parent 21315f5 commit 599b852

File tree

1 file changed

+49
-5
lines changed
  • rolling-shutter/medley/chainsync/chainsegment

1 file changed

+49
-5
lines changed

rolling-shutter/medley/chainsync/chainsegment/chain.go

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ type UpdateLatestResult struct {
3232
UpdatedSegment *ChainSegment
3333
}
3434

35+
// capNumPollBlocks is a pipeline function
36+
// that restricts the number of blocks to be
37+
// polled, e.g. during filling gaps between
38+
// two chain-segments.
3539
func capNumPollBlocks(num int) int {
3640
if num > MaxNumPollBlocks {
3741
return MaxNumPollBlocks
@@ -45,8 +49,6 @@ type ChainSegment struct {
4549
chain []*types.Header
4650
}
4751

48-
// assumes reverse order, and that it is
49-
// a connected chain-segment.
5052
func NewChainSegment(chain ...*types.Header) *ChainSegment {
5153
bc := &ChainSegment{
5254
chain: chain,
@@ -91,16 +93,31 @@ func (bc *ChainSegment) Copy() *ChainSegment {
9193
return NewChainSegment(bc.chain...)
9294
}
9395

96+
// UpdateLatest incorporates a new chainsegment `update` into it's existing
97+
// chain-segment.
98+
// For this it backtracks the new chain-segment until it finds the common ancestor
99+
// with it's current chain-segment. If there is no ancestor because of a block-number
100+
// gap between the old segments "latest" block and the new segments "earliest" block,
101+
// it will incrementally batch-augment the 'update' chain-segment with blocks older than
102+
// it's "earliest" block, and call the UpdateLatest latest method recursively
103+
// until the algorithm finds a common ancestor.
104+
// The outcome of this process is an `UpdateLatestResult`, which
105+
// communicates to the caller what part of the previous chain-segment had to be removed,
106+
// and what part of the `update` chain-segment was appended to the previous chain-segment
107+
// after removal of out-of-date blocks, in addition to the full newly updated chain-segment.
108+
// This is a pointer method that updates the internal state of it's chain-segment!
94109
func (bc *ChainSegment) UpdateLatest(ctx context.Context, c client.Sync, update *ChainSegment) (UpdateLatestResult, error) {
95110
update = update.Copy()
96111
if bc.Len() == 0 {
112+
// We can't compare anything - instead of silently absorbing the
113+
// whole new segment, communicate this to the caller with a specific error.
97114
return UpdateLatestResult{}, ErrEmpty
98115
}
99116

100117
if bc.Earliest().Number.Cmp(update.Earliest().Number) == 1 {
101-
// We don't reach so far in the past.
102-
// This only happens when the cache of used blocks in
103-
// doesn't reach so far.
118+
// We don't reach so far in the past for the old chain-segment.
119+
// This happens when there is a large reorg, while the chain-segment
120+
// of the cache is still small.
104121
return UpdateLatestResult{}, fmt.Errorf(
105122
"segment earliest=%d, update earliest=%d: %w",
106123
bc.Earliest().Number.Int64(), update.Earliest().Number.Int64(),
@@ -143,12 +160,22 @@ func (bc *ChainSegment) UpdateLatest(ctx context.Context, c client.Sync, update
143160
return bc.UpdateLatest(ctx, c, update)
144161
}
145162
// implicit case - overlap > 0:
163+
// now we can compare the segments and find the common ancestor
164+
// Return the segment of the overlap from the current segment
165+
// and compute the diff of the whole new update segment.
146166
removed, updated := bc.GetLatest(overlap).DiffLeftAligned(update)
167+
// don't copy, but use the method's struct,
168+
// that way we modify in-place
147169
full := bc
148170
if removed != nil {
171+
// cut the reorged section that has to be removed
172+
// so that we only have the "left" section up until the
173+
// common ancestor
149174
full = full.GetEarliest(full.Len() - removed.Len())
150175
}
151176
if updated != nil {
177+
// and now append the update section
178+
// to the right, effectively removing the reorged section
152179
full.AddRight(updated)
153180
}
154181
return UpdateLatestResult{
@@ -158,11 +185,28 @@ func (bc *ChainSegment) UpdateLatest(ctx context.Context, c client.Sync, update
158185
}, nil
159186
}
160187

188+
// AddRight adds the `add` chain-segment to the "right" of the
189+
// original chain-segment, and thus assumes that the `add` segments
190+
// Earliest() block is the child-block of the original segments
191+
// Latest() block. This condition is *not* checked,
192+
// so callers have to guarantee for it.
161193
func (bc *ChainSegment) AddRight(add *ChainSegment) *ChainSegment {
162194
bc.chain = append(bc.chain, add.chain...)
163195
return bc
164196
}
165197

198+
// DiffLeftAligned compares the ChainSegment to another chain-segment that
199+
// starts at the same Earliest() block-number.
200+
// It walks both segments from earliest to latest header simultaneously
201+
// and compares the block-hashes. As soon as there is a mismatch
202+
// in block-hashes, a consecutive difference from that point on is assumed.
203+
// All diff blocks from the `other` chain-segment will be appended to the returned `update`
204+
// chain-segment, and all diff blocks from the original chain-segment
205+
// will be appended to the `remove` chain-segment.
206+
// If there is no overlap in the diff, but the `other` chain-segment is longer than
207+
// the original segment, the `remove` segment will be nil, and the `update` segment
208+
// will consist of the non-overlapping blocks of the `other` segment.
209+
// If both segments are identical, both `update` and `remove` segments will be nil.
166210
func (bc *ChainSegment) DiffLeftAligned(other *ChainSegment) (remove, update *ChainSegment) {
167211
// 1) assumes both segments start at the same block height (earliest block at index 0 with same blocknum)
168212
// 2) assumes the other.Len() >= bc.Len()

0 commit comments

Comments
 (0)