fix(sync): enforce ForkLengthThreshold for synced chain (#5182)

This commit is contained in:
Lucas Molas 2020-12-22 12:29:36 -03:00 committed by GitHub
parent e9989d0e46
commit 461a3cdebc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1449,7 +1449,7 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know
return nil, ErrForkCheckpoint return nil, ErrForkCheckpoint
} }
// TODO: Does this mean we always ask for ForkLengthThreshold blocks from the network, even if we just need, like, 2? // TODO: Does this mean we always ask for ForkLengthThreshold blocks from the network, even if we just need, like, 2? Yes.
// Would it not be better to ask in smaller chunks, given that an ~ForkLengthThreshold is very rare? // Would it not be better to ask in smaller chunks, given that an ~ForkLengthThreshold is very rare?
tips, err := syncer.Exchange.GetBlocks(ctx, incoming.Parents(), int(build.ForkLengthThreshold)) tips, err := syncer.Exchange.GetBlocks(ctx, incoming.Parents(), int(build.ForkLengthThreshold))
if err != nil { if err != nil {
@ -1460,6 +1460,10 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to load next local tipset: %w", err) return nil, xerrors.Errorf("failed to load next local tipset: %w", err)
} }
// Track the fork length on our side of the synced chain to enforce
// `ForkLengthThreshold`. Initialized to 1 because we already walked back
// one tipset from `known` (our synced head).
forkLengthInHead := 1
for cur := 0; cur < len(tips); { for cur := 0; cur < len(tips); {
if nts.Height() == 0 { if nts.Height() == 0 {
@ -1476,6 +1480,13 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know
if nts.Height() < tips[cur].Height() { if nts.Height() < tips[cur].Height() {
cur++ cur++
} else { } else {
// Walk back one block in our synced chain to try to meet the fork's
// height.
forkLengthInHead++
if forkLengthInHead > int(build.ForkLengthThreshold) {
return nil, ErrForkTooLong
}
// We will be forking away from nts, check that it isn't checkpointed // We will be forking away from nts, check that it isn't checkpointed
if nts.Key() == chkpt { if nts.Key() == chkpt {
return nil, ErrForkCheckpoint return nil, ErrForkCheckpoint