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

Implement pruning point proof #1832

Merged
merged 41 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
21827c4
Calculate GHOSTDAG, reachability etc for each level
someone235 Sep 13, 2021
204f790
Don't preallocate cache for dag stores except level 0 and reduce the …
someone235 Sep 14, 2021
70ba9c8
Reduce the number of connections in the integration test to 16
someone235 Sep 14, 2021
0d8980b
Increase page file
someone235 Sep 14, 2021
a183a94
BuildPruningPointProof
someone235 Sep 15, 2021
6f4a9c5
BuildPruningPointProof
someone235 Sep 22, 2021
a0c6cf0
Add PruningProofManager
someone235 Sep 23, 2021
367dcbb
Implement ApplyPruningPointProof
someone235 Sep 23, 2021
d78e2d7
Add prefix and fix blockAtDepth and fill headersByLevel
someone235 Sep 25, 2021
ba12089
Some bug fixes
someone235 Sep 25, 2021
fc706b4
Include all relevant blocks for each level in the proof
someone235 Sep 27, 2021
ec499fb
Fix syncAndValidatePruningPointProof to return the right block hash
someone235 Sep 27, 2021
9028c01
Fix block window
someone235 Sep 27, 2021
0fa5635
Fix isAncestorOfPruningPoint
someone235 Sep 27, 2021
9c624cb
Ban for rule errors on pruning proof
someone235 Sep 29, 2021
1f639a9
Find common ancestor for blockAtDepthMAtNextLevel
someone235 Sep 30, 2021
59382c4
Use pruning proof in TestValidateAndInsertImportedPruningPoint
someone235 Oct 4, 2021
1c5e120
stage status and finality point for proof blocks
someone235 Oct 10, 2021
18a4c52
Uncomment golint
someone235 Oct 10, 2021
0017617
Change test timeouts
someone235 Oct 10, 2021
8ac5a48
Calculate merge set for ApplyPruningPointProof
someone235 Oct 13, 2021
911484d
Increase test timeout
someone235 Oct 13, 2021
8bf65b2
Add better caching for daa window store
someone235 Oct 13, 2021
8ae689d
Return to default timeout
someone235 Oct 13, 2021
7b08552
Add ErrPruningProofMissesBlocksBelowPruningPoint
someone235 Oct 13, 2021
da19b88
Add errDAAWindowBlockNotFound
someone235 Oct 13, 2021
e2a7c73
Force connection loop next iteration on connection manager stop
someone235 Oct 14, 2021
5edc4e2
Revert to Test64IncomingConnections
someone235 Oct 14, 2021
951792a
Remove BlockAtDepth from DAGTraversalManager
someone235 Oct 14, 2021
ccf60ae
numBullies->16
someone235 Oct 14, 2021
1b1fb05
Set page file size to 8gb
someone235 Oct 14, 2021
c3da6a3
Increase p2p max message size
someone235 Oct 18, 2021
4a3b72f
Test64IncomingConnections->Test16IncomingConnections
someone235 Oct 25, 2021
c5f5f9d
Add comment for PruningProofM
someone235 Oct 25, 2021
c72f563
Add comment in `func (c *ConnectionManager) Stop()`
someone235 Oct 25, 2021
8256318
Rename isAncestorOfPruningPoint->isAncestorOfSelectedTip
someone235 Oct 25, 2021
c9f7c93
Revert page file to 16gb
someone235 Oct 25, 2021
bca1080
Improve ExpectedHeaderPruningPoint perf
someone235 Oct 25, 2021
2a761e1
Fix comment
someone235 Oct 26, 2021
885ca57
Revert "Improve ExpectedHeaderPruningPoint perf"
someone235 Oct 26, 2021
9ba63c2
Don't test windows
someone235 Oct 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/SetPageFileSize.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#>

param(
[System.UInt64] $MinimumSize = 16gb ,
[System.UInt64] $MaximumSize = 16gb ,
[System.UInt64] $MinimumSize = 8gb ,
[System.UInt64] $MaximumSize = 8gb ,
[System.String] $DiskRoot = "D:"
)

Expand Down
4 changes: 2 additions & 2 deletions app/protocol/flows/blockrelay/ibd.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ func (flow *handleRelayInvsFlow) syncPruningPointFutureHeaders(consensus externa
}
return nil
}
for _, block := range ibdBlocksMessage.BlockHeaders {
err = flow.processHeader(consensus, block)
for _, header := range ibdBlocksMessage.BlockHeaders {
err = flow.processHeader(consensus, header)
if err != nil {
return err
}
Expand Down
90 changes: 66 additions & 24 deletions app/protocol/flows/blockrelay/ibd_with_headers_proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -71,51 +72,73 @@ func (flow *handleRelayInvsFlow) checkIfHighHashHasMoreBlueWorkThanSelectedTip(h
return highBlock.Header.BlueWork().Cmp(headersSelectedTipInfo.BlueWork) > 0, nil
}

func (flow *handleRelayInvsFlow) syncAndValidatePruningPointProof() error {
func (flow *handleRelayInvsFlow) syncAndValidatePruningPointProof() (*externalapi.DomainHash, error) {
log.Infof("Downloading the pruning point proof from %s", flow.peer)
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointProof())
if err != nil {
return err
return nil, err
}
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
if err != nil {
return err
return nil, err
}
pruningPointProofMessage, ok := message.(*appmessage.MsgPruningPointProof)
if !ok {
return protocolerrors.Errorf(true, "received unexpected message type. "+
return nil, protocolerrors.Errorf(true, "received unexpected message type. "+
"expected: %s, got: %s", appmessage.CmdPruningPointProof, message.Command())
}
pruningPointProof := appmessage.MsgPruningPointProofToDomainPruningPointProof(pruningPointProofMessage)
return flow.Domain().Consensus().ValidatePruningPointProof(pruningPointProof)
err = flow.Domain().Consensus().ValidatePruningPointProof(pruningPointProof)
if err != nil {
if errors.As(err, &ruleerrors.RuleError{}) {
return nil, protocolerrors.Wrapf(true, err, "pruning point proof validation failed")
}
return nil, err
}

err = flow.Domain().StagingConsensus().ApplyPruningPointProof(pruningPointProof)
if err != nil {
return nil, err
}

return consensushashing.HeaderHash(pruningPointProof.Headers[0][len(pruningPointProof.Headers[0])-1]), nil
}

func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash) error {
err := flow.syncAndValidatePruningPointProof()
proofPruningPoint, err := flow.syncAndValidatePruningPointProof()
if err != nil {
return err
}

pruningPoint, err := flow.syncPruningPointsAndPruningPointAnticone()
err = flow.syncPruningPointsAndPruningPointAnticone(proofPruningPoint)
if err != nil {
return err
}

// TODO: Remove this condition once there's more proper way to check finality violation
// in the headers proof.
if pruningPoint.Equal(flow.Config().NetParams().GenesisHash) {
if proofPruningPoint.Equal(flow.Config().NetParams().GenesisHash) {
return protocolerrors.Errorf(true, "the genesis pruning point violates finality")
}

err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), pruningPoint, highHash)
err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), proofPruningPoint, highHash)
if err != nil {
return err
}

log.Debugf("Headers downloaded from peer %s", flow.peer)

highHashInfo, err := flow.Domain().StagingConsensus().GetBlockInfo(highHash)
if err != nil {
return err
}

log.Debugf("Blocks downloaded from peer %s", flow.peer)
if !highHashInfo.Exists {
return protocolerrors.Errorf(true, "the triggering IBD block was not sent")
}

log.Debugf("Syncing the current pruning point UTXO set")
syncedPruningPointUTXOSetSuccessfully, err := flow.syncPruningPointUTXOSet(flow.Domain().StagingConsensus(), pruningPoint)
syncedPruningPointUTXOSetSuccessfully, err := flow.syncPruningPointUTXOSet(flow.Domain().StagingConsensus(), proofPruningPoint)
if err != nil {
return err
}
Expand All @@ -127,36 +150,40 @@ func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(highHash *exte
return nil
}

func (flow *handleRelayInvsFlow) syncPruningPointsAndPruningPointAnticone() (*externalapi.DomainHash, error) {
func (flow *handleRelayInvsFlow) syncPruningPointsAndPruningPointAnticone(proofPruningPoint *externalapi.DomainHash) error {
log.Infof("Downloading the past pruning points and the pruning point anticone from %s", flow.peer)
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointAndItsAnticone())
if err != nil {
return nil, err
return err
}

err = flow.validateAndInsertPruningPoints()
err = flow.validateAndInsertPruningPoints(proofPruningPoint)
if err != nil {
return nil, err
return err
}

pruningPoint, done, err := flow.receiveBlockWithTrustedData()
pruningPointWithMetaData, done, err := flow.receiveBlockWithTrustedData()
if err != nil {
return nil, err
return err
}

if done {
return nil, protocolerrors.Errorf(true, "got `done` message before receiving the pruning point")
return protocolerrors.Errorf(true, "got `done` message before receiving the pruning point")
}

err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), pruningPoint)
if !pruningPointWithMetaData.Block.Header.BlockHash().Equal(proofPruningPoint) {
return protocolerrors.Errorf(true, "first block with trusted data is not the pruning point")
}

err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), pruningPointWithMetaData)
if err != nil {
return nil, err
return err
}

for {
blockWithTrustedData, done, err := flow.receiveBlockWithTrustedData()
if err != nil {
return nil, err
return err
}

if done {
Expand All @@ -165,12 +192,12 @@ func (flow *handleRelayInvsFlow) syncPruningPointsAndPruningPointAnticone() (*ex

err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), blockWithTrustedData)
if err != nil {
return nil, err
return err
}
}

log.Infof("Finished downloading pruning point and its anticone from %s", flow.peer)
return pruningPoint.Block.Header.BlockHash(), nil
return nil
}

func (flow *handleRelayInvsFlow) processBlockWithTrustedData(
Expand Down Expand Up @@ -217,7 +244,16 @@ func (flow *handleRelayInvsFlow) receivePruningPoints() (*appmessage.MsgPruningP
return msgPruningPoints, nil
}

func (flow *handleRelayInvsFlow) validateAndInsertPruningPoints() error {
func (flow *handleRelayInvsFlow) validateAndInsertPruningPoints(proofPruningPoint *externalapi.DomainHash) error {
currentPruningPoint, err := flow.Domain().Consensus().PruningPoint()
if err != nil {
return err
}

if currentPruningPoint.Equal(proofPruningPoint) {
return protocolerrors.Errorf(true, "the proposed pruning point is the same as the current pruning point")
}

pruningPoints, err := flow.receivePruningPoints()
if err != nil {
return err
Expand All @@ -238,6 +274,12 @@ func (flow *handleRelayInvsFlow) validateAndInsertPruningPoints() error {
return protocolerrors.Errorf(false, "pruning points are violating finality")
}

lastPruningPoint := consensushashing.HeaderHash(headers[len(headers)-1])
if !lastPruningPoint.Equal(proofPruningPoint) {
return protocolerrors.Errorf(true, "the proof pruning point is not equal to the last pruning "+
"point in the list")
}

err = flow.Domain().StagingConsensus().ImportPruningPoints(headers)
if err != nil {
return err
Expand Down
Loading