[NOD-1525] Implement headers first ibd (#1017)

* [NOD-1525] Implement headers first IBD

* [NOD-1525] Fix proto translators

* [NOD-1525] Register missing flows

* [NOD-1525] Rename SyncStateNormal->SyncStateRelay, simplifiy IBD peer selection code and get rid of panic in FinishIBD

* [NOD-1525] Remove redundant methods from interface
This commit is contained in:
Ori Newman 2020-11-10 06:14:51 -08:00 committed by GitHub
parent 31c5264430
commit 23c1ea6c31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 2822 additions and 1802 deletions

View File

@ -17,9 +17,9 @@ func DomainBlockToMsgBlock(domainBlock *externalapi.DomainBlock) *MsgBlock {
}
}
// DomainBlockHeaderToBlockHeader converts an externalapi.DomainBlockHeader to BlockHeader
func DomainBlockHeaderToBlockHeader(domainBlockHeader *externalapi.DomainBlockHeader) *BlockHeader {
return &BlockHeader{
// DomainBlockHeaderToBlockHeader converts an externalapi.DomainBlockHeader to MsgBlockHeader
func DomainBlockHeaderToBlockHeader(domainBlockHeader *externalapi.DomainBlockHeader) *MsgBlockHeader {
return &MsgBlockHeader{
Version: domainBlockHeader.Version,
ParentHashes: domainBlockHeader.ParentHashes,
HashMerkleRoot: &domainBlockHeader.HashMerkleRoot,
@ -44,8 +44,8 @@ func MsgBlockToDomainBlock(msgBlock *MsgBlock) *externalapi.DomainBlock {
}
}
// BlockHeaderToDomainBlockHeader converts a BlockHeader to externalapi.DomainBlockHeader
func BlockHeaderToDomainBlockHeader(blockHeader *BlockHeader) *externalapi.DomainBlockHeader {
// BlockHeaderToDomainBlockHeader converts a MsgBlockHeader to externalapi.DomainBlockHeader
func BlockHeaderToDomainBlockHeader(blockHeader *MsgBlockHeader) *externalapi.DomainBlockHeader {
return &externalapi.DomainBlockHeader{
Version: blockHeader.Version,
ParentHashes: blockHeader.ParentHashes,

View File

@ -34,7 +34,7 @@ const (
CmdVerAck
CmdRequestAddresses
CmdAddresses
CmdRequestIBDBlocks
CmdRequestHeaders
CmdBlock
CmdTx
CmdPing
@ -48,10 +48,15 @@ const (
CmdInvTransaction
CmdRequestTransactions
CmdIBDBlock
CmdRequestNextIBDBlocks
CmdDoneIBDBlocks
CmdDoneHeaders
CmdTransactionNotFound
CmdReject
CmdHeader
CmdRequestNextHeaders
CmdRequestIBDRootUTXOSetAndBlock
CmdIBDRootUTXOSetAndBlock
CmdRequestIBDBlocks
CmdIBDRootNotFound
// rpc
CmdGetCurrentNetworkRequestMessage
@ -107,28 +112,32 @@ const (
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
var ProtocolMessageCommandToString = map[MessageCommand]string{
CmdVersion: "Version",
CmdVerAck: "VerAck",
CmdRequestAddresses: "RequestAddresses",
CmdAddresses: "Addresses",
CmdRequestIBDBlocks: "RequestBlocks",
CmdBlock: "Block",
CmdTx: "Tx",
CmdPing: "Ping",
CmdPong: "Pong",
CmdRequestBlockLocator: "RequestBlockLocator",
CmdBlockLocator: "BlockLocator",
CmdSelectedTip: "SelectedTip",
CmdRequestSelectedTip: "RequestSelectedTip",
CmdInvRelayBlock: "InvRelayBlock",
CmdRequestRelayBlocks: "RequestRelayBlocks",
CmdInvTransaction: "InvTransaction",
CmdRequestTransactions: "RequestTransactions",
CmdIBDBlock: "IBDBlock",
CmdRequestNextIBDBlocks: "RequestNextIBDBlocks",
CmdDoneIBDBlocks: "DoneIBDBlocks",
CmdTransactionNotFound: "TransactionNotFound",
CmdReject: "Reject",
CmdVersion: "Version",
CmdVerAck: "VerAck",
CmdRequestAddresses: "RequestAddresses",
CmdAddresses: "Addresses",
CmdRequestHeaders: "RequestBlocks",
CmdBlock: "Block",
CmdTx: "Tx",
CmdPing: "Ping",
CmdPong: "Pong",
CmdRequestBlockLocator: "RequestBlockLocator",
CmdBlockLocator: "BlockLocator",
CmdSelectedTip: "SelectedTip",
CmdRequestSelectedTip: "RequestSelectedTip",
CmdInvRelayBlock: "InvRelayBlock",
CmdRequestRelayBlocks: "RequestRelayBlocks",
CmdInvTransaction: "InvTransaction",
CmdRequestTransactions: "RequestTransactions",
CmdIBDBlock: "IBDBlock",
CmdDoneHeaders: "DoneIBDBlocks",
CmdTransactionNotFound: "TransactionNotFound",
CmdReject: "Reject",
CmdHeader: "Header",
CmdRequestNextHeaders: "RequestNextHeaders",
CmdRequestIBDRootUTXOSetAndBlock: "RequestPruningUTXOSetAndBlock",
CmdIBDRootUTXOSetAndBlock: "IBDRootUTXOSetAndBlock",
CmdIBDRootNotFound: "IBDRootNotFound",
}
// RPCMessageCommandToString maps all MessageCommands to their string representation

View File

@ -0,0 +1,22 @@
package appmessage
// MsgIBDRootNotFound implements the Message interface and represents a kaspa
// IBDRootNotFound message. It is used to notify the IBD root that was requested
// by other peer was not found.
//
// This message has no payload.
type MsgIBDRootNotFound struct {
baseMessage
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgIBDRootNotFound) Command() MessageCommand {
return CmdDoneHeaders
}
// NewMsgIBDRootNotFound returns a new kaspa IBDRootNotFound message that conforms to the
// Message interface.
func NewMsgIBDRootNotFound() *MsgDoneHeaders {
return &MsgDoneHeaders{}
}

View File

@ -40,7 +40,7 @@ type TxLoc struct {
// response to a getdata message (MsgGetData) for a given block hash.
type MsgBlock struct {
baseMessage
Header BlockHeader
Header MsgBlockHeader
Transactions []*MsgTx
}
@ -79,7 +79,7 @@ func (msg *MsgBlock) ConvertToPartial(subnetworkID *externalapi.DomainSubnetwork
// NewMsgBlock returns a new kaspa block message that conforms to the
// Message interface. See MsgBlock for details.
func NewMsgBlock(blockHeader *BlockHeader) *MsgBlock {
func NewMsgBlock(blockHeader *MsgBlockHeader) *MsgBlock {
return &MsgBlock{
Header: *blockHeader,
Transactions: make([]*MsgTx, 0, defaultTransactionAlloc),

View File

@ -129,7 +129,7 @@ func TestConvertToPartial(t *testing.T) {
// blockOne is the first block in the mainnet block DAG.
var blockOne = MsgBlock{
Header: BlockHeader{
Header: MsgBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{mainnetGenesisHash, simnetGenesisHash},
HashMerkleRoot: mainnetGenesisMerkleRoot,

View File

@ -31,9 +31,11 @@ const MaxNumParentBlocks = 255
// BaseBlockHeaderPayload + up to MaxNumParentBlocks hashes of parent blocks
const MaxBlockHeaderPayload = BaseBlockHeaderPayload + (MaxNumParentBlocks * externalapi.DomainHashSize)
// BlockHeader defines information about a block and is used in the kaspa
// MsgBlockHeader defines information about a block and is used in the kaspa
// block (MsgBlock) and headers (MsgHeader) messages.
type BlockHeader struct {
type MsgBlockHeader struct {
baseMessage
// Version of the block. This is not the same as the protocol version.
Version int32
@ -61,7 +63,7 @@ type BlockHeader struct {
}
// NumParentBlocks return the number of entries in ParentHashes
func (h *BlockHeader) NumParentBlocks() byte {
func (h *MsgBlockHeader) NumParentBlocks() byte {
numParents := len(h.ParentHashes)
if numParents > math.MaxUint8 {
panic(errors.Errorf("number of parents is %d, which is more than one byte can fit", numParents))
@ -70,24 +72,30 @@ func (h *BlockHeader) NumParentBlocks() byte {
}
// BlockHash computes the block identifier hash for the given block header.
func (h *BlockHeader) BlockHash() *externalapi.DomainHash {
func (h *MsgBlockHeader) BlockHash() *externalapi.DomainHash {
return consensusserialization.HeaderHash(BlockHeaderToDomainBlockHeader(h))
}
// IsGenesis returns true iff this block is a genesis block
func (h *BlockHeader) IsGenesis() bool {
func (h *MsgBlockHeader) IsGenesis() bool {
return h.NumParentBlocks() == 0
}
// NewBlockHeader returns a new BlockHeader using the provided version, previous
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (h *MsgBlockHeader) Command() MessageCommand {
return CmdHeader
}
// NewBlockHeader returns a new MsgBlockHeader using the provided version, previous
// block hash, hash merkle root, accepted ID merkle root, difficulty bits, and nonce used to generate the
// block with defaults or calclulated values for the remaining fields.
func NewBlockHeader(version int32, parentHashes []*externalapi.DomainHash, hashMerkleRoot *externalapi.DomainHash,
acceptedIDMerkleRoot *externalapi.DomainHash, utxoCommitment *externalapi.DomainHash, bits uint32, nonce uint64) *BlockHeader {
acceptedIDMerkleRoot *externalapi.DomainHash, utxoCommitment *externalapi.DomainHash, bits uint32, nonce uint64) *MsgBlockHeader {
// Limit the timestamp to one millisecond precision since the protocol
// doesn't support better.
return &BlockHeader{
return &MsgBlockHeader{
Version: version,
ParentHashes: parentHashes,
HashMerkleRoot: hashMerkleRoot,

View File

@ -14,7 +14,7 @@ import (
"github.com/kaspanet/kaspad/util/random"
)
// TestBlockHeader tests the BlockHeader API.
// TestBlockHeader tests the MsgBlockHeader API.
func TestBlockHeader(t *testing.T) {
nonce, err := random.Uint64()
if err != nil {
@ -52,7 +52,7 @@ func TestIsGenesis(t *testing.T) {
bits := uint32(0x1d00ffff)
timestamp := mstime.UnixMilliseconds(0x495fab29000)
baseBlockHdr := &BlockHeader{
baseBlockHdr := &MsgBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{mainnetGenesisHash, simnetGenesisHash},
HashMerkleRoot: mainnetGenesisMerkleRoot,
@ -60,7 +60,7 @@ func TestIsGenesis(t *testing.T) {
Bits: bits,
Nonce: nonce,
}
genesisBlockHdr := &BlockHeader{
genesisBlockHdr := &MsgBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{},
HashMerkleRoot: mainnetGenesisMerkleRoot,
@ -70,8 +70,8 @@ func TestIsGenesis(t *testing.T) {
}
tests := []struct {
in *BlockHeader // Block header to encode
isGenesis bool // Expected result for call of .IsGenesis
in *MsgBlockHeader // Block header to encode
isGenesis bool // Expected result for call of .IsGenesis
}{
{genesisBlockHdr, true},
{baseBlockHdr, false},
@ -81,7 +81,7 @@ func TestIsGenesis(t *testing.T) {
for i, test := range tests {
isGenesis := test.in.IsGenesis()
if isGenesis != test.isGenesis {
t.Errorf("BlockHeader.IsGenesis: #%d got: %t, want: %t",
t.Errorf("MsgBlockHeader.IsGenesis: #%d got: %t, want: %t",
i, isGenesis, test.isGenesis)
}
}

View File

@ -0,0 +1,22 @@
package appmessage
// MsgDoneHeaders implements the Message interface and represents a kaspa
// DoneHeaders message. It is used to notify the IBD syncing peer that the
// syncer sent all the requested headers.
//
// This message has no payload.
type MsgDoneHeaders struct {
baseMessage
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgDoneHeaders) Command() MessageCommand {
return CmdDoneHeaders
}
// NewMsgDoneHeaders returns a new kaspa DoneIBDBlocks message that conforms to the
// Message interface.
func NewMsgDoneHeaders() *MsgDoneHeaders {
return &MsgDoneHeaders{}
}

View File

@ -1,22 +0,0 @@
package appmessage
// MsgDoneIBDBlocks implements the Message interface and represents a kaspa
// DoneIBDBlocks message. It is used to notify the IBD syncing peer that the
// syncer sent all the requested blocks.
//
// This message has no payload.
type MsgDoneIBDBlocks struct {
baseMessage
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgDoneIBDBlocks) Command() MessageCommand {
return CmdDoneIBDBlocks
}
// NewMsgDoneIBDBlocks returns a new kaspa DoneIBDBlocks message that conforms to the
// Message interface.
func NewMsgDoneIBDBlocks() *MsgDoneIBDBlocks {
return &MsgDoneIBDBlocks{}
}

View File

@ -0,0 +1,23 @@
package appmessage
// MsgIBDRootUTXOSetAndBlock implements the Message interface and represents a kaspa
// IBDRootUTXOSetAndBlock message. It is used to answer RequestIBDRootUTXOSetAndBlock messages.
type MsgIBDRootUTXOSetAndBlock struct {
baseMessage
UTXOSet []byte
Block *MsgBlock
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgIBDRootUTXOSetAndBlock) Command() MessageCommand {
return CmdRequestIBDRootUTXOSetAndBlock
}
// NewMsgIBDRootUTXOSetAndBlock returns a new MsgIBDRootUTXOSetAndBlock.
func NewMsgIBDRootUTXOSetAndBlock(utxoSet []byte, block *MsgBlock) *MsgIBDRootUTXOSetAndBlock {
return &MsgIBDRootUTXOSetAndBlock{
UTXOSet: utxoSet,
Block: block,
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package appmessage
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// MsgRequestHeaders implements the Message interface and represents a kaspa
// RequestHeaders message. It is used to request a list of blocks starting after the
// low hash and until the high hash.
type MsgRequestHeaders struct {
baseMessage
LowHash *externalapi.DomainHash
HighHash *externalapi.DomainHash
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgRequestHeaders) Command() MessageCommand {
return CmdRequestHeaders
}
// NewMsgRequstHeaders returns a new kaspa RequestHeaders message that conforms to the
// Message interface using the passed parameters and defaults for the remaining
// fields.
func NewMsgRequstHeaders(lowHash, highHash *externalapi.DomainHash) *MsgRequestHeaders {
return &MsgRequestHeaders{
LowHash: lowHash,
HighHash: highHash,
}
}

View File

@ -10,7 +10,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
)
// TestRequstIBDBlocks tests the MsgRequestIBDBlocks API.
// TestRequstIBDBlocks tests the MsgRequestHeaders API.
func TestRequstIBDBlocks(t *testing.T) {
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
lowHash, err := hashes.FromString(hashStr)
@ -25,16 +25,16 @@ func TestRequstIBDBlocks(t *testing.T) {
}
// Ensure we get the same data back out.
msg := NewMsgRequstIBDBlocks(lowHash, highHash)
msg := NewMsgRequstHeaders(lowHash, highHash)
if *msg.HighHash != *highHash {
t.Errorf("NewMsgRequstIBDBlocks: wrong high hash - got %v, want %v",
t.Errorf("NewMsgRequstHeaders: wrong high hash - got %v, want %v",
msg.HighHash, highHash)
}
// Ensure the command is expected value.
wantCmd := MessageCommand(4)
if cmd := msg.Command(); cmd != wantCmd {
t.Errorf("NewMsgRequstIBDBlocks: wrong command - got %v want %v",
t.Errorf("NewMsgRequstHeaders: wrong command - got %v want %v",
cmd, wantCmd)
}
}

View File

@ -1,20 +1,19 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package appmessage
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// MaxRequestIBDBlocksHashes is the maximum number of hashes that can
// be in a single RequestIBDBlocks message.
const MaxRequestIBDBlocksHashes = MaxInvPerMsg
// MsgRequestIBDBlocks implements the Message interface and represents a kaspa
// RequestIBDBlocks message. It is used to request a list of blocks starting after the
// low hash and until the high hash.
// RequestIBDBlocks message. It is used to request blocks as part of the IBD
// protocol.
type MsgRequestIBDBlocks struct {
baseMessage
LowHash *externalapi.DomainHash
HighHash *externalapi.DomainHash
Hashes []*externalapi.DomainHash
}
// Command returns the protocol command string for the message. This is part
@ -23,12 +22,9 @@ func (msg *MsgRequestIBDBlocks) Command() MessageCommand {
return CmdRequestIBDBlocks
}
// NewMsgRequstIBDBlocks returns a new kaspa RequestIBDBlocks message that conforms to the
// Message interface using the passed parameters and defaults for the remaining
// fields.
func NewMsgRequstIBDBlocks(lowHash, highHash *externalapi.DomainHash) *MsgRequestIBDBlocks {
// NewMsgRequestIBDBlocks returns a new MsgRequestIBDBlocks.
func NewMsgRequestIBDBlocks(hashes []*externalapi.DomainHash) *MsgRequestIBDBlocks {
return &MsgRequestIBDBlocks{
LowHash: lowHash,
HighHash: highHash,
Hashes: hashes,
}
}

View File

@ -0,0 +1,26 @@
package appmessage
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// MsgRequestIBDRootUTXOSetAndBlock implements the Message interface and represents a kaspa
// RequestIBDRootUTXOSetAndBlock message. It is used to request the UTXO set and block body
// of the IBD root block.
type MsgRequestIBDRootUTXOSetAndBlock struct {
baseMessage
IBDRoot *externalapi.DomainHash
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgRequestIBDRootUTXOSetAndBlock) Command() MessageCommand {
return CmdRequestIBDRootUTXOSetAndBlock
}
// NewMsgRequestIBDRootUTXOSetAndBlock returns a new MsgRequestIBDRootUTXOSetAndBlock.
func NewMsgRequestIBDRootUTXOSetAndBlock(ibdRoot *externalapi.DomainHash) *MsgRequestIBDRootUTXOSetAndBlock {
return &MsgRequestIBDRootUTXOSetAndBlock{
IBDRoot: ibdRoot,
}
}

View File

@ -0,0 +1,22 @@
package appmessage
// MsgRequestNextHeaders implements the Message interface and represents a kaspa
// RequestNextHeaders message. It is used to notify the IBD syncer peer to send
// more headers.
//
// This message has no payload.
type MsgRequestNextHeaders struct {
baseMessage
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgRequestNextHeaders) Command() MessageCommand {
return CmdRequestNextHeaders
}
// NewMsgRequestNextHeaders returns a new kaspa RequestNextHeaders message that conforms to the
// Message interface.
func NewMsgRequestNextHeaders() *MsgRequestNextHeaders {
return &MsgRequestNextHeaders{}
}

View File

@ -1,22 +0,0 @@
package appmessage
// MsgRequestNextIBDBlocks implements the Message interface and represents a kaspa
// RequestNextIBDBlocks message. It is used to notify the IBD syncer peer to send
// more blocks.
//
// This message has no payload.
type MsgRequestNextIBDBlocks struct {
baseMessage
}
// Command returns the protocol command string for the message. This is part
// of the Message interface implementation.
func (msg *MsgRequestNextIBDBlocks) Command() MessageCommand {
return CmdRequestNextIBDBlocks
}
// NewMsgRequestNextIBDBlocks returns a new kaspa RequestNextIBDBlocks message that conforms to the
// Message interface.
func NewMsgRequestNextIBDBlocks() *MsgRequestNextIBDBlocks {
return &MsgRequestNextIBDBlocks{}
}

View File

@ -4,9 +4,9 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// MsgRequestRelayBlocksHashes is the maximum number of hashes that can
// MaxRequestRelayBlocksHashes is the maximum number of hashes that can
// be in a single RequestRelayBlocks message.
const MsgRequestRelayBlocksHashes = MaxInvPerMsg
const MaxRequestRelayBlocksHashes = MaxInvPerMsg
// MsgRequestRelayBlocks implements the Message interface and represents a kaspa
// RequestRelayBlocks message. It is used to request blocks as part of the block

View File

@ -1,6 +1,7 @@
package flowcontext
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"sync/atomic"
"time"
@ -19,7 +20,16 @@ func (f *FlowContext) StartIBDIfRequired() error {
return nil
}
peer, err := f.selectPeerForIBD()
syncInfo, err := f.domain.Consensus().GetSyncInfo()
if err != nil {
return err
}
if syncInfo.State == externalapi.SyncStateRelay {
return nil
}
peer, err := f.selectPeerForIBD(syncInfo)
if err != nil {
return err
}
@ -42,20 +52,32 @@ func (f *FlowContext) IsInIBD() bool {
// selectPeerForIBD returns the first peer whose selected tip
// hash is not in our DAG
func (f *FlowContext) selectPeerForIBD() (*peerpkg.Peer, error) {
func (f *FlowContext) selectPeerForIBD(syncInfo *externalapi.SyncInfo) (*peerpkg.Peer, error) {
f.peersMutex.RLock()
defer f.peersMutex.RUnlock()
for _, peer := range f.peers {
peerSelectedTipHash := peer.SelectedTipHash()
blockInfo, err := f.domain.Consensus().GetBlockInfo(peerSelectedTipHash)
if err != nil {
return nil, err
}
if !blockInfo.Exists {
return peer, nil
if syncInfo.State == externalapi.SyncStateHeadersFirst {
for _, peer := range f.peers {
peerSelectedTipHash := peer.SelectedTipHash()
blockInfo, err := f.domain.Consensus().GetBlockInfo(peerSelectedTipHash)
if err != nil {
return nil, err
}
if syncInfo.State == externalapi.SyncStateHeadersFirst {
if !blockInfo.Exists {
return peer, nil
}
} else {
if blockInfo.Exists && blockInfo.BlockStatus == externalapi.StatusHeaderOnly &&
blockInfo.IsBlockInHeaderPruningPointFuture {
return peer, nil
}
}
}
return nil, nil
}
return nil, nil
}

View File

@ -114,7 +114,7 @@ func (flow *handleRelayInvsFlow) readInv() (*appmessage.MsgInvRelayBlock, error)
}
func (flow *handleRelayInvsFlow) requestBlocks(requestQueue *hashesQueueSet) error {
numHashesToRequest := mathUtil.MinInt(appmessage.MsgRequestRelayBlocksHashes, requestQueue.len())
numHashesToRequest := mathUtil.MinInt(appmessage.MaxRequestRelayBlocksHashes, requestQueue.len())
hashesToRequest := requestQueue.dequeue(numHashesToRequest)
pendingBlocks := map[externalapi.DomainHash]struct{}{}

View File

@ -0,0 +1,49 @@
package ibd
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
"github.com/kaspanet/kaspad/domain"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
"github.com/pkg/errors"
)
// HandleIBDBlockRequestsContext is the interface for the context needed for the HandleIBDBlockRequests flow.
type HandleIBDBlockRequestsContext interface {
Domain() domain.Domain
}
// HandleIBDBlockRequests listens to appmessage.MsgRequestRelayBlocks messages and sends
// their corresponding blocks to the requesting peer.
func HandleIBDBlockRequests(context HandleIBDBlockRequestsContext, incomingRoute *router.Route,
outgoingRoute *router.Route) error {
for {
message, err := incomingRoute.Dequeue()
if err != nil {
return err
}
msgRequestIBDBlocks := message.(*appmessage.MsgRequestIBDBlocks)
for _, hash := range msgRequestIBDBlocks.Hashes {
// Fetch the block from the database.
blockInfo, err := context.Domain().Consensus().GetBlockInfo(hash)
if err != nil {
return err
}
if !blockInfo.Exists {
return protocolerrors.Errorf(true, "block %s not found", hash)
}
block, err := context.Domain().Consensus().GetBlock(hash)
if err != nil {
return errors.Wrapf(err, "unable to fetch requested block hash %s", hash)
}
// TODO (Partial nodes): Convert block to partial block if needed
err = outgoingRoute.Enqueue(appmessage.DomainBlockToMsgBlock(block))
if err != nil {
return err
}
}
}
}

View File

@ -11,7 +11,7 @@ import (
const ibdBatchSize = router.DefaultMaxMessages
// RequestIBDBlocksContext is the interface for the context needed for the HandleRequestIBDBlocks flow.
// RequestIBDBlocksContext is the interface for the context needed for the HandleRequestHeaders flow.
type RequestIBDBlocksContext interface {
Domain() domain.Domain
}
@ -21,8 +21,8 @@ type handleRequestBlocksFlow struct {
incomingRoute, outgoingRoute *router.Route
}
// HandleRequestIBDBlocks handles getBlocks messages
func HandleRequestIBDBlocks(context RequestIBDBlocksContext, incomingRoute *router.Route, outgoingRoute *router.Route) error {
// HandleRequestHeaders handles RequestHeaders messages
func HandleRequestHeaders(context RequestIBDBlocksContext, incomingRoute *router.Route, outgoingRoute *router.Route) error {
flow := &handleRequestBlocksFlow{
RequestIBDBlocksContext: context,
incomingRoute: incomingRoute,
@ -33,24 +33,24 @@ func HandleRequestIBDBlocks(context RequestIBDBlocksContext, incomingRoute *rout
func (flow *handleRequestBlocksFlow) start() error {
for {
lowHash, highHash, err := receiveRequestIBDBlocks(flow.incomingRoute)
lowHash, highHash, err := receiveRequestHeaders(flow.incomingRoute)
if err != nil {
return err
}
msgIBDBlocks, err := flow.buildMsgIBDBlocks(lowHash, highHash)
msgHeaders, err := flow.buildMsgBlockHeaders(lowHash, highHash)
if err != nil {
return err
}
for offset := 0; offset < len(msgIBDBlocks); offset += ibdBatchSize {
for offset := 0; offset < len(msgHeaders); offset += ibdBatchSize {
end := offset + ibdBatchSize
if end > len(msgIBDBlocks) {
end = len(msgIBDBlocks)
if end > len(msgHeaders) {
end = len(msgHeaders)
}
blocksToSend := msgIBDBlocks[offset:end]
err = flow.sendMsgIBDBlocks(blocksToSend)
blocksToSend := msgHeaders[offset:end]
err = flow.sendHeaders(blocksToSend)
if err != nil {
return nil
}
@ -66,56 +66,56 @@ func (flow *handleRequestBlocksFlow) start() error {
return err
}
if _, ok := message.(*appmessage.MsgRequestNextIBDBlocks); !ok {
if _, ok := message.(*appmessage.MsgRequestNextHeaders); !ok {
return protocolerrors.Errorf(true, "received unexpected message type. "+
"expected: %s, got: %s", appmessage.CmdRequestNextIBDBlocks, message.Command())
"expected: %s, got: %s", appmessage.CmdRequestNextHeaders, message.Command())
}
}
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgDoneIBDBlocks())
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgDoneHeaders())
if err != nil {
return err
}
}
}
func receiveRequestIBDBlocks(incomingRoute *router.Route) (lowHash *externalapi.DomainHash,
func receiveRequestHeaders(incomingRoute *router.Route) (lowHash *externalapi.DomainHash,
highHash *externalapi.DomainHash, err error) {
message, err := incomingRoute.Dequeue()
if err != nil {
return nil, nil, err
}
msgRequestIBDBlocks := message.(*appmessage.MsgRequestIBDBlocks)
msgRequestIBDBlocks := message.(*appmessage.MsgRequestHeaders)
return msgRequestIBDBlocks.LowHash, msgRequestIBDBlocks.HighHash, nil
}
func (flow *handleRequestBlocksFlow) buildMsgIBDBlocks(lowHash *externalapi.DomainHash,
highHash *externalapi.DomainHash) ([]*appmessage.MsgIBDBlock, error) {
func (flow *handleRequestBlocksFlow) buildMsgBlockHeaders(lowHash *externalapi.DomainHash,
highHash *externalapi.DomainHash) ([]*appmessage.MsgBlockHeader, error) {
blockHashes, err := flow.Domain().Consensus().GetHashesBetween(lowHash, highHash)
if err != nil {
return nil, err
}
const maxHashesInMsgIBDBlocks = appmessage.MaxInvPerMsg
if len(blockHashes) > maxHashesInMsgIBDBlocks {
blockHashes = blockHashes[:maxHashesInMsgIBDBlocks]
const maxHeaders = appmessage.MaxInvPerMsg
if len(blockHashes) > maxHeaders {
blockHashes = blockHashes[:maxHeaders]
}
msgIBDBlocks := make([]*appmessage.MsgIBDBlock, len(blockHashes))
msgBlockHeaders := make([]*appmessage.MsgBlockHeader, len(blockHashes))
for i, blockHash := range blockHashes {
block, err := flow.Domain().Consensus().GetBlock(blockHash)
header, err := flow.Domain().Consensus().GetBlockHeader(blockHash)
if err != nil {
return nil, err
}
msgIBDBlocks[i] = appmessage.NewMsgIBDBlock(appmessage.DomainBlockToMsgBlock(block))
msgBlockHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(header)
}
return msgIBDBlocks, nil
return msgBlockHeaders, nil
}
func (flow *handleRequestBlocksFlow) sendMsgIBDBlocks(msgIBDBlocks []*appmessage.MsgIBDBlock) error {
for _, msgIBDBlock := range msgIBDBlocks {
func (flow *handleRequestBlocksFlow) sendHeaders(headers []*appmessage.MsgBlockHeader) error {
for _, msgIBDBlock := range headers {
err := flow.outgoingRoute.Enqueue(msgIBDBlock)
if err != nil {
return err

View File

@ -0,0 +1,65 @@
package ibd
import (
"errors"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/domain"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
)
// HandleRequestIBDRootUTXOSetAndBlockContext is the interface for the context needed for the HandleRequestIBDRootUTXOSetAndBlock flow.
type HandleRequestIBDRootUTXOSetAndBlockContext interface {
Domain() domain.Domain
}
type handleRequestIBDRootUTXOSetAndBlockFlow struct {
HandleRequestIBDRootUTXOSetAndBlockContext
incomingRoute, outgoingRoute *router.Route
}
// HandleRequestIBDRootUTXOSetAndBlock listens to appmessage.MsgRequestIBDRootUTXOSetAndBlock messages and sends
// the IBD root UTXO set and block body.
func HandleRequestIBDRootUTXOSetAndBlock(context HandleRequestIBDRootUTXOSetAndBlockContext, incomingRoute,
outgoingRoute *router.Route) error {
flow := &handleRequestIBDRootUTXOSetAndBlockFlow{
HandleRequestIBDRootUTXOSetAndBlockContext: context,
incomingRoute: incomingRoute,
outgoingRoute: outgoingRoute,
}
return flow.start()
}
func (flow *handleRequestIBDRootUTXOSetAndBlockFlow) start() error {
for {
message, err := flow.incomingRoute.Dequeue()
if err != nil {
return err
}
msgRequestIBDRootUTXOSetAndBlock := message.(*appmessage.MsgRequestIBDRootUTXOSetAndBlock)
utxoSet, err := flow.Domain().Consensus().GetPruningPointUTXOSet(msgRequestIBDRootUTXOSetAndBlock.IBDRoot)
if err != nil {
if errors.Is(err, ruleerrors.ErrWrongPruningPointHash) {
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgIBDRootNotFound())
if err != nil {
return err
}
continue
}
}
block, err := flow.Domain().Consensus().GetBlock(msgRequestIBDRootUTXOSetAndBlock.IBDRoot)
if err != nil {
return err
}
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgIBDRootUTXOSetAndBlock(utxoSet,
appmessage.DomainBlockToMsgBlock(block)))
if err != nil {
return err
}
}
}

View File

@ -53,8 +53,53 @@ func (flow *handleIBDFlow) start() error {
func (flow *handleIBDFlow) runIBD() error {
flow.peer.WaitForIBDStart()
defer flow.FinishIBD()
err := flow.ibdLoop()
if err != nil {
finishIBDErr := flow.FinishIBD()
if finishIBDErr != nil {
return finishIBDErr
}
return err
}
return flow.FinishIBD()
}
func (flow *handleIBDFlow) ibdLoop() error {
for {
syncInfo, err := flow.Domain().Consensus().GetSyncInfo()
if err != nil {
return err
}
switch syncInfo.State {
case externalapi.SyncStateHeadersFirst:
err := flow.syncHeaders()
if err != nil {
return err
}
case externalapi.SyncStateMissingUTXOSet:
found, err := flow.fetchMissingUTXOSet(syncInfo.IBDRootUTXOBlockHash)
if err != nil {
return err
}
if !found {
return nil
}
case externalapi.SyncStateMissingBlockBodies:
err := flow.syncMissingBlockBodies()
if err != nil {
return err
}
case externalapi.SyncStateRelay:
return nil
default:
return errors.Errorf("unexpected state %s", syncInfo.State)
}
}
}
func (flow *handleIBDFlow) syncHeaders() error {
peerSelectedTipHash := flow.peer.SelectedTipHash()
log.Debugf("Trying to find highest shared chain block with peer %s with selected tip %s", flow.peer, peerSelectedTipHash)
highestSharedBlockHash, err := flow.findHighestSharedBlockHash(peerSelectedTipHash)
@ -64,7 +109,104 @@ func (flow *handleIBDFlow) runIBD() error {
log.Debugf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
return flow.downloadBlocks(highestSharedBlockHash, peerSelectedTipHash)
return flow.downloadHeaders(highestSharedBlockHash, peerSelectedTipHash)
}
func (flow *handleIBDFlow) syncMissingBlockBodies() error {
hashes, err := flow.Domain().Consensus().GetMissingBlockBodyHashes(flow.peer.SelectedTipHash())
if err != nil {
return err
}
for offset := 0; offset < len(hashes); offset += appmessage.MaxRequestIBDBlocksHashes {
var hashesToRequest []*externalapi.DomainHash
if offset+appmessage.MaxRequestIBDBlocksHashes < len(hashes) {
hashesToRequest = hashes[offset : offset+appmessage.MaxRequestIBDBlocksHashes]
} else {
hashesToRequest = hashes[offset:]
}
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestIBDBlocks(hashesToRequest))
if err != nil {
return err
}
for _, expectedHash := range hashesToRequest {
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
if err != nil {
return err
}
msgIBDBlock, ok := message.(*appmessage.MsgIBDBlock)
if !ok {
return protocolerrors.Errorf(true, "received unexpected message type. "+
"expected: %s, got: %s", appmessage.CmdIBDBlock, message.Command())
}
block := appmessage.MsgBlockToDomainBlock(msgIBDBlock.MsgBlock)
blockHash := consensusserialization.BlockHash(block)
if *expectedHash != *blockHash {
return protocolerrors.Errorf(true, "expected block %s but got %s", expectedHash, blockHash)
}
err = flow.Domain().Consensus().ValidateAndInsertBlock(block)
if err != nil {
return protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "invalid block %s", blockHash)
}
}
}
return nil
}
func (flow *handleIBDFlow) fetchMissingUTXOSet(ibdRootHash *externalapi.DomainHash) (bool, error) {
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestIBDRootUTXOSetAndBlock(ibdRootHash))
if err != nil {
return false, err
}
utxoSet, block, found, err := flow.receiveIBDRootUTXOSetAndBlock()
if err != nil {
return false, err
}
if !found {
return false, nil
}
err = flow.Domain().Consensus().ValidateAndInsertBlock(block)
if err != nil {
blockHash := consensusserialization.BlockHash(block)
return false, protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "got invalid block %s during IBD", blockHash)
}
err = flow.Domain().Consensus().SetPruningPointUTXOSet(utxoSet)
if err != nil {
return false, protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "error with IBD root UTXO set")
}
return true, nil
}
func (flow *handleIBDFlow) receiveIBDRootUTXOSetAndBlock() ([]byte, *externalapi.DomainBlock, bool, error) {
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
if err != nil {
return nil, nil, false, err
}
switch message := message.(type) {
case *appmessage.MsgIBDRootUTXOSetAndBlock:
return message.UTXOSet,
appmessage.MsgBlockToDomainBlock(message.Block), true, nil
case *appmessage.MsgIBDRootNotFound:
return nil, nil, false, nil
default:
return nil, nil, false,
protocolerrors.Errorf(true, "received unexpected message type. "+
"expected: %s or %s, got: %s",
appmessage.CmdIBDRootUTXOSetAndBlock, appmessage.CmdIBDRootNotFound, message.Command(),
)
}
}
func (flow *handleIBDFlow) findHighestSharedBlockHash(peerSelectedTipHash *externalapi.DomainHash) (lowHash *externalapi.DomainHash,
@ -123,17 +265,17 @@ func (flow *handleIBDFlow) receiveBlockLocator() (blockLocatorHashes []*external
return msgBlockLocator.BlockLocatorHashes, nil
}
func (flow *handleIBDFlow) downloadBlocks(highestSharedBlockHash *externalapi.DomainHash,
func (flow *handleIBDFlow) downloadHeaders(highestSharedBlockHash *externalapi.DomainHash,
peerSelectedTipHash *externalapi.DomainHash) error {
err := flow.sendGetBlocks(highestSharedBlockHash, peerSelectedTipHash)
err := flow.sendRequestHeaders(highestSharedBlockHash, peerSelectedTipHash)
if err != nil {
return err
}
blocksReceived := 0
for {
msgIBDBlock, doneIBD, err := flow.receiveIBDBlock()
msgBlockHeader, doneIBD, err := flow.receiveHeader()
if err != nil {
return err
}
@ -142,14 +284,14 @@ func (flow *handleIBDFlow) downloadBlocks(highestSharedBlockHash *externalapi.Do
return nil
}
err = flow.processIBDBlock(msgIBDBlock)
err = flow.processHeader(msgBlockHeader)
if err != nil {
return err
}
blocksReceived++
if blocksReceived%ibdBatchSize == 0 {
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestNextIBDBlocks())
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestNextHeaders())
if err != nil {
return err
}
@ -157,47 +299,52 @@ func (flow *handleIBDFlow) downloadBlocks(highestSharedBlockHash *externalapi.Do
}
}
func (flow *handleIBDFlow) sendGetBlocks(highestSharedBlockHash *externalapi.DomainHash,
func (flow *handleIBDFlow) sendRequestHeaders(highestSharedBlockHash *externalapi.DomainHash,
peerSelectedTipHash *externalapi.DomainHash) error {
msgGetBlockInvs := appmessage.NewMsgRequstIBDBlocks(highestSharedBlockHash, peerSelectedTipHash)
msgGetBlockInvs := appmessage.NewMsgRequstHeaders(highestSharedBlockHash, peerSelectedTipHash)
return flow.outgoingRoute.Enqueue(msgGetBlockInvs)
}
func (flow *handleIBDFlow) receiveIBDBlock() (msgIBDBlock *appmessage.MsgIBDBlock, doneIBD bool, err error) {
func (flow *handleIBDFlow) receiveHeader() (msgIBDBlock *appmessage.MsgBlockHeader, doneIBD bool, err error) {
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
if err != nil {
return nil, false, err
}
switch message := message.(type) {
case *appmessage.MsgIBDBlock:
case *appmessage.MsgBlockHeader:
return message, false, nil
case *appmessage.MsgDoneIBDBlocks:
case *appmessage.MsgDoneHeaders:
return nil, true, nil
default:
return nil, false,
protocolerrors.Errorf(true, "received unexpected message type. "+
"expected: %s, got: %s", appmessage.CmdIBDBlock, message.Command())
"expected: %s or %s, got: %s", appmessage.CmdHeader, appmessage.CmdDoneHeaders, message.Command())
}
}
func (flow *handleIBDFlow) processIBDBlock(msgIBDBlock *appmessage.MsgIBDBlock) error {
block := appmessage.MsgBlockToDomainBlock(msgIBDBlock.MsgBlock)
func (flow *handleIBDFlow) processHeader(msgBlockHeader *appmessage.MsgBlockHeader) error {
header := appmessage.BlockHeaderToDomainBlockHeader(msgBlockHeader)
block := &externalapi.DomainBlock{
Header: header,
Transactions: nil,
}
blockHash := consensusserialization.BlockHash(block)
blockInfo, err := flow.Domain().Consensus().GetBlockInfo(blockHash)
if err != nil {
return err
}
if blockInfo.Exists {
log.Debugf("IBD block %s is already in the DAG. Skipping...", blockHash)
log.Debugf("Block header %s is already in the DAG. Skipping...", blockHash)
return nil
}
err = flow.Domain().Consensus().ValidateAndInsertBlock(block)
if err != nil {
if !errors.As(err, &ruleerrors.RuleError{}) {
return errors.Wrapf(err, "failed to process block %s during IBD", blockHash)
return errors.Wrapf(err, "failed to process header %s during IBD", blockHash)
}
log.Infof("Rejected block %s from %s during IBD: %s", blockHash, flow.peer, err)
log.Infof("Rejected block header %s from %s during IBD: %s", blockHash, flow.peer, err)
return protocolerrors.Wrapf(true, err, "got invalid block %s during IBD", blockHash)
}

View File

@ -180,33 +180,51 @@ func (m *Manager) registerIBDFlows(router *routerpkg.Router, isStopping *uint32,
return []*flow{
m.registerFlow("HandleIBD", router, []appmessage.MessageCommand{appmessage.CmdBlockLocator, appmessage.CmdIBDBlock,
appmessage.CmdDoneIBDBlocks}, isStopping, errChan,
appmessage.CmdDoneHeaders, appmessage.CmdIBDRootNotFound, appmessage.CmdIBDRootUTXOSetAndBlock}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return ibd.HandleIBD(m.context, incomingRoute, outgoingRoute, peer)
},
),
m.registerFlow("RequestSelectedTip", router, []appmessage.MessageCommand{appmessage.CmdSelectedTip}, isStopping, errChan,
m.registerFlow("RequestSelectedTip", router,
[]appmessage.MessageCommand{appmessage.CmdSelectedTip}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return selectedtip.RequestSelectedTip(m.context, incomingRoute, outgoingRoute, peer)
},
),
m.registerFlow("HandleRequestSelectedTip", router, []appmessage.MessageCommand{appmessage.CmdRequestSelectedTip}, isStopping, errChan,
m.registerFlow("HandleRequestSelectedTip", router,
[]appmessage.MessageCommand{appmessage.CmdRequestSelectedTip}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return selectedtip.HandleRequestSelectedTip(m.context, incomingRoute, outgoingRoute)
},
),
m.registerFlow("HandleRequestBlockLocator", router, []appmessage.MessageCommand{appmessage.CmdRequestBlockLocator}, isStopping, errChan,
m.registerFlow("HandleRequestBlockLocator", router,
[]appmessage.MessageCommand{appmessage.CmdRequestBlockLocator}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return ibd.HandleRequestBlockLocator(m.context, incomingRoute, outgoingRoute)
},
),
m.registerFlow("HandleRequestIBDBlocks", router, []appmessage.MessageCommand{appmessage.CmdRequestIBDBlocks, appmessage.CmdRequestNextIBDBlocks}, isStopping, errChan,
m.registerFlow("HandleRequestHeaders", router,
[]appmessage.MessageCommand{appmessage.CmdRequestHeaders, appmessage.CmdRequestNextHeaders}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return ibd.HandleRequestIBDBlocks(m.context, incomingRoute, outgoingRoute)
return ibd.HandleRequestHeaders(m.context, incomingRoute, outgoingRoute)
},
),
m.registerFlow("HandleRequestIBDRootUTXOSetAndBlock", router,
[]appmessage.MessageCommand{appmessage.CmdRequestIBDRootUTXOSetAndBlock}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return ibd.HandleRequestIBDRootUTXOSetAndBlock(m.context, incomingRoute, outgoingRoute)
},
),
m.registerFlow("HandleIBDBlockRequests", router,
[]appmessage.MessageCommand{appmessage.CmdRequestIBDBlocks}, isStopping, errChan,
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return ibd.HandleIBDBlockRequests(m.context, incomingRoute, outgoingRoute)
},
),
}

View File

@ -1,6 +1,9 @@
package protocolerrors
import "github.com/pkg/errors"
import (
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/pkg/errors"
)
// ProtocolError is an error that signifies a violation
// of the peer-to-peer protocol
@ -50,3 +53,14 @@ func Wrapf(shouldBan bool, err error, format string, args ...interface{}) error
Cause: errors.Wrapf(err, format, args...),
}
}
// ConvertToBanningProtocolErrorIfRuleError converts the given error to
// a banning protocol error if it's a rule error, and otherwise keep it
// as is.
func ConvertToBanningProtocolErrorIfRuleError(err error, format string, args ...interface{}) error {
if !errors.As(err, &ruleerrors.RuleError{}) {
return err
}
return Wrapf(true, err, format, args...)
}

View File

@ -5,6 +5,8 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/pkg/errors"
)
type consensus struct {
@ -132,11 +134,26 @@ func (s *consensus) GetMissingBlockBodyHashes(highHash *externalapi.DomainHash)
return s.syncManager.GetMissingBlockBodyHashes(highHash)
}
func (s *consensus) GetPruningPointUTXOSet() ([]byte, error) {
func (s *consensus) GetPruningPointUTXOSet(expectedPruningPointHash *externalapi.DomainHash) ([]byte, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.pruningStore.PruningPointSerializedUTXOSet(s.databaseContext)
pruningPointHash, err := s.pruningStore.PruningPoint(s.databaseContext)
if err != nil {
return nil, err
}
if *expectedPruningPointHash != *pruningPointHash {
return nil, errors.Wrapf(ruleerrors.ErrWrongPruningPointHash, "expected pruning point %s but got %s",
expectedPruningPointHash,
pruningPointHash)
}
serializedUTXOSet, err := s.pruningStore.PruningPointSerializedUTXOSet(s.databaseContext)
if err != nil {
return nil, err
}
return serializedUTXOSet, nil
}
func (s *consensus) SetPruningPointUTXOSet(serializedUTXOSet []byte) error {

View File

@ -12,7 +12,7 @@ type Consensus interface {
GetHashesBetween(lowHash, highHash *DomainHash) ([]*DomainHash, error)
GetMissingBlockBodyHashes(highHash *DomainHash) ([]*DomainHash, error)
GetPruningPointUTXOSet() ([]byte, error)
GetPruningPointUTXOSet(expectedPruningPointHash *DomainHash) ([]byte, error)
SetPruningPointUTXOSet(serializedUTXOSet []byte) error
GetVirtualSelectedParent() (*DomainBlock, error)
CreateBlockLocator(lowHash, highHash *DomainHash) (BlockLocator, error)

View File

@ -1,9 +1,11 @@
package externalapi
import "fmt"
// Each of the following represent one of the possible sync
// states of the consensus
const (
SyncStateNormal SyncState = iota
SyncStateRelay SyncState = iota
SyncStateMissingGenesis
SyncStateHeadersFirst
SyncStateMissingUTXOSet
@ -15,8 +17,8 @@ type SyncState uint8
func (s SyncState) String() string {
switch s {
case SyncStateNormal:
return "SyncStateNormal"
case SyncStateRelay:
return "SyncStateRelay"
case SyncStateHeadersFirst:
return "SyncStateHeadersFirst"
case SyncStateMissingUTXOSet:
@ -25,7 +27,7 @@ func (s SyncState) String() string {
return "SyncStateMissingBlockBodies"
}
return "<unknown state>"
return fmt.Sprintf("<unknown state (%d)>", s)
}
// SyncInfo holds info about the current sync state of the consensus

View File

@ -34,7 +34,7 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
}
if mode.State == externalapi.SyncStateHeadersFirst && !isHeaderOnlyBlock(block) {
mode.State = externalapi.SyncStateNormal
mode.State = externalapi.SyncStateRelay
log.Warnf("block %s contains transactions while validating in header only mode", hash)
}
@ -97,7 +97,7 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
if err != nil {
return err
}
} else if mode.State == externalapi.SyncStateNormal {
} else if mode.State == externalapi.SyncStateRelay {
// Attempt to add the block to the virtual
err = bp.consensusStateManager.AddBlockToVirtual(hash)
if err != nil {
@ -118,7 +118,7 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
}
}
if mode.State == externalapi.SyncStateNormal {
if mode.State == externalapi.SyncStateRelay {
// Trigger pruning, which will check if the pruning point changed and delete the data if it did.
err = bp.pruningManager.FindNextPruningPoint()
if err != nil {

View File

@ -52,6 +52,9 @@ func (csm *consensusStateManager) restorePastUTXO(blockHash *externalapi.DomainH
utxoDiffs = append(utxoDiffs, utxoDiff)
nextBlockHash, err = csm.utxoDiffStore.UTXODiffChild(csm.databaseContext, nextBlockHash)
if err != nil {
return nil, err
}
}
// apply the diffs in reverse order

View File

@ -629,6 +629,9 @@ func (rt *reachabilityManager) reclaimIntervalAfterChosenChild(node, commonAnces
currentInterval.Start,
currentInterval.End-slackReachabilityIntervalForReclaiming,
))
if err != nil {
return err
}
currentParent, err := rt.parent(current)
if err != nil {

View File

@ -70,7 +70,7 @@ func (sm *syncManager) resolveSyncState() (externalapi.SyncState, error) {
return externalapi.SyncStateMissingBlockBodies, nil
}
return externalapi.SyncStateNormal, nil
return externalapi.SyncStateRelay, nil
}
func (sm *syncManager) virtualSelectedParentHash() (*externalapi.DomainHash, error) {

View File

@ -234,6 +234,8 @@ var (
ErrMissingBlockHeaderInIBD = newRuleError("ErrMissingBlockHeaderInIBD")
ErrMalformedUTXO = newRuleError("ErrMalformedUTXO")
ErrWrongPruningPointHash = newRuleError("ErrWrongPruningPointHash")
)
// RuleError identifies a rule violation. It is used to indicate that

View File

@ -11,9 +11,9 @@ message KaspadMessage {
RequestBlockLocatorMessage requestBlockLocator = 4;
BlockLocatorMessage blockLocator = 5;
RequestAddressesMessage requestAddresses = 6;
RequestIBDBlocksMessage requestIBDBlocks = 7;
RequestNextIBDBlocksMessage requestNextIBDBlocks = 8;
DoneIBDBlocksMessage DoneIBDBlocks = 9;
RequestHeadersMessage requestHeaders = 7;
RequestNextHeadersMessage requestNextHeaders = 8;
DoneHeadersMessage DoneHeaders = 9;
RequestRelayBlocksMessage requestRelayBlocks = 10;
RequestSelectedTipMessage requestSelectedTip = 11;
RequestTransactionsMessage requestTransactions = 12;
@ -27,6 +27,11 @@ message KaspadMessage {
VersionMessage version = 20;
TransactionNotFoundMessage transactionNotFound = 21;
RejectMessage reject = 22;
BlockHeaderMessage blockHeader = 23;
RequestIBDRootUTXOSetAndBlockMessage requestIBDRootUTXOSetAndBlock = 24;
IBDRootUTXOSetAndBlockMessage ibdRootUTXOSetAndBlock = 25;
RequestIBDBlocksMessage requestIBDBlocks = 26;
IBDRootNotFoundMessage ibdRootNotFound = 27;
GetCurrentNetworkRequestMessage getCurrentNetworkRequest = 1001;
GetCurrentNetworkResponseMessage getCurrentNetworkResponse = 1002;
@ -144,11 +149,11 @@ message TransactionOutput{
// BlockMessage start
message BlockMessage{
BlockHeader header = 1;
BlockHeaderMessage header = 1;
repeated TransactionMessage transactions = 2;
}
message BlockHeader{
message BlockHeaderMessage{
int32 version = 1;
repeated Hash parentHashes = 2;
Hash hashMerkleRoot = 3;
@ -178,27 +183,27 @@ message BlockLocatorMessage{
// BlockLocatorMessage end
// GetBlocksMessage start
message RequestIBDBlocksMessage{
message RequestHeadersMessage{
Hash lowHash = 1;
Hash highHash = 2;
}
// GetBlocksMessage end
// RequestNextIBDBlocksMessage start
message RequestNextIBDBlocksMessage{
message RequestNextHeadersMessage{
}
// RequestNextIBDBlocksMessage end
// DoneIBDBlocksMessage start
message DoneIBDBlocksMessage{
message DoneHeadersMessage{
}
// DoneIBDBlocksMessage end
// GetRelayBlocksMessage start
// RequestRelayBlocksMessage start
message RequestRelayBlocksMessage{
repeated Hash hashes = 1;
}
// GetRelayBlocksMessage end
// RequestRelayBlocksMessage end
// GetSelectedTipMessage start
message RequestSelectedTipMessage{
@ -273,6 +278,30 @@ message RejectMessage{
}
// RejectMessage end
// RequestIBDRootUTXOSetAndBlockMessage start
message RequestIBDRootUTXOSetAndBlockMessage{
Hash ibdRoot = 1;
}
// RequestIBDRootUTXOSetAndBlockMessage end
// IBDRootUTXOSetAndBlockMessage start
message IBDRootUTXOSetAndBlockMessage{
bytes utxoSet = 1;
BlockMessage block = 2;
}
// IBDRootUTXOSetAndBlockMessage end
// RequestIBDBlocksMessage start
message RequestIBDBlocksMessage{
repeated Hash hashes = 1;
}
// RequestIBDBlocksMessage end
// IBDRootNotFoundMessage start
message IBDRootNotFoundMessage{
}
// IBDRootNotFoundMessage end
service P2P {
rpc MessageStream (stream KaspadMessage) returns (stream KaspadMessage) {}
}
@ -455,7 +484,7 @@ message BlockVerboseData{
double difficulty = 11;
repeated string parentHashes = 12;
string selectedParentHash = 13;
repeated string transactionIDs=14;
repeated string transactionIDs = 14;
}
message TransactionVerboseData{

View File

@ -2,7 +2,6 @@ package protowire
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/util/mstime"
"github.com/pkg/errors"
)
@ -15,7 +14,7 @@ func (x *KaspadMessage_Block) fromAppMessage(msgBlock *appmessage.MsgBlock) erro
return x.Block.fromAppMessage(msgBlock)
}
func (x *BlockMessage) toAppMessage() (appmessage.Message, error) {
func (x *BlockMessage) toAppMessage() (*appmessage.MsgBlock, error) {
if len(x.Transactions) > appmessage.MaxTxPerBlock {
return nil, errors.Errorf("too many transactions to fit into a block "+
"[count %d, max %d]", len(x.Transactions), appmessage.MaxTxPerBlock)
@ -31,37 +30,11 @@ func (x *BlockMessage) toAppMessage() (appmessage.Message, error) {
"is %d", len(protoBlockHeader.ParentHashes), appmessage.MaxBlockParents)
}
parentHashes, err := protoHashesToDomain(protoBlockHeader.ParentHashes)
header, err := x.Header.toAppMessage()
if err != nil {
return nil, err
}
hashMerkleRoot, err := protoBlockHeader.HashMerkleRoot.toDomain()
if err != nil {
return nil, err
}
acceptedIDMerkleRoot, err := protoBlockHeader.AcceptedIDMerkleRoot.toDomain()
if err != nil {
return nil, err
}
utxoCommitment, err := protoBlockHeader.UtxoCommitment.toDomain()
if err != nil {
return nil, err
}
header := appmessage.BlockHeader{
Version: protoBlockHeader.Version,
ParentHashes: parentHashes,
HashMerkleRoot: hashMerkleRoot,
AcceptedIDMerkleRoot: acceptedIDMerkleRoot,
UTXOCommitment: utxoCommitment,
Timestamp: mstime.UnixMilliseconds(protoBlockHeader.Timestamp),
Bits: protoBlockHeader.Bits,
Nonce: protoBlockHeader.Nonce,
}
transactions := make([]*appmessage.MsgTx, len(x.Transactions))
for i, protoTx := range x.Transactions {
msgTx, err := protoTx.toAppMessage()
@ -72,7 +45,7 @@ func (x *BlockMessage) toAppMessage() (appmessage.Message, error) {
}
return &appmessage.MsgBlock{
Header: header,
Header: *header,
Transactions: transactions,
}, nil
}
@ -88,17 +61,12 @@ func (x *BlockMessage) fromAppMessage(msgBlock *appmessage.MsgBlock) error {
"is %d", len(msgBlock.Header.ParentHashes), appmessage.MaxBlockParents)
}
header := msgBlock.Header
protoHeader := &BlockHeader{
Version: header.Version,
ParentHashes: domainHashesToProto(header.ParentHashes),
HashMerkleRoot: domainHashToProto(header.HashMerkleRoot),
AcceptedIDMerkleRoot: domainHashToProto(header.AcceptedIDMerkleRoot),
UtxoCommitment: domainHashToProto(header.UTXOCommitment),
Timestamp: header.Timestamp.UnixMilliseconds(),
Bits: header.Bits,
Nonce: header.Nonce,
protoHeader := new(BlockHeaderMessage)
err := protoHeader.fromAppMessage(&msgBlock.Header)
if err != nil {
return err
}
protoTransactions := make([]*TransactionMessage, len(msgBlock.Transactions))
for i, tx := range msgBlock.Transactions {
protoTx := new(TransactionMessage)

View File

@ -2,10 +2,10 @@ package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_DoneIBDBlocks) toAppMessage() (appmessage.Message, error) {
return &appmessage.MsgDoneIBDBlocks{}, nil
func (x *KaspadMessage_DoneHeaders) toAppMessage() (appmessage.Message, error) {
return &appmessage.MsgDoneHeaders{}, nil
}
func (x *KaspadMessage_DoneIBDBlocks) fromAppMessage(_ *appmessage.MsgDoneIBDBlocks) error {
func (x *KaspadMessage_DoneHeaders) fromAppMessage(_ *appmessage.MsgDoneHeaders) error {
return nil
}

View File

@ -0,0 +1,73 @@
package protowire
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/util/mstime"
"github.com/pkg/errors"
)
func (x *KaspadMessage_BlockHeader) toAppMessage() (appmessage.Message, error) {
return x.BlockHeader.toAppMessage()
}
func (x *KaspadMessage_BlockHeader) fromAppMessage(msgBlockHeader *appmessage.MsgBlockHeader) error {
x.BlockHeader = new(BlockHeaderMessage)
return x.BlockHeader.fromAppMessage(msgBlockHeader)
}
func (x *BlockHeaderMessage) toAppMessage() (*appmessage.MsgBlockHeader, error) {
if len(x.ParentHashes) > appmessage.MaxBlockParents {
return nil, errors.Errorf("block header has %d parents, but the maximum allowed amount "+
"is %d", len(x.ParentHashes), appmessage.MaxBlockParents)
}
parentHashes, err := protoHashesToDomain(x.ParentHashes)
if err != nil {
return nil, err
}
hashMerkleRoot, err := x.HashMerkleRoot.toDomain()
if err != nil {
return nil, err
}
acceptedIDMerkleRoot, err := x.AcceptedIDMerkleRoot.toDomain()
if err != nil {
return nil, err
}
utxoCommitment, err := x.UtxoCommitment.toDomain()
if err != nil {
return nil, err
}
return &appmessage.MsgBlockHeader{
Version: x.Version,
ParentHashes: parentHashes,
HashMerkleRoot: hashMerkleRoot,
AcceptedIDMerkleRoot: acceptedIDMerkleRoot,
UTXOCommitment: utxoCommitment,
Timestamp: mstime.UnixMilliseconds(x.Timestamp),
Bits: x.Bits,
Nonce: x.Nonce,
}, nil
}
func (x *BlockHeaderMessage) fromAppMessage(msgBlockHeader *appmessage.MsgBlockHeader) error {
if len(msgBlockHeader.ParentHashes) > appmessage.MaxBlockParents {
return errors.Errorf("block header has %d parents, but the maximum allowed amount "+
"is %d", len(msgBlockHeader.ParentHashes), appmessage.MaxBlockParents)
}
*x = BlockHeaderMessage{
Version: msgBlockHeader.Version,
ParentHashes: domainHashesToProto(msgBlockHeader.ParentHashes),
HashMerkleRoot: domainHashToProto(msgBlockHeader.HashMerkleRoot),
AcceptedIDMerkleRoot: domainHashToProto(msgBlockHeader.AcceptedIDMerkleRoot),
UtxoCommitment: domainHashToProto(msgBlockHeader.UTXOCommitment),
Timestamp: msgBlockHeader.Timestamp.UnixMilliseconds(),
Bits: msgBlockHeader.Bits,
Nonce: msgBlockHeader.Nonce,
}
return nil
}

View File

@ -7,7 +7,7 @@ func (x *KaspadMessage_IbdBlock) toAppMessage() (appmessage.Message, error) {
if err != nil {
return nil, err
}
return &appmessage.MsgIBDBlock{MsgBlock: msgBlock.(*appmessage.MsgBlock)}, nil
return &appmessage.MsgIBDBlock{MsgBlock: msgBlock}, nil
}
func (x *KaspadMessage_IbdBlock) fromAppMessage(msgIBDBlock *appmessage.MsgIBDBlock) error {

View File

@ -0,0 +1,11 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_IbdRootNotFound) toAppMessage() (appmessage.Message, error) {
return &appmessage.MsgIBDRootNotFound{}, nil
}
func (x *KaspadMessage_IbdRootNotFound) fromAppMessage(_ *appmessage.MsgIBDRootNotFound) error {
return nil
}

View File

@ -0,0 +1,19 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_IbdRootUTXOSetAndBlock) toAppMessage() (appmessage.Message, error) {
msgBlock, err := x.IbdRootUTXOSetAndBlock.Block.toAppMessage()
if err != nil {
return nil, err
}
return &appmessage.MsgIBDRootUTXOSetAndBlock{
UTXOSet: x.IbdRootUTXOSetAndBlock.UtxoSet,
Block: msgBlock,
}, nil
}
func (x *KaspadMessage_IbdRootUTXOSetAndBlock) fromAppMessage(msgIBDRootUTXOSetAndBlock *appmessage.MsgIBDRootUTXOSetAndBlock) error {
x.IbdRootUTXOSetAndBlock.UtxoSet = msgIBDRootUTXOSetAndBlock.UTXOSet
return x.IbdRootUTXOSetAndBlock.Block.fromAppMessage(msgIBDRootUTXOSetAndBlock.Block)
}

View File

@ -0,0 +1,28 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_RequestHeaders) toAppMessage() (appmessage.Message, error) {
lowHash, err := x.RequestHeaders.LowHash.toDomain()
if err != nil {
return nil, err
}
highHash, err := x.RequestHeaders.HighHash.toDomain()
if err != nil {
return nil, err
}
return &appmessage.MsgRequestHeaders{
LowHash: lowHash,
HighHash: highHash,
}, nil
}
func (x *KaspadMessage_RequestHeaders) fromAppMessage(msgRequestHeaders *appmessage.MsgRequestHeaders) error {
x.RequestHeaders = &RequestHeadersMessage{
LowHash: domainHashToProto(msgRequestHeaders.LowHash),
HighHash: domainHashToProto(msgRequestHeaders.HighHash),
}
return nil
}

View File

@ -1,28 +1,31 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/pkg/errors"
)
func (x *KaspadMessage_RequestIBDBlocks) toAppMessage() (appmessage.Message, error) {
lowHash, err := x.RequestIBDBlocks.LowHash.toDomain()
if len(x.RequestIBDBlocks.Hashes) > appmessage.MaxRequestIBDBlocksHashes {
return nil, errors.Errorf("too many hashes for message "+
"[count %d, max %d]", len(x.RequestIBDBlocks.Hashes), appmessage.MaxRequestIBDBlocksHashes)
}
hashes, err := protoHashesToDomain(x.RequestIBDBlocks.Hashes)
if err != nil {
return nil, err
}
highHash, err := x.RequestIBDBlocks.HighHash.toDomain()
if err != nil {
return nil, err
}
return &appmessage.MsgRequestIBDBlocks{
LowHash: lowHash,
HighHash: highHash,
}, nil
return &appmessage.MsgRequestRelayBlocks{Hashes: hashes}, nil
}
func (x *KaspadMessage_RequestIBDBlocks) fromAppMessage(msgGetBlocks *appmessage.MsgRequestIBDBlocks) error {
x.RequestIBDBlocks = &RequestIBDBlocksMessage{
LowHash: domainHashToProto(msgGetBlocks.LowHash),
HighHash: domainHashToProto(msgGetBlocks.HighHash),
func (x *KaspadMessage_RequestIBDBlocks) fromAppMessage(msgRequestIBDBlocks *appmessage.MsgRequestIBDBlocks) error {
if len(msgRequestIBDBlocks.Hashes) > appmessage.MaxRequestIBDBlocksHashes {
return errors.Errorf("too many hashes for message "+
"[count %d, max %d]", len(msgRequestIBDBlocks.Hashes), appmessage.MaxRequestIBDBlocksHashes)
}
x.RequestIBDBlocks = &RequestIBDBlocksMessage{
Hashes: domainHashesToProto(msgRequestIBDBlocks.Hashes),
}
return nil
}

View File

@ -0,0 +1,18 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_RequestIBDRootUTXOSetAndBlock) toAppMessage() (appmessage.Message, error) {
ibdRoot, err := x.RequestIBDRootUTXOSetAndBlock.IbdRoot.toDomain()
if err != nil {
return nil, err
}
return &appmessage.MsgRequestIBDRootUTXOSetAndBlock{IBDRoot: ibdRoot}, nil
}
func (x *KaspadMessage_RequestIBDRootUTXOSetAndBlock) fromAppMessage(
msgRequestIBDRootUTXOSetAndBlock *appmessage.MsgRequestIBDRootUTXOSetAndBlock) error {
x.RequestIBDRootUTXOSetAndBlock.IbdRoot = domainHashToProto(msgRequestIBDRootUTXOSetAndBlock.IBDRoot)
return nil
}

View File

@ -0,0 +1,11 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_RequestNextHeaders) toAppMessage() (appmessage.Message, error) {
return &appmessage.MsgRequestNextHeaders{}, nil
}
func (x *KaspadMessage_RequestNextHeaders) fromAppMessage(_ *appmessage.MsgRequestNextHeaders) error {
return nil
}

View File

@ -1,11 +0,0 @@
package protowire
import "github.com/kaspanet/kaspad/app/appmessage"
func (x *KaspadMessage_RequestNextIBDBlocks) toAppMessage() (appmessage.Message, error) {
return &appmessage.MsgRequestNextIBDBlocks{}, nil
}
func (x *KaspadMessage_RequestNextIBDBlocks) fromAppMessage(_ *appmessage.MsgRequestNextIBDBlocks) error {
return nil
}

View File

@ -6,9 +6,9 @@ import (
)
func (x *KaspadMessage_RequestRelayBlocks) toAppMessage() (appmessage.Message, error) {
if len(x.RequestRelayBlocks.Hashes) > appmessage.MsgRequestRelayBlocksHashes {
if len(x.RequestRelayBlocks.Hashes) > appmessage.MaxRequestRelayBlocksHashes {
return nil, errors.Errorf("too many hashes for message "+
"[count %d, max %d]", len(x.RequestRelayBlocks.Hashes), appmessage.MsgRequestRelayBlocksHashes)
"[count %d, max %d]", len(x.RequestRelayBlocks.Hashes), appmessage.MaxRequestRelayBlocksHashes)
}
hashes, err := protoHashesToDomain(x.RequestRelayBlocks.Hashes)
if err != nil {
@ -18,9 +18,9 @@ func (x *KaspadMessage_RequestRelayBlocks) toAppMessage() (appmessage.Message, e
}
func (x *KaspadMessage_RequestRelayBlocks) fromAppMessage(msgGetRelayBlocks *appmessage.MsgRequestRelayBlocks) error {
if len(msgGetRelayBlocks.Hashes) > appmessage.MsgRequestRelayBlocksHashes {
if len(msgGetRelayBlocks.Hashes) > appmessage.MaxRequestRelayBlocksHashes {
return errors.Errorf("too many hashes for message "+
"[count %d, max %d]", len(msgGetRelayBlocks.Hashes), appmessage.MsgRequestRelayBlocksHashes)
"[count %d, max %d]", len(msgGetRelayBlocks.Hashes), appmessage.MaxRequestRelayBlocksHashes)
}
x.RequestRelayBlocks = &RequestRelayBlocksMessage{

View File

@ -22,7 +22,7 @@ func (x *KaspadMessage_GetBlockTemplateResponse) toAppMessage() (appmessage.Mess
if err != nil {
return nil, err
}
return appmessage.NewGetBlockTemplateResponseMessage(msgBlock.(*appmessage.MsgBlock)), nil
return appmessage.NewGetBlockTemplateResponseMessage(msgBlock), nil
}
func (x *KaspadMessage_GetBlockTemplateResponse) fromAppMessage(message *appmessage.GetBlockTemplateResponseMessage) error {

View File

@ -38,7 +38,7 @@ func (x *KaspadMessage_BlockAddedNotification) toAppMessage() (appmessage.Messag
return nil, err
}
return &appmessage.BlockAddedNotificationMessage{
Block: block.(*appmessage.MsgBlock),
Block: block,
}, nil
}

View File

@ -9,7 +9,7 @@ func (x *KaspadMessage_SubmitBlockRequest) toAppMessage() (appmessage.Message, e
}
return &appmessage.SubmitBlockRequestMessage{
Block: blockAppMessage.(*appmessage.MsgBlock),
Block: blockAppMessage,
}, nil
}

View File

@ -93,15 +93,15 @@ func toP2PPayload(message appmessage.Message) (isKaspadMessage_Payload, error) {
return nil, err
}
return payload, nil
case *appmessage.MsgRequestNextIBDBlocks:
payload := new(KaspadMessage_RequestNextIBDBlocks)
case *appmessage.MsgRequestNextHeaders:
payload := new(KaspadMessage_RequestNextHeaders)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
case *appmessage.MsgDoneIBDBlocks:
payload := new(KaspadMessage_DoneIBDBlocks)
case *appmessage.MsgDoneHeaders:
payload := new(KaspadMessage_DoneHeaders)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
@ -205,6 +205,47 @@ func toP2PPayload(message appmessage.Message) (isKaspadMessage_Payload, error) {
return nil, err
}
return payload, nil
case *appmessage.MsgBlockHeader:
payload := new(KaspadMessage_BlockHeader)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
case *appmessage.MsgRequestIBDRootUTXOSetAndBlock:
payload := new(KaspadMessage_RequestIBDRootUTXOSetAndBlock)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
case *appmessage.MsgIBDRootUTXOSetAndBlock:
payload := new(KaspadMessage_IbdRootUTXOSetAndBlock)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
case *appmessage.MsgRequestHeaders:
payload := new(KaspadMessage_RequestHeaders)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
case *appmessage.MsgIBDRootNotFound:
payload := new(KaspadMessage_IbdRootNotFound)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
default:
return nil, nil
}