diff --git a/app/protocol/flowcontext/errors.go b/app/protocol/flowcontext/errors.go index 3ce363f26..f73c2d71d 100644 --- a/app/protocol/flowcontext/errors.go +++ b/app/protocol/flowcontext/errors.go @@ -2,6 +2,7 @@ package flowcontext import ( "errors" + "strings" "sync/atomic" "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" @@ -9,6 +10,11 @@ import ( "github.com/kaspanet/kaspad/app/protocol/protocolerrors" ) +var ( + // ErrPingTimeout signifies that a ping operation timed out. + ErrPingTimeout = protocolerrors.New(false, "timeout expired on ping") +) + // HandleError handles an error from a flow, // It sends the error to errChan if isStopping == 0 and increments isStopping // @@ -21,8 +27,15 @@ func (*FlowContext) HandleError(err error, flowName string, isStopping *uint32, if protocolErr := (protocolerrors.ProtocolError{}); !errors.As(err, &protocolErr) { panic(err) } - - log.Errorf("error from %s: %+v", flowName, err) + if errors.Is(err, ErrPingTimeout) { + // Avoid printing the call stack on ping timeouts, since users get panicked and this case is not interesting + log.Errorf("error from %s: %s", flowName, err) + } else { + // Explain to the user that this is not a panic, but only a protocol error with a specific peer + logFrame := strings.Repeat("=", 52) + log.Errorf("Non-critical peer protocol error from %s, printing the full stack for debug purposes: \n%s\n%+v \n%s", + flowName, logFrame, err, logFrame) + } } if atomic.AddUint32(isStopping, 1) == 1 { diff --git a/app/protocol/flows/v4/blockrelay/ibd_with_headers_proof.go b/app/protocol/flows/v4/blockrelay/ibd_with_headers_proof.go index cbb4f41c7..c60900b6b 100644 --- a/app/protocol/flows/v4/blockrelay/ibd_with_headers_proof.go +++ b/app/protocol/flows/v4/blockrelay/ibd_with_headers_proof.go @@ -24,6 +24,7 @@ func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash, return err } + log.Infof("IBD with pruning proof from %s was unsuccessful. Deleting the staging consensus.", flow.peer) deleteStagingConsensusErr := flow.Domain().DeleteStagingConsensus() if deleteStagingConsensusErr != nil { return deleteStagingConsensusErr @@ -32,6 +33,8 @@ func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash, return err } + log.Infof("Header download stage of IBD with pruning proof completed successfully from %s. "+ + "Committing the staging consensus and deleting the previous obsolete one if such exists.", flow.peer) err = flow.Domain().CommitStagingConsensus() if err != nil { return err diff --git a/app/protocol/flows/v4/ping/send.go b/app/protocol/flows/v4/ping/send.go index be476383e..13980ff11 100644 --- a/app/protocol/flows/v4/ping/send.go +++ b/app/protocol/flows/v4/ping/send.go @@ -2,6 +2,8 @@ package ping import ( "github.com/kaspanet/kaspad/app/protocol/common" + "github.com/kaspanet/kaspad/app/protocol/flowcontext" + "github.com/pkg/errors" "time" "github.com/kaspanet/kaspad/app/appmessage" @@ -61,6 +63,9 @@ func (flow *sendPingsFlow) start() error { message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) if err != nil { + if errors.Is(err, router.ErrTimeout) { + return errors.Wrapf(flowcontext.ErrPingTimeout, err.Error()) + } return err } pongMessage := message.(*appmessage.MsgPong) diff --git a/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go b/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go index 2593320b6..885f7f062 100644 --- a/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go +++ b/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go @@ -25,6 +25,7 @@ func (flow *handleIBDFlow) ibdWithHeadersProof( return err } + log.Infof("IBD with pruning proof from %s was unsuccessful. Deleting the staging consensus.", flow.peer) deleteStagingConsensusErr := flow.Domain().DeleteStagingConsensus() if deleteStagingConsensusErr != nil { return deleteStagingConsensusErr @@ -33,6 +34,8 @@ func (flow *handleIBDFlow) ibdWithHeadersProof( return err } + log.Infof("Header download stage of IBD with pruning proof completed successfully from %s. "+ + "Committing the staging consensus and deleting the previous obsolete one if such exists.", flow.peer) err = flow.Domain().CommitStagingConsensus() if err != nil { return err diff --git a/app/protocol/flows/v5/ping/send.go b/app/protocol/flows/v5/ping/send.go index be476383e..13980ff11 100644 --- a/app/protocol/flows/v5/ping/send.go +++ b/app/protocol/flows/v5/ping/send.go @@ -2,6 +2,8 @@ package ping import ( "github.com/kaspanet/kaspad/app/protocol/common" + "github.com/kaspanet/kaspad/app/protocol/flowcontext" + "github.com/pkg/errors" "time" "github.com/kaspanet/kaspad/app/appmessage" @@ -61,6 +63,9 @@ func (flow *sendPingsFlow) start() error { message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) if err != nil { + if errors.Is(err, router.ErrTimeout) { + return errors.Wrapf(flowcontext.ErrPingTimeout, err.Error()) + } return err } pongMessage := message.(*appmessage.MsgPong) diff --git a/domain/consensus/processes/syncmanager/antipast.go b/domain/consensus/processes/syncmanager/antipast.go index 91b02f7ae..f00207f45 100644 --- a/domain/consensus/processes/syncmanager/antipast.go +++ b/domain/consensus/processes/syncmanager/antipast.go @@ -145,7 +145,7 @@ func (sm *syncManager) missingBlockBodyHashes(stagingArea *model.StagingArea, hi lowHash = selectedChild } if !foundHeaderOnlyBlock { - if lowHash == highHash { + if lowHash.Equal(highHash) { // Blocks can be inserted inside the DAG during IBD if those were requested before IBD started. // In rare cases, all the IBD blocks might be already inserted by the time we reach this point. // In these cases - return an empty list of blocks to sync @@ -153,7 +153,7 @@ func (sm *syncManager) missingBlockBodyHashes(stagingArea *model.StagingArea, hi } // TODO: Once block children are fixed (https://github.com/kaspanet/kaspad/issues/1499), // this error should be returned rather the logged - log.Errorf("no header-only blocks between %s and %s", + log.Errorf("No header-only blocks between %s and %s", lowHash, highHash) }