Reject SubmitBlock if the node is in IBD (#1409)

* Reject SubmitBlock if the node is in IBD

* Add comments

* Don't use iota for RejectReason constants, since in .proto those are hard-coded
This commit is contained in:
Svarog 2021-01-13 15:04:55 +02:00 committed by GitHub
parent 68bd8330ac
commit 4988817da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 833 additions and 717 deletions

View File

@ -19,11 +19,33 @@ func NewSubmitBlockRequestMessage(block *MsgBlock) *SubmitBlockRequestMessage {
}
}
// RejectReason describes the reason why a block sent by SubmitBlock was rejected
type RejectReason byte
// RejectReason constants
// Not using iota, since in the .proto file those are hardcoded
const (
RejectReasonNone RejectReason = 0
RejectReasonBlockInvalid RejectReason = 1
RejectReasonIsInIBD RejectReason = 2
)
var rejectReasonToString = map[RejectReason]string{
RejectReasonNone: "None",
RejectReasonBlockInvalid: "Block is invalid",
RejectReasonIsInIBD: "Node is in IBD",
}
func (rr RejectReason) String() string {
return rejectReasonToString[rr]
}
// SubmitBlockResponseMessage is an appmessage corresponding to
// its respective RPC message
type SubmitBlockResponseMessage struct {
baseMessage
Error *RPCError
RejectReason RejectReason
Error *RPCError
}
// Command returns the protocol command string for the message

View File

@ -79,3 +79,8 @@ func (m *Manager) SetOnTransactionAddedToMempoolHandler(onTransactionAddedToMemp
func (m *Manager) ShouldMine() (bool, error) {
return m.context.ShouldMine()
}
// IsIBDRunning returns true if IBD is currently marked as running
func (m *Manager) IsIBDRunning() bool {
return m.context.IsIBDRunning()
}

View File

@ -16,14 +16,22 @@ func HandleSubmitBlock(context *rpccontext.Context, _ *router.Router, request ap
msgBlock := submitBlockRequest.Block
domainBlock := appmessage.MsgBlockToDomainBlock(msgBlock)
if context.ProtocolManager.IsIBDRunning() {
return &appmessage.SubmitBlockResponseMessage{
Error: appmessage.RPCErrorf("Block not submitted - IBD is running"),
RejectReason: appmessage.RejectReasonIsInIBD,
}, nil
}
err := context.ProtocolManager.AddBlock(domainBlock)
if err != nil {
if !errors.As(err, &ruleerrors.RuleError{}) {
return nil, err
}
errorMessage := &appmessage.SubmitBlockResponseMessage{}
errorMessage.Error = appmessage.RPCErrorf("Block rejected. Reason: %s", err)
return errorMessage, nil
return &appmessage.SubmitBlockResponseMessage{
Error: appmessage.RPCErrorf("Block rejected. Reason: %s", err),
RejectReason: appmessage.RejectReasonBlockInvalid,
}, nil
}
log.Infof("Accepted block %s via submitBlock", consensushashing.BlockHash(domainBlock))

View File

@ -115,8 +115,12 @@ func handleFoundBlock(client *minerClient, block *externalapi.DomainBlock) error
blockHash := consensushashing.BlockHash(block)
log.Infof("Found block %s with parents %s. Submitting to %s", blockHash, block.Header.ParentHashes(), client.Address())
err := client.SubmitBlock(block)
rejectReason, err := client.SubmitBlock(block)
if err != nil {
if rejectReason == appmessage.RejectReasonIsInIBD {
log.Warnf("Block %s was rejected because the node is in IBD", blockHash)
return nil
}
return errors.Errorf("Error submitting block %s to %s: %s", blockHash, client.Address(), err)
}
return nil

View File

@ -41,6 +41,12 @@ message SubmitBlockRequestMessage{
}
message SubmitBlockResponseMessage{
enum RejectReason {
NONE = 0;
BLOCK_INVALID = 1;
IS_IN_IBD = 2;
}
RejectReason rejectReason = 1;
RPCError error = 1000;
}

View File

@ -24,7 +24,8 @@ func (x *KaspadMessage_SubmitBlockResponse) toAppMessage() (appmessage.Message,
err = &appmessage.RPCError{Message: x.SubmitBlockResponse.Error.Message}
}
return &appmessage.SubmitBlockResponseMessage{
Error: err,
RejectReason: appmessage.RejectReason(x.SubmitBlockResponse.RejectReason),
Error: err,
}, nil
}
@ -34,7 +35,8 @@ func (x *KaspadMessage_SubmitBlockResponse) fromAppMessage(message *appmessage.S
err = &RPCError{Message: message.Error.Message}
}
x.SubmitBlockResponse = &SubmitBlockResponseMessage{
Error: err,
RejectReason: SubmitBlockResponseMessage_RejectReason(message.RejectReason),
Error: err,
}
return nil
}

View File

@ -6,19 +6,19 @@ import (
)
// SubmitBlock sends an RPC request respective to the function's name and returns the RPC server's response
func (c *RPCClient) SubmitBlock(block *externalapi.DomainBlock) error {
func (c *RPCClient) SubmitBlock(block *externalapi.DomainBlock) (appmessage.RejectReason, error) {
err := c.rpcRouter.outgoingRoute().Enqueue(
appmessage.NewSubmitBlockRequestMessage(appmessage.DomainBlockToMsgBlock(block)))
if err != nil {
return err
return appmessage.RejectReasonNone, err
}
response, err := c.route(appmessage.CmdSubmitBlockResponseMessage).DequeueWithTimeout(c.timeout)
if err != nil {
return err
return appmessage.RejectReasonNone, err
}
submitBlockResponse := response.(*appmessage.SubmitBlockResponseMessage)
if submitBlockResponse.Error != nil {
return c.convertRPCError(submitBlockResponse.Error)
return submitBlockResponse.RejectReason, c.convertRPCError(submitBlockResponse.Error)
}
return nil
return appmessage.RejectReasonNone, nil
}

View File

@ -1,14 +1,13 @@
package integration
import (
"github.com/kaspanet/kaspad/domain/consensus/model/pow"
"github.com/kaspanet/kaspad/util/difficulty"
"math/rand"
"testing"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/pow"
"github.com/kaspanet/kaspad/util/difficulty"
)
func solveBlock(block *externalapi.DomainBlock) *externalapi.DomainBlock {
@ -36,7 +35,7 @@ func mineNextBlock(t *testing.T, harness *appHarness) *externalapi.DomainBlock {
solveBlock(block)
err = harness.rpcClient.SubmitBlock(block)
_, err = harness.rpcClient.SubmitBlock(block)
if err != nil {
t.Fatalf("Error submitting block: %s", err)
}