diff --git a/app/appmessage/error.go b/app/appmessage/error.go index e6d13f0743..1ec7e1fef5 100644 --- a/app/appmessage/error.go +++ b/app/appmessage/error.go @@ -38,6 +38,10 @@ type RPCError struct { Message string } +func (err RPCError) Error() string { + return err.Message +} + // RPCErrorf formats according to a format specifier and returns the string // as an RPCError. func RPCErrorf(format string, args ...interface{}) *RPCError { diff --git a/app/appmessage/message.go b/app/appmessage/message.go index 0e34d0f8b5..064fcc7eb8 100644 --- a/app/appmessage/message.go +++ b/app/appmessage/message.go @@ -150,6 +150,8 @@ const ( CmdNotifyVirtualDaaScoreChangedRequestMessage CmdNotifyVirtualDaaScoreChangedResponseMessage CmdVirtualDaaScoreChangedNotificationMessage + CmdGetBalancesByAddressesRequestMessage + CmdGetBalancesByAddressesResponseMessage ) // ProtocolMessageCommandToString maps all MessageCommands to their string representation @@ -274,6 +276,8 @@ var RPCMessageCommandToString = map[MessageCommand]string{ CmdNotifyVirtualDaaScoreChangedRequestMessage: "NotifyVirtualDaaScoreChangedRequest", CmdNotifyVirtualDaaScoreChangedResponseMessage: "NotifyVirtualDaaScoreChangedResponse", CmdVirtualDaaScoreChangedNotificationMessage: "VirtualDaaScoreChangedNotification", + CmdGetBalancesByAddressesRequestMessage: "GetBalancesByAddressesRequest", + CmdGetBalancesByAddressesResponseMessage: "GetBalancesByAddressesResponse", } // Message is an interface that describes a kaspa message. A type that diff --git a/app/appmessage/rpc_get_balances_by_addresses.go b/app/appmessage/rpc_get_balances_by_addresses.go new file mode 100644 index 0000000000..7a58b56bb8 --- /dev/null +++ b/app/appmessage/rpc_get_balances_by_addresses.go @@ -0,0 +1,47 @@ +package appmessage + +// GetBalancesByAddressesRequestMessage is an appmessage corresponding to +// its respective RPC message +type GetBalancesByAddressesRequestMessage struct { + baseMessage + Addresses []string +} + +// Command returns the protocol command string for the message +func (msg *GetBalancesByAddressesRequestMessage) Command() MessageCommand { + return CmdGetBalancesByAddressesRequestMessage +} + +// NewGetBalancesByAddressesRequest returns a instance of the message +func NewGetBalancesByAddressesRequest(addresses []string) *GetBalancesByAddressesRequestMessage { + return &GetBalancesByAddressesRequestMessage{ + Addresses: addresses, + } +} + +// BalancesByAddressesEntry represents the balance of some address +type BalancesByAddressesEntry struct { + Address string + Balance uint64 +} + +// GetBalancesByAddressesResponseMessage is an appmessage corresponding to +// its respective RPC message +type GetBalancesByAddressesResponseMessage struct { + baseMessage + Entries []*BalancesByAddressesEntry + + Error *RPCError +} + +// Command returns the protocol command string for the message +func (msg *GetBalancesByAddressesResponseMessage) Command() MessageCommand { + return CmdGetBalancesByAddressesResponseMessage +} + +// NewGetBalancesByAddressesResponse returns an instance of the message +func NewGetBalancesByAddressesResponse(entries []*BalancesByAddressesEntry) *GetBalancesByAddressesResponseMessage { + return &GetBalancesByAddressesResponseMessage{ + Entries: entries, + } +} diff --git a/app/protocol/flows/handshake/receiveversion.go b/app/protocol/flows/handshake/receiveversion.go index 8e1772cc3d..029266a775 100644 --- a/app/protocol/flows/handshake/receiveversion.go +++ b/app/protocol/flows/handshake/receiveversion.go @@ -18,7 +18,7 @@ var ( // minAcceptableProtocolVersion is the lowest protocol version that a // connected peer may support. - minAcceptableProtocolVersion = uint32(3) + minAcceptableProtocolVersion = uint32(4) maxAcceptableProtocolVersion = uint32(4) ) diff --git a/app/protocol/flows/v3/blockrelay/block_locator.go b/app/protocol/flows/v3/blockrelay/block_locator.go deleted file mode 100644 index 70b18e6eaf..0000000000 --- a/app/protocol/flows/v3/blockrelay/block_locator.go +++ /dev/null @@ -1,33 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/common" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" -) - -func (flow *handleRelayInvsFlow) sendGetBlockLocator(highHash *externalapi.DomainHash, limit uint32) error { - msgGetBlockLocator := appmessage.NewMsgRequestBlockLocator(highHash, limit) - return flow.outgoingRoute.Enqueue(msgGetBlockLocator) -} - -func (flow *handleRelayInvsFlow) receiveBlockLocator() (blockLocatorHashes []*externalapi.DomainHash, err error) { - for { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, err - } - - switch message := message.(type) { - case *appmessage.MsgInvRelayBlock: - flow.invsQueue = append(flow.invsQueue, message) - case *appmessage.MsgBlockLocator: - return message.BlockLocatorHashes, nil - default: - return nil, - protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdBlockLocator, message.Command()) - } - } -} diff --git a/app/protocol/flows/v3/blockrelay/handle_ibd_block_locator.go b/app/protocol/flows/v3/blockrelay/handle_ibd_block_locator.go deleted file mode 100644 index 4e9cd0bc45..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_ibd_block_locator.go +++ /dev/null @@ -1,86 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -// HandleIBDBlockLocatorContext is the interface for the context needed for the HandleIBDBlockLocator flow. -type HandleIBDBlockLocatorContext interface { - Domain() domain.Domain -} - -// HandleIBDBlockLocator listens to appmessage.MsgIBDBlockLocator messages and sends -// the highest known block that's in the selected parent chain of `targetHash` to the -// requesting peer. -func HandleIBDBlockLocator(context HandleIBDBlockLocatorContext, incomingRoute *router.Route, - outgoingRoute *router.Route, peer *peer.Peer) error { - - for { - message, err := incomingRoute.Dequeue() - if err != nil { - return err - } - ibdBlockLocatorMessage := message.(*appmessage.MsgIBDBlockLocator) - - targetHash := ibdBlockLocatorMessage.TargetHash - log.Debugf("Received IBDBlockLocator from %s with targetHash %s", peer, targetHash) - - blockInfo, err := context.Domain().Consensus().GetBlockInfo(targetHash) - if err != nil { - return err - } - if !blockInfo.Exists { - return protocolerrors.Errorf(true, "received IBDBlockLocator "+ - "with an unknown targetHash %s", targetHash) - } - - foundHighestHashInTheSelectedParentChainOfTargetHash := false - for _, blockLocatorHash := range ibdBlockLocatorMessage.BlockLocatorHashes { - blockInfo, err := context.Domain().Consensus().GetBlockInfo(blockLocatorHash) - if err != nil { - return err - } - - // The IBD block locator is checking only existing blocks with bodies. - if !blockInfo.Exists || blockInfo.BlockStatus == externalapi.StatusHeaderOnly { - continue - } - - isBlockLocatorHashInSelectedParentChainOfHighHash, err := - context.Domain().Consensus().IsInSelectedParentChainOf(blockLocatorHash, targetHash) - if err != nil { - return err - } - if !isBlockLocatorHashInSelectedParentChainOfHighHash { - continue - } - - foundHighestHashInTheSelectedParentChainOfTargetHash = true - log.Debugf("Found a known hash %s amongst peer %s's "+ - "blockLocator that's in the selected parent chain of targetHash %s", blockLocatorHash, peer, targetHash) - - ibdBlockLocatorHighestHashMessage := appmessage.NewMsgIBDBlockLocatorHighestHash(blockLocatorHash) - err = outgoingRoute.Enqueue(ibdBlockLocatorHighestHashMessage) - if err != nil { - return err - } - break - } - - if !foundHighestHashInTheSelectedParentChainOfTargetHash { - log.Warnf("no hash was found in the blockLocator "+ - "that was in the selected parent chain of targetHash %s", targetHash) - - ibdBlockLocatorHighestHashNotFoundMessage := appmessage.NewMsgIBDBlockLocatorHighestHashNotFound() - err = outgoingRoute.Enqueue(ibdBlockLocatorHighestHashNotFoundMessage) - if err != nil { - return err - } - } - } -} diff --git a/app/protocol/flows/v3/blockrelay/handle_ibd_block_requests.go b/app/protocol/flows/v3/blockrelay/handle_ibd_block_requests.go deleted file mode 100644 index c7ac18cdce..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_ibd_block_requests.go +++ /dev/null @@ -1,54 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "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) - log.Debugf("Got request for %d ibd blocks", len(msgRequestIBDBlocks.Hashes)) - for i, 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 || blockInfo.BlockStatus == externalapi.StatusHeaderOnly { - 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 - - blockMessage := appmessage.DomainBlockToMsgBlock(block) - ibdBlockMessage := appmessage.NewMsgIBDBlock(blockMessage) - err = outgoingRoute.Enqueue(ibdBlockMessage) - if err != nil { - return err - } - log.Debugf("sent %d out of %d", i+1, len(msgRequestIBDBlocks.Hashes)) - } - } -} diff --git a/app/protocol/flows/v3/blockrelay/handle_pruning_point_and_its_anticone_requests.go b/app/protocol/flows/v3/blockrelay/handle_pruning_point_and_its_anticone_requests.go deleted file mode 100644 index db07653e2d..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_pruning_point_and_its_anticone_requests.go +++ /dev/null @@ -1,95 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" - "runtime" - "sync/atomic" -) - -// PruningPointAndItsAnticoneRequestsContext is the interface for the context needed for the HandlePruningPointAndItsAnticoneRequests flow. -type PruningPointAndItsAnticoneRequestsContext interface { - Domain() domain.Domain -} - -var isBusy uint32 - -// HandlePruningPointAndItsAnticoneRequests listens to appmessage.MsgRequestPruningPointAndItsAnticone messages and sends -// the pruning point and its anticone to the requesting peer. -func HandlePruningPointAndItsAnticoneRequests(context PruningPointAndItsAnticoneRequestsContext, incomingRoute *router.Route, - outgoingRoute *router.Route, peer *peerpkg.Peer) error { - - for { - err := func() error { - _, err := incomingRoute.Dequeue() - if err != nil { - return err - } - - if !atomic.CompareAndSwapUint32(&isBusy, 0, 1) { - return protocolerrors.Errorf(false, "node is busy with other pruning point anticone requests") - } - defer atomic.StoreUint32(&isBusy, 0) - - log.Debugf("Got request for pruning point and its anticone from %s", peer) - - pruningPointHeaders, err := context.Domain().Consensus().PruningPointHeaders() - if err != nil { - return err - } - - msgPruningPointHeaders := make([]*appmessage.MsgBlockHeader, len(pruningPointHeaders)) - for i, header := range pruningPointHeaders { - msgPruningPointHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(header) - } - - err = outgoingRoute.Enqueue(appmessage.NewMsgPruningPoints(msgPruningPointHeaders)) - if err != nil { - return err - } - - pointAndItsAnticone, err := context.Domain().Consensus().PruningPointAndItsAnticone() - if err != nil { - return err - } - - for _, blockHash := range pointAndItsAnticone { - err := sendBlockWithTrustedData(context, outgoingRoute, blockHash) - if err != nil { - return err - } - } - - err = outgoingRoute.Enqueue(appmessage.NewMsgDoneBlocksWithTrustedData()) - if err != nil { - return err - } - - log.Debugf("Sent pruning point and its anticone to %s", peer) - return nil - }() - if err != nil { - return err - } - } -} - -func sendBlockWithTrustedData(context PruningPointAndItsAnticoneRequestsContext, outgoingRoute *router.Route, blockHash *externalapi.DomainHash) error { - blockWithTrustedData, err := context.Domain().Consensus().BlockWithTrustedData(blockHash) - if err != nil { - return err - } - - err = outgoingRoute.Enqueue(appmessage.DomainBlockWithTrustedDataToBlockWithTrustedData(blockWithTrustedData)) - if err != nil { - return err - } - - runtime.GC() - - return nil -} diff --git a/app/protocol/flows/v3/blockrelay/handle_pruning_point_proof_requests.go b/app/protocol/flows/v3/blockrelay/handle_pruning_point_proof_requests.go deleted file mode 100644 index 8391a402ab..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_pruning_point_proof_requests.go +++ /dev/null @@ -1,40 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -// PruningPointProofRequestsContext is the interface for the context needed for the HandlePruningPointProofRequests flow. -type PruningPointProofRequestsContext interface { - Domain() domain.Domain -} - -// HandlePruningPointProofRequests listens to appmessage.MsgRequestPruningPointProof messages and sends -// the pruning point proof to the requesting peer. -func HandlePruningPointProofRequests(context PruningPointProofRequestsContext, incomingRoute *router.Route, - outgoingRoute *router.Route, peer *peerpkg.Peer) error { - - for { - _, err := incomingRoute.Dequeue() - if err != nil { - return err - } - - log.Debugf("Got request for pruning point proof from %s", peer) - - pruningPointProof, err := context.Domain().Consensus().BuildPruningPointProof() - if err != nil { - return err - } - pruningPointProofMessage := appmessage.DomainPruningPointProofToMsgPruningPointProof(pruningPointProof) - err = outgoingRoute.Enqueue(pruningPointProofMessage) - if err != nil { - return err - } - - log.Debugf("Sent pruning point proof to %s", peer) - } -} diff --git a/app/protocol/flows/v3/blockrelay/handle_relay_block_requests.go b/app/protocol/flows/v3/blockrelay/handle_relay_block_requests.go deleted file mode 100644 index db4e545583..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_relay_block_requests.go +++ /dev/null @@ -1,53 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" - "github.com/pkg/errors" -) - -// RelayBlockRequestsContext is the interface for the context needed for the HandleRelayBlockRequests flow. -type RelayBlockRequestsContext interface { - Domain() domain.Domain -} - -// HandleRelayBlockRequests listens to appmessage.MsgRequestRelayBlocks messages and sends -// their corresponding blocks to the requesting peer. -func HandleRelayBlockRequests(context RelayBlockRequestsContext, incomingRoute *router.Route, - outgoingRoute *router.Route, peer *peerpkg.Peer) error { - - for { - message, err := incomingRoute.Dequeue() - if err != nil { - return err - } - getRelayBlocksMessage := message.(*appmessage.MsgRequestRelayBlocks) - log.Debugf("Got request for relay blocks with hashes %s", getRelayBlocksMessage.Hashes) - for _, hash := range getRelayBlocksMessage.Hashes { - // Fetch the block from the database. - blockInfo, err := context.Domain().Consensus().GetBlockInfo(hash) - if err != nil { - return err - } - if !blockInfo.Exists || blockInfo.BlockStatus == externalapi.StatusHeaderOnly { - 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 - } - log.Debugf("Relayed block with hash %s", hash) - } - } -} diff --git a/app/protocol/flows/v3/blockrelay/handle_relay_invs.go b/app/protocol/flows/v3/blockrelay/handle_relay_invs.go deleted file mode 100644 index 227416f9ef..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_relay_invs.go +++ /dev/null @@ -1,382 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/common" - "github.com/kaspanet/kaspad/app/protocol/flowcontext" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "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/kaspanet/kaspad/infrastructure/config" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" - "github.com/pkg/errors" -) - -// orphanResolutionRange is the maximum amount of blockLocator hashes -// to search for known blocks. See isBlockInOrphanResolutionRange for -// further details -var orphanResolutionRange uint32 = 5 - -// RelayInvsContext is the interface for the context needed for the HandleRelayInvs flow. -type RelayInvsContext interface { - Domain() domain.Domain - Config() *config.Config - OnNewBlock(block *externalapi.DomainBlock, virtualChangeSet *externalapi.VirtualChangeSet) error - OnVirtualChange(virtualChangeSet *externalapi.VirtualChangeSet) error - OnPruningPointUTXOSetOverride() error - SharedRequestedBlocks() *flowcontext.SharedRequestedBlocks - Broadcast(message appmessage.Message) error - AddOrphan(orphanBlock *externalapi.DomainBlock) - GetOrphanRoots(orphanHash *externalapi.DomainHash) ([]*externalapi.DomainHash, bool, error) - IsOrphan(blockHash *externalapi.DomainHash) bool - IsIBDRunning() bool - IsRecoverableError(err error) bool -} - -type handleRelayInvsFlow struct { - RelayInvsContext - incomingRoute, outgoingRoute *router.Route - peer *peerpkg.Peer - invsQueue []*appmessage.MsgInvRelayBlock -} - -// HandleRelayInvs listens to appmessage.MsgInvRelayBlock messages, requests their corresponding blocks if they -// are missing, adds them to the DAG and propagates them to the rest of the network. -func HandleRelayInvs(context RelayInvsContext, incomingRoute *router.Route, outgoingRoute *router.Route, - peer *peerpkg.Peer) error { - - flow := &handleRelayInvsFlow{ - RelayInvsContext: context, - incomingRoute: incomingRoute, - outgoingRoute: outgoingRoute, - peer: peer, - invsQueue: make([]*appmessage.MsgInvRelayBlock, 0), - } - err := flow.start() - // Currently, HandleRelayInvs flow is the only place where IBD is triggered, so the channel can be closed now - close(peer.IBDRequestChannel()) - return err -} - -func (flow *handleRelayInvsFlow) start() error { - for { - log.Debugf("Waiting for inv") - inv, err := flow.readInv() - if err != nil { - return err - } - - log.Debugf("Got relay inv for block %s", inv.Hash) - - blockInfo, err := flow.Domain().Consensus().GetBlockInfo(inv.Hash) - if err != nil { - return err - } - if blockInfo.Exists && blockInfo.BlockStatus != externalapi.StatusHeaderOnly { - if blockInfo.BlockStatus == externalapi.StatusInvalid { - return protocolerrors.Errorf(true, "sent inv of an invalid block %s", - inv.Hash) - } - log.Debugf("Block %s already exists. continuing...", inv.Hash) - continue - } - - isGenesisVirtualSelectedParent, err := flow.isGenesisVirtualSelectedParent() - if err != nil { - return err - } - - if flow.IsOrphan(inv.Hash) { - if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced && isGenesisVirtualSelectedParent { - log.Infof("Cannot process orphan %s for a node with only the genesis block. The node needs to IBD "+ - "to the recent pruning point before normal operation can resume.", inv.Hash) - continue - } - - log.Debugf("Block %s is a known orphan. Requesting its missing ancestors", inv.Hash) - err := flow.AddOrphanRootsToQueue(inv.Hash) - if err != nil { - return err - } - continue - } - - // Block relay is disabled during IBD - if flow.IsIBDRunning() { - log.Debugf("Got block %s while in IBD. continuing...", inv.Hash) - continue - } - - log.Debugf("Requesting block %s", inv.Hash) - block, exists, err := flow.requestBlock(inv.Hash) - if err != nil { - return err - } - if exists { - log.Debugf("Aborting requesting block %s because it already exists", inv.Hash) - continue - } - - err = flow.banIfBlockIsHeaderOnly(block) - if err != nil { - return err - } - - if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced && !flow.Config().Devnet && flow.isChildOfGenesis(block) { - log.Infof("Cannot process %s because it's a direct child of genesis.", consensushashing.BlockHash(block)) - continue - } - - log.Debugf("Processing block %s", inv.Hash) - missingParents, virtualChangeSet, err := flow.processBlock(block) - if err != nil { - if errors.Is(err, ruleerrors.ErrPrunedBlock) { - log.Infof("Ignoring pruned block %s", inv.Hash) - continue - } - - if errors.Is(err, ruleerrors.ErrDuplicateBlock) { - log.Infof("Ignoring duplicate block %s", inv.Hash) - continue - } - return err - } - if len(missingParents) > 0 { - log.Debugf("Block %s is orphan and has missing parents: %s", inv.Hash, missingParents) - err := flow.processOrphan(block) - if err != nil { - return err - } - continue - } - - log.Debugf("Relaying block %s", inv.Hash) - err = flow.relayBlock(block) - if err != nil { - return err - } - log.Infof("Accepted block %s via relay", inv.Hash) - err = flow.OnNewBlock(block, virtualChangeSet) - if err != nil { - return err - } - } -} - -func (flow *handleRelayInvsFlow) banIfBlockIsHeaderOnly(block *externalapi.DomainBlock) error { - if len(block.Transactions) == 0 { - return protocolerrors.Errorf(true, "sent header of %s block where expected block with body", - consensushashing.BlockHash(block)) - } - - return nil -} - -func (flow *handleRelayInvsFlow) readInv() (*appmessage.MsgInvRelayBlock, error) { - if len(flow.invsQueue) > 0 { - var inv *appmessage.MsgInvRelayBlock - inv, flow.invsQueue = flow.invsQueue[0], flow.invsQueue[1:] - return inv, nil - } - - msg, err := flow.incomingRoute.Dequeue() - if err != nil { - return nil, err - } - - inv, ok := msg.(*appmessage.MsgInvRelayBlock) - if !ok { - return nil, protocolerrors.Errorf(true, "unexpected %s message in the block relay handleRelayInvsFlow while "+ - "expecting an inv message", msg.Command()) - } - return inv, nil -} - -func (flow *handleRelayInvsFlow) requestBlock(requestHash *externalapi.DomainHash) (*externalapi.DomainBlock, bool, error) { - exists := flow.SharedRequestedBlocks().AddIfNotExists(requestHash) - if exists { - return nil, true, nil - } - - // In case the function returns earlier than expected, we want to make sure flow.SharedRequestedBlocks() is - // clean from any pending blocks. - defer flow.SharedRequestedBlocks().Remove(requestHash) - - getRelayBlocksMsg := appmessage.NewMsgRequestRelayBlocks([]*externalapi.DomainHash{requestHash}) - err := flow.outgoingRoute.Enqueue(getRelayBlocksMsg) - if err != nil { - return nil, false, err - } - - msgBlock, err := flow.readMsgBlock() - if err != nil { - return nil, false, err - } - - block := appmessage.MsgBlockToDomainBlock(msgBlock) - blockHash := consensushashing.BlockHash(block) - if !blockHash.Equal(requestHash) { - return nil, false, protocolerrors.Errorf(true, "got unrequested block %s", blockHash) - } - - return block, false, nil -} - -// readMsgBlock returns the next msgBlock in msgChan, and populates invsQueue with any inv messages that meanwhile arrive. -// -// Note: this function assumes msgChan can contain only appmessage.MsgInvRelayBlock and appmessage.MsgBlock messages. -func (flow *handleRelayInvsFlow) readMsgBlock() (msgBlock *appmessage.MsgBlock, err error) { - for { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, err - } - - switch message := message.(type) { - case *appmessage.MsgInvRelayBlock: - flow.invsQueue = append(flow.invsQueue, message) - case *appmessage.MsgBlock: - return message, nil - default: - return nil, errors.Errorf("unexpected message %s", message.Command()) - } - } -} - -func (flow *handleRelayInvsFlow) processBlock(block *externalapi.DomainBlock) ([]*externalapi.DomainHash, *externalapi.VirtualChangeSet, error) { - blockHash := consensushashing.BlockHash(block) - virtualChangeSet, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, true) - if err != nil { - if !errors.As(err, &ruleerrors.RuleError{}) { - return nil, nil, errors.Wrapf(err, "failed to process block %s", blockHash) - } - - missingParentsError := &ruleerrors.ErrMissingParents{} - if errors.As(err, missingParentsError) { - return missingParentsError.MissingParentHashes, nil, nil - } - log.Warnf("Rejected block %s from %s: %s", blockHash, flow.peer, err) - return nil, nil, protocolerrors.Wrapf(true, err, "got invalid block %s from relay", blockHash) - } - return nil, virtualChangeSet, nil -} - -func (flow *handleRelayInvsFlow) relayBlock(block *externalapi.DomainBlock) error { - blockHash := consensushashing.BlockHash(block) - return flow.Broadcast(appmessage.NewMsgInvBlock(blockHash)) -} - -func (flow *handleRelayInvsFlow) processOrphan(block *externalapi.DomainBlock) error { - blockHash := consensushashing.BlockHash(block) - - // Return if the block has been orphaned from elsewhere already - if flow.IsOrphan(blockHash) { - log.Debugf("Skipping orphan processing for block %s because it is already an orphan", blockHash) - return nil - } - - // Add the block to the orphan set if it's within orphan resolution range - isBlockInOrphanResolutionRange, err := flow.isBlockInOrphanResolutionRange(blockHash) - if err != nil { - return err - } - if isBlockInOrphanResolutionRange { - if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced { - isGenesisVirtualSelectedParent, err := flow.isGenesisVirtualSelectedParent() - if err != nil { - return err - } - - if isGenesisVirtualSelectedParent { - log.Infof("Cannot process orphan %s for a node with only the genesis block. The node needs to IBD "+ - "to the recent pruning point before normal operation can resume.", blockHash) - return nil - } - } - - log.Debugf("Block %s is within orphan resolution range. "+ - "Adding it to the orphan set", blockHash) - flow.AddOrphan(block) - log.Debugf("Requesting block %s missing ancestors", blockHash) - return flow.AddOrphanRootsToQueue(blockHash) - } - - // Start IBD unless we already are in IBD - log.Debugf("Block %s is out of orphan resolution range. "+ - "Attempting to start IBD against it.", blockHash) - - // Send the block to IBD flow via the IBDRequestChannel. - // Note that this is a non-blocking send, since if IBD is already running, there is no need to trigger it - select { - case flow.peer.IBDRequestChannel() <- block: - default: - } - return nil -} - -func (flow *handleRelayInvsFlow) isGenesisVirtualSelectedParent() (bool, error) { - virtualSelectedParent, err := flow.Domain().Consensus().GetVirtualSelectedParent() - if err != nil { - return false, err - } - - return virtualSelectedParent.Equal(flow.Config().NetParams().GenesisHash), nil -} - -func (flow *handleRelayInvsFlow) isChildOfGenesis(block *externalapi.DomainBlock) bool { - parents := block.Header.DirectParents() - return len(parents) == 1 && parents[0].Equal(flow.Config().NetParams().GenesisHash) -} - -// isBlockInOrphanResolutionRange finds out whether the given blockHash should be -// retrieved via the unorphaning mechanism or via IBD. This method sends a -// getBlockLocator request to the peer with a limit of orphanResolutionRange. -// In the response, if we know none of the hashes, we should retrieve the given -// blockHash via IBD. Otherwise, via unorphaning. -func (flow *handleRelayInvsFlow) isBlockInOrphanResolutionRange(blockHash *externalapi.DomainHash) (bool, error) { - err := flow.sendGetBlockLocator(blockHash, orphanResolutionRange) - if err != nil { - return false, err - } - - blockLocatorHashes, err := flow.receiveBlockLocator() - if err != nil { - return false, err - } - for _, blockLocatorHash := range blockLocatorHashes { - blockInfo, err := flow.Domain().Consensus().GetBlockInfo(blockLocatorHash) - if err != nil { - return false, err - } - if blockInfo.Exists && blockInfo.BlockStatus != externalapi.StatusHeaderOnly { - return true, nil - } - } - return false, nil -} - -func (flow *handleRelayInvsFlow) AddOrphanRootsToQueue(orphan *externalapi.DomainHash) error { - orphanRoots, orphanExists, err := flow.GetOrphanRoots(orphan) - if err != nil { - return err - } - - if !orphanExists { - log.Infof("Orphan block %s was missing from the orphan pool while requesting for its roots. This "+ - "probably happened because it was randomly evicted immediately after it was added.", orphan) - } - - log.Infof("Block %s has %d missing ancestors. Adding them to the invs queue...", orphan, len(orphanRoots)) - - invMessages := make([]*appmessage.MsgInvRelayBlock, len(orphanRoots)) - for i, root := range orphanRoots { - log.Debugf("Adding block %s missing ancestor %s to the invs queue", orphan, root) - invMessages[i] = appmessage.NewMsgInvBlock(root) - } - - flow.invsQueue = append(invMessages, flow.invsQueue...) - return nil -} diff --git a/app/protocol/flows/v3/blockrelay/handle_request_block_locator.go b/app/protocol/flows/v3/blockrelay/handle_request_block_locator.go deleted file mode 100644 index 027f869961..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_request_block_locator.go +++ /dev/null @@ -1,75 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -// RequestBlockLocatorContext is the interface for the context needed for the HandleRequestBlockLocator flow. -type RequestBlockLocatorContext interface { - Domain() domain.Domain -} - -type handleRequestBlockLocatorFlow struct { - RequestBlockLocatorContext - incomingRoute, outgoingRoute *router.Route -} - -// HandleRequestBlockLocator handles getBlockLocator messages -func HandleRequestBlockLocator(context RequestBlockLocatorContext, incomingRoute *router.Route, - outgoingRoute *router.Route) error { - - flow := &handleRequestBlockLocatorFlow{ - RequestBlockLocatorContext: context, - incomingRoute: incomingRoute, - outgoingRoute: outgoingRoute, - } - return flow.start() -} - -func (flow *handleRequestBlockLocatorFlow) start() error { - for { - highHash, limit, err := flow.receiveGetBlockLocator() - if err != nil { - return err - } - log.Debugf("Received getBlockLocator with highHash: %s, limit: %d", highHash, limit) - - locator, err := flow.Domain().Consensus().CreateBlockLocatorFromPruningPoint(highHash, limit) - if err != nil || len(locator) == 0 { - if err != nil { - log.Debugf("Received error from CreateBlockLocatorFromPruningPoint: %s", err) - } - return protocolerrors.Errorf(true, "couldn't build a block "+ - "locator between the pruning point and %s", highHash) - } - - err = flow.sendBlockLocator(locator) - if err != nil { - return err - } - } -} - -func (flow *handleRequestBlockLocatorFlow) receiveGetBlockLocator() (highHash *externalapi.DomainHash, limit uint32, err error) { - - message, err := flow.incomingRoute.Dequeue() - if err != nil { - return nil, 0, err - } - msgGetBlockLocator := message.(*appmessage.MsgRequestBlockLocator) - - return msgGetBlockLocator.HighHash, msgGetBlockLocator.Limit, nil -} - -func (flow *handleRequestBlockLocatorFlow) sendBlockLocator(locator externalapi.BlockLocator) error { - msgBlockLocator := appmessage.NewMsgBlockLocator(locator) - err := flow.outgoingRoute.Enqueue(msgBlockLocator) - if err != nil { - return err - } - return nil -} diff --git a/app/protocol/flows/v3/blockrelay/handle_request_headers.go b/app/protocol/flows/v3/blockrelay/handle_request_headers.go deleted file mode 100644 index 72576cf66c..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_request_headers.go +++ /dev/null @@ -1,105 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -const ibdBatchSize = router.DefaultMaxMessages - -// RequestHeadersContext is the interface for the context needed for the HandleRequestHeaders flow. -type RequestHeadersContext interface { - Domain() domain.Domain -} - -type handleRequestHeadersFlow struct { - RequestHeadersContext - incomingRoute, outgoingRoute *router.Route - peer *peer.Peer -} - -// HandleRequestHeaders handles RequestHeaders messages -func HandleRequestHeaders(context RequestHeadersContext, incomingRoute *router.Route, - outgoingRoute *router.Route, peer *peer.Peer) error { - - flow := &handleRequestHeadersFlow{ - RequestHeadersContext: context, - incomingRoute: incomingRoute, - outgoingRoute: outgoingRoute, - peer: peer, - } - return flow.start() -} - -func (flow *handleRequestHeadersFlow) start() error { - for { - lowHash, highHash, err := receiveRequestHeaders(flow.incomingRoute) - if err != nil { - return err - } - log.Debugf("Recieved requestHeaders with lowHash: %s, highHash: %s", lowHash, highHash) - - for !lowHash.Equal(highHash) { - log.Debugf("Getting block headers between %s and %s to %s", lowHash, highHash, flow.peer) - - // GetHashesBetween is a relatively heavy operation so we limit it - // in order to avoid locking the consensus for too long - // maxBlocks MUST be >= MergeSetSizeLimit + 1 - const maxBlocks = 1 << 10 - blockHashes, _, err := flow.Domain().Consensus().GetHashesBetween(lowHash, highHash, maxBlocks) - if err != nil { - return err - } - log.Debugf("Got %d header hashes above lowHash %s", len(blockHashes), lowHash) - - blockHeaders := make([]*appmessage.MsgBlockHeader, len(blockHashes)) - for i, blockHash := range blockHashes { - blockHeader, err := flow.Domain().Consensus().GetBlockHeader(blockHash) - if err != nil { - return err - } - blockHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(blockHeader) - } - - blockHeadersMessage := appmessage.NewBlockHeadersMessage(blockHeaders) - err = flow.outgoingRoute.Enqueue(blockHeadersMessage) - if err != nil { - return err - } - - message, err := flow.incomingRoute.Dequeue() - if err != nil { - return err - } - if _, ok := message.(*appmessage.MsgRequestNextHeaders); !ok { - return protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdRequestNextHeaders, message.Command()) - } - - // The next lowHash is the last element in blockHashes - lowHash = blockHashes[len(blockHashes)-1] - } - - err = flow.outgoingRoute.Enqueue(appmessage.NewMsgDoneHeaders()) - if err != nil { - return err - } - } -} - -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.MsgRequestHeaders) - - return msgRequestIBDBlocks.LowHash, msgRequestIBDBlocks.HighHash, nil -} diff --git a/app/protocol/flows/v3/blockrelay/handle_request_pruning_point_utxo_set.go b/app/protocol/flows/v3/blockrelay/handle_request_pruning_point_utxo_set.go deleted file mode 100644 index 4d1ed41f27..0000000000 --- a/app/protocol/flows/v3/blockrelay/handle_request_pruning_point_utxo_set.go +++ /dev/null @@ -1,140 +0,0 @@ -package blockrelay - -import ( - "errors" - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/common" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/ruleerrors" - "github.com/kaspanet/kaspad/infrastructure/logger" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -// HandleRequestPruningPointUTXOSetContext is the interface for the context needed for the HandleRequestPruningPointUTXOSet flow. -type HandleRequestPruningPointUTXOSetContext interface { - Domain() domain.Domain -} - -type handleRequestPruningPointUTXOSetFlow struct { - HandleRequestPruningPointUTXOSetContext - incomingRoute, outgoingRoute *router.Route -} - -// HandleRequestPruningPointUTXOSet listens to appmessage.MsgRequestPruningPointUTXOSet messages and sends -// the pruning point UTXO set and block body. -func HandleRequestPruningPointUTXOSet(context HandleRequestPruningPointUTXOSetContext, incomingRoute, - outgoingRoute *router.Route) error { - - flow := &handleRequestPruningPointUTXOSetFlow{ - HandleRequestPruningPointUTXOSetContext: context, - incomingRoute: incomingRoute, - outgoingRoute: outgoingRoute, - } - - return flow.start() -} - -func (flow *handleRequestPruningPointUTXOSetFlow) start() error { - for { - msgRequestPruningPointUTXOSet, err := flow.waitForRequestPruningPointUTXOSetMessages() - if err != nil { - return err - } - - err = flow.handleRequestPruningPointUTXOSetMessage(msgRequestPruningPointUTXOSet) - if err != nil { - return err - } - } -} - -func (flow *handleRequestPruningPointUTXOSetFlow) handleRequestPruningPointUTXOSetMessage( - msgRequestPruningPointUTXOSet *appmessage.MsgRequestPruningPointUTXOSet) error { - - onEnd := logger.LogAndMeasureExecutionTime(log, "handleRequestPruningPointUTXOSetFlow") - defer onEnd() - - log.Debugf("Got request for pruning point UTXO set") - - return flow.sendPruningPointUTXOSet(msgRequestPruningPointUTXOSet) -} - -func (flow *handleRequestPruningPointUTXOSetFlow) waitForRequestPruningPointUTXOSetMessages() ( - *appmessage.MsgRequestPruningPointUTXOSet, error) { - - message, err := flow.incomingRoute.Dequeue() - if err != nil { - return nil, err - } - msgRequestPruningPointUTXOSet, ok := message.(*appmessage.MsgRequestPruningPointUTXOSet) - if !ok { - // TODO: Change to shouldBan: true once we fix the bug of getting redundant messages - return nil, protocolerrors.Errorf(false, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdRequestPruningPointUTXOSet, message.Command()) - } - return msgRequestPruningPointUTXOSet, nil -} - -func (flow *handleRequestPruningPointUTXOSetFlow) sendPruningPointUTXOSet( - msgRequestPruningPointUTXOSet *appmessage.MsgRequestPruningPointUTXOSet) error { - - // Send the UTXO set in `step`-sized chunks - const step = 1000 - var fromOutpoint *externalapi.DomainOutpoint - chunksSent := 0 - for { - pruningPointUTXOs, err := flow.Domain().Consensus().GetPruningPointUTXOs( - msgRequestPruningPointUTXOSet.PruningPointHash, fromOutpoint, step) - if err != nil { - if errors.Is(err, ruleerrors.ErrWrongPruningPointHash) { - return flow.outgoingRoute.Enqueue(appmessage.NewMsgUnexpectedPruningPoint()) - } - } - - log.Debugf("Retrieved %d UTXOs for pruning block %s", - len(pruningPointUTXOs), msgRequestPruningPointUTXOSet.PruningPointHash) - - outpointAndUTXOEntryPairs := - appmessage.DomainOutpointAndUTXOEntryPairsToOutpointAndUTXOEntryPairs(pruningPointUTXOs) - err = flow.outgoingRoute.Enqueue(appmessage.NewMsgPruningPointUTXOSetChunk(outpointAndUTXOEntryPairs)) - if err != nil { - return err - } - - finished := len(pruningPointUTXOs) < step - if finished && chunksSent%ibdBatchSize != 0 { - log.Debugf("Finished sending UTXOs for pruning block %s", - msgRequestPruningPointUTXOSet.PruningPointHash) - - return flow.outgoingRoute.Enqueue(appmessage.NewMsgDonePruningPointUTXOSetChunks()) - } - - if len(pruningPointUTXOs) > 0 { - fromOutpoint = pruningPointUTXOs[len(pruningPointUTXOs)-1].Outpoint - } - chunksSent++ - - // Wait for the peer to request more chunks every `ibdBatchSize` chunks - if chunksSent%ibdBatchSize == 0 { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return err - } - _, ok := message.(*appmessage.MsgRequestNextPruningPointUTXOSetChunk) - if !ok { - // TODO: Change to shouldBan: true once we fix the bug of getting redundant messages - return protocolerrors.Errorf(false, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdRequestNextPruningPointUTXOSetChunk, message.Command()) - } - - if finished { - log.Debugf("Finished sending UTXOs for pruning block %s", - msgRequestPruningPointUTXOSet.PruningPointHash) - - return flow.outgoingRoute.Enqueue(appmessage.NewMsgDonePruningPointUTXOSetChunks()) - } - } - } -} diff --git a/app/protocol/flows/v3/blockrelay/ibd.go b/app/protocol/flows/v3/blockrelay/ibd.go deleted file mode 100644 index 9f76d82e33..0000000000 --- a/app/protocol/flows/v3/blockrelay/ibd.go +++ /dev/null @@ -1,577 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/common" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/app/protocol/protocolerrors" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/domain/consensus/model" - "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/kaspanet/kaspad/infrastructure/config" - "github.com/kaspanet/kaspad/infrastructure/logger" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" - "github.com/pkg/errors" - "time" -) - -// IBDContext is the interface for the context needed for the HandleIBD flow. -type IBDContext interface { - Domain() domain.Domain - Config() *config.Config - OnNewBlock(block *externalapi.DomainBlock, virtualChangeSet *externalapi.VirtualChangeSet) error - OnVirtualChange(virtualChangeSet *externalapi.VirtualChangeSet) error - OnPruningPointUTXOSetOverride() error - IsIBDRunning() bool - TrySetIBDRunning(ibdPeer *peerpkg.Peer) bool - UnsetIBDRunning() - IsRecoverableError(err error) bool -} - -type handleIBDFlow struct { - IBDContext - incomingRoute, outgoingRoute *router.Route - peer *peerpkg.Peer -} - -// HandleIBD handles IBD -func HandleIBD(context IBDContext, incomingRoute *router.Route, outgoingRoute *router.Route, - peer *peerpkg.Peer) error { - - flow := &handleIBDFlow{ - IBDContext: context, - incomingRoute: incomingRoute, - outgoingRoute: outgoingRoute, - peer: peer, - } - return flow.start() -} - -func (flow *handleIBDFlow) start() error { - for { - // Wait for IBD requests triggered by other flows - block, ok := <-flow.peer.IBDRequestChannel() - if !ok { - return nil - } - err := flow.runIBDIfNotRunning(block) - if err != nil { - return err - } - } -} - -func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) error { - wasIBDNotRunning := flow.TrySetIBDRunning(flow.peer) - if !wasIBDNotRunning { - log.Debugf("IBD is already running") - return nil - } - - isFinishedSuccessfully := false - defer func() { - flow.UnsetIBDRunning() - flow.logIBDFinished(isFinishedSuccessfully) - }() - - highHash := consensushashing.BlockHash(block) - log.Debugf("IBD started with peer %s and highHash %s", flow.peer, highHash) - log.Debugf("Syncing blocks up to %s", highHash) - log.Debugf("Trying to find highest shared chain block with peer %s with high hash %s", flow.peer, highHash) - highestSharedBlockHash, highestSharedBlockFound, err := flow.findHighestSharedBlockHash(highHash) - if err != nil { - return err - } - log.Debugf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer) - - shouldDownloadHeadersProof, shouldSync, err := flow.shouldSyncAndShouldDownloadHeadersProof(block, highestSharedBlockFound) - if err != nil { - return err - } - - if !shouldSync { - return nil - } - - if shouldDownloadHeadersProof { - log.Infof("Starting IBD with headers proof") - err := flow.ibdWithHeadersProof(highHash) - if err != nil { - return err - } - } else { - if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced { - isGenesisVirtualSelectedParent, err := flow.isGenesisVirtualSelectedParent() - if err != nil { - return err - } - - if isGenesisVirtualSelectedParent { - log.Infof("Cannot IBD to %s because it won't change the pruning point. The node needs to IBD "+ - "to the recent pruning point before normal operation can resume.", highHash) - return nil - } - } - - err = flow.syncPruningPointFutureHeaders(flow.Domain().Consensus(), highestSharedBlockHash, highHash) - if err != nil { - return err - } - } - - err = flow.syncMissingBlockBodies(highHash) - if err != nil { - return err - } - - log.Debugf("Finished syncing blocks up to %s", highHash) - isFinishedSuccessfully = true - return nil -} - -func (flow *handleIBDFlow) isGenesisVirtualSelectedParent() (bool, error) { - virtualSelectedParent, err := flow.Domain().Consensus().GetVirtualSelectedParent() - if err != nil { - return false, err - } - - return virtualSelectedParent.Equal(flow.Config().NetParams().GenesisHash), nil -} - -func (flow *handleIBDFlow) logIBDFinished(isFinishedSuccessfully bool) { - successString := "successfully" - if !isFinishedSuccessfully { - successString = "(interrupted)" - } - log.Infof("IBD finished %s", successString) -} - -// findHighestSharedBlock attempts to find the highest shared block between the peer -// and this node. This method may fail because the peer and us have conflicting pruning -// points. In that case we return (nil, false, nil) so that we may stop IBD gracefully. -func (flow *handleIBDFlow) findHighestSharedBlockHash( - targetHash *externalapi.DomainHash) (*externalapi.DomainHash, bool, error) { - - log.Debugf("Sending a blockLocator to %s between pruning point and headers selected tip", flow.peer) - blockLocator, err := flow.Domain().Consensus().CreateFullHeadersSelectedChainBlockLocator() - if err != nil { - return nil, false, err - } - - for { - highestHash, highestHashFound, err := flow.fetchHighestHash(targetHash, blockLocator) - if err != nil { - return nil, false, err - } - if !highestHashFound { - return nil, false, nil - } - highestHashIndex, err := flow.findHighestHashIndex(highestHash, blockLocator) - if err != nil { - return nil, false, err - } - - if highestHashIndex == 0 || - // If the block locator contains only two adjacent chain blocks, the - // syncer will always find the same highest chain block, so to avoid - // an endless loop, we explicitly stop the loop in such situation. - (len(blockLocator) == 2 && highestHashIndex == 1) { - - return highestHash, true, nil - } - - locatorHashAboveHighestHash := highestHash - if highestHashIndex > 0 { - locatorHashAboveHighestHash = blockLocator[highestHashIndex-1] - } - - blockLocator, err = flow.nextBlockLocator(highestHash, locatorHashAboveHighestHash) - if err != nil { - return nil, false, err - } - } -} - -func (flow *handleIBDFlow) nextBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) { - log.Debugf("Sending a blockLocator to %s between %s and %s", flow.peer, lowHash, highHash) - blockLocator, err := flow.Domain().Consensus().CreateHeadersSelectedChainBlockLocator(lowHash, highHash) - if err != nil { - if errors.Is(model.ErrBlockNotInSelectedParentChain, err) { - return nil, err - } - log.Debugf("Headers selected parent chain moved since findHighestSharedBlockHash - " + - "restarting with full block locator") - blockLocator, err = flow.Domain().Consensus().CreateFullHeadersSelectedChainBlockLocator() - if err != nil { - return nil, err - } - } - - return blockLocator, nil -} - -func (flow *handleIBDFlow) findHighestHashIndex( - highestHash *externalapi.DomainHash, blockLocator externalapi.BlockLocator) (int, error) { - - highestHashIndex := 0 - highestHashIndexFound := false - for i, blockLocatorHash := range blockLocator { - if highestHash.Equal(blockLocatorHash) { - highestHashIndex = i - highestHashIndexFound = true - break - } - } - if !highestHashIndexFound { - return 0, protocolerrors.Errorf(true, "highest hash %s "+ - "returned from peer %s is not in the original blockLocator", highestHash, flow.peer) - } - log.Debugf("The index of the highest hash in the original "+ - "blockLocator sent to %s is %d", flow.peer, highestHashIndex) - - return highestHashIndex, nil -} - -// fetchHighestHash attempts to fetch the highest hash the peer knows amongst the given -// blockLocator. This method may fail because the peer and us have conflicting pruning -// points. In that case we return (nil, false, nil) so that we may stop IBD gracefully. -func (flow *handleIBDFlow) fetchHighestHash( - targetHash *externalapi.DomainHash, blockLocator externalapi.BlockLocator) (*externalapi.DomainHash, bool, error) { - - ibdBlockLocatorMessage := appmessage.NewMsgIBDBlockLocator(targetHash, blockLocator) - err := flow.outgoingRoute.Enqueue(ibdBlockLocatorMessage) - if err != nil { - return nil, false, err - } - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, false, err - } - switch message := message.(type) { - case *appmessage.MsgIBDBlockLocatorHighestHash: - highestHash := message.HighestHash - log.Debugf("The highest hash the peer %s knows is %s", flow.peer, highestHash) - - return highestHash, true, nil - case *appmessage.MsgIBDBlockLocatorHighestHashNotFound: - log.Debugf("Peer %s does not know any block within our blockLocator. "+ - "This should only happen if there's a DAG split deeper than the pruning point.", flow.peer) - return nil, false, nil - default: - return nil, false, protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdIBDBlockLocatorHighestHash, message.Command()) - } -} - -func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.Consensus, highestSharedBlockHash *externalapi.DomainHash, - highHash *externalapi.DomainHash) error { - - log.Infof("Downloading headers from %s", flow.peer) - - err := flow.sendRequestHeaders(highestSharedBlockHash, highHash) - if err != nil { - return err - } - - // Keep a short queue of BlockHeadersMessages so that there's - // never a moment when the node is not validating and inserting - // headers - blockHeadersMessageChan := make(chan *appmessage.BlockHeadersMessage, 2) - errChan := make(chan error) - spawn("handleRelayInvsFlow-syncPruningPointFutureHeaders", func() { - for { - blockHeadersMessage, doneIBD, err := flow.receiveHeaders() - if err != nil { - errChan <- err - return - } - if doneIBD { - close(blockHeadersMessageChan) - return - } - - blockHeadersMessageChan <- blockHeadersMessage - - err = flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestNextHeaders()) - if err != nil { - errChan <- err - return - } - } - }) - - for { - select { - case ibdBlocksMessage, ok := <-blockHeadersMessageChan: - if !ok { - // If the highHash has not been received, the peer is misbehaving - highHashBlockInfo, err := consensus.GetBlockInfo(highHash) - if err != nil { - return err - } - if !highHashBlockInfo.Exists { - return protocolerrors.Errorf(true, "did not receive "+ - "highHash block %s from peer %s during block download", highHash, flow.peer) - } - return nil - } - for _, header := range ibdBlocksMessage.BlockHeaders { - err = flow.processHeader(consensus, header) - if err != nil { - return err - } - } - case err := <-errChan: - return err - } - } -} - -func (flow *handleIBDFlow) sendRequestHeaders(highestSharedBlockHash *externalapi.DomainHash, - peerSelectedTipHash *externalapi.DomainHash) error { - - msgGetBlockInvs := appmessage.NewMsgRequstHeaders(highestSharedBlockHash, peerSelectedTipHash) - return flow.outgoingRoute.Enqueue(msgGetBlockInvs) -} - -func (flow *handleIBDFlow) receiveHeaders() (msgIBDBlock *appmessage.BlockHeadersMessage, doneHeaders bool, err error) { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, false, err - } - switch message := message.(type) { - case *appmessage.BlockHeadersMessage: - return message, false, nil - case *appmessage.MsgDoneHeaders: - return nil, true, nil - default: - return nil, false, - protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s or %s, got: %s", - appmessage.CmdBlockHeaders, - appmessage.CmdDoneHeaders, - message.Command()) - } -} - -func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlockHeader *appmessage.MsgBlockHeader) error { - header := appmessage.BlockHeaderToDomainBlockHeader(msgBlockHeader) - block := &externalapi.DomainBlock{ - Header: header, - Transactions: nil, - } - - blockHash := consensushashing.BlockHash(block) - blockInfo, err := consensus.GetBlockInfo(blockHash) - if err != nil { - return err - } - if blockInfo.Exists { - log.Debugf("Block header %s is already in the DAG. Skipping...", blockHash) - return nil - } - _, err = consensus.ValidateAndInsertBlock(block, false) - if err != nil { - if !errors.As(err, &ruleerrors.RuleError{}) { - return errors.Wrapf(err, "failed to process header %s during IBD", blockHash) - } - - if errors.Is(err, ruleerrors.ErrDuplicateBlock) { - log.Debugf("Skipping block header %s as it is a duplicate", blockHash) - } else { - log.Infof("Rejected block header %s from %s during IBD: %s", blockHash, flow.peer, err) - return protocolerrors.Wrapf(true, err, "got invalid block header %s during IBD", blockHash) - } - } - - return nil -} - -func (flow *handleIBDFlow) validatePruningPointFutureHeaderTimestamps() error { - headerSelectedTipHash, err := flow.Domain().StagingConsensus().GetHeadersSelectedTip() - if err != nil { - return err - } - headerSelectedTipHeader, err := flow.Domain().StagingConsensus().GetBlockHeader(headerSelectedTipHash) - if err != nil { - return err - } - headerSelectedTipTimestamp := headerSelectedTipHeader.TimeInMilliseconds() - - currentSelectedTipHash, err := flow.Domain().Consensus().GetHeadersSelectedTip() - if err != nil { - return err - } - currentSelectedTipHeader, err := flow.Domain().Consensus().GetBlockHeader(currentSelectedTipHash) - if err != nil { - return err - } - currentSelectedTipTimestamp := currentSelectedTipHeader.TimeInMilliseconds() - - if headerSelectedTipTimestamp < currentSelectedTipTimestamp { - return protocolerrors.Errorf(false, "the timestamp of the candidate selected "+ - "tip is smaller than the current selected tip") - } - - minTimestampDifferenceInMilliseconds := (10 * time.Minute).Milliseconds() - if headerSelectedTipTimestamp-currentSelectedTipTimestamp < minTimestampDifferenceInMilliseconds { - return protocolerrors.Errorf(false, "difference between the timestamps of "+ - "the current pruning point and the candidate pruning point is too small. Aborting IBD...") - } - return nil -} - -func (flow *handleIBDFlow) receiveAndInsertPruningPointUTXOSet( - consensus externalapi.Consensus, pruningPointHash *externalapi.DomainHash) (bool, error) { - - onEnd := logger.LogAndMeasureExecutionTime(log, "receiveAndInsertPruningPointUTXOSet") - defer onEnd() - - receivedChunkCount := 0 - receivedUTXOCount := 0 - for { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return false, err - } - - switch message := message.(type) { - case *appmessage.MsgPruningPointUTXOSetChunk: - receivedUTXOCount += len(message.OutpointAndUTXOEntryPairs) - domainOutpointAndUTXOEntryPairs := - appmessage.OutpointAndUTXOEntryPairsToDomainOutpointAndUTXOEntryPairs(message.OutpointAndUTXOEntryPairs) - - err := consensus.AppendImportedPruningPointUTXOs(domainOutpointAndUTXOEntryPairs) - if err != nil { - return false, err - } - - receivedChunkCount++ - if receivedChunkCount%ibdBatchSize == 0 { - log.Debugf("Received %d UTXO set chunks so far, totaling in %d UTXOs", - receivedChunkCount, receivedUTXOCount) - - requestNextPruningPointUTXOSetChunkMessage := appmessage.NewMsgRequestNextPruningPointUTXOSetChunk() - err := flow.outgoingRoute.Enqueue(requestNextPruningPointUTXOSetChunkMessage) - if err != nil { - return false, err - } - } - - case *appmessage.MsgDonePruningPointUTXOSetChunks: - log.Infof("Finished receiving the UTXO set. Total UTXOs: %d", receivedUTXOCount) - return true, nil - - case *appmessage.MsgUnexpectedPruningPoint: - log.Infof("Could not receive the next UTXO chunk because the pruning point %s "+ - "is no longer the pruning point of peer %s", pruningPointHash, flow.peer) - return false, nil - - default: - return false, protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s or %s or %s, got: %s", appmessage.CmdPruningPointUTXOSetChunk, - appmessage.CmdDonePruningPointUTXOSetChunks, appmessage.CmdUnexpectedPruningPoint, message.Command(), - ) - } - } -} - -func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHash) error { - hashes, err := flow.Domain().Consensus().GetMissingBlockBodyHashes(highHash) - if err != nil { - return err - } - if len(hashes) == 0 { - // 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 - GetMissingBlockBodyHashes would return an empty array. - log.Debugf("No missing block body hashes found.") - return nil - } - - for offset := 0; offset < len(hashes); offset += ibdBatchSize { - var hashesToRequest []*externalapi.DomainHash - if offset+ibdBatchSize < len(hashes) { - hashesToRequest = hashes[offset : offset+ibdBatchSize] - } 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 := consensushashing.BlockHash(block) - if !expectedHash.Equal(blockHash) { - return protocolerrors.Errorf(true, "expected block %s but got %s", expectedHash, blockHash) - } - - err = flow.banIfBlockIsHeaderOnly(block) - if err != nil { - return err - } - - virtualChangeSet, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, false) - if err != nil { - if errors.Is(err, ruleerrors.ErrDuplicateBlock) { - log.Debugf("Skipping IBD Block %s as it has already been added to the DAG", blockHash) - continue - } - return protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "invalid block %s", blockHash) - } - err = flow.OnNewBlock(block, virtualChangeSet) - if err != nil { - return err - } - } - } - - return flow.resolveVirtual() -} - -func (flow *handleIBDFlow) banIfBlockIsHeaderOnly(block *externalapi.DomainBlock) error { - if len(block.Transactions) == 0 { - return protocolerrors.Errorf(true, "sent header of %s block where expected block with body", - consensushashing.BlockHash(block)) - } - - return nil -} - -func (flow *handleIBDFlow) resolveVirtual() error { - for i := 0; ; i++ { - if i%10 == 0 { - log.Infof("Resolving virtual. This may take some time...") - } - virtualChangeSet, isCompletelyResolved, err := flow.Domain().Consensus().ResolveVirtual() - if err != nil { - return err - } - - err = flow.OnVirtualChange(virtualChangeSet) - if err != nil { - return err - } - - if isCompletelyResolved { - log.Infof("Resolved virtual") - return nil - } - } -} diff --git a/app/protocol/flows/v3/blockrelay/ibd_with_headers_proof.go b/app/protocol/flows/v3/blockrelay/ibd_with_headers_proof.go deleted file mode 100644 index e0b0d300f7..0000000000 --- a/app/protocol/flows/v3/blockrelay/ibd_with_headers_proof.go +++ /dev/null @@ -1,364 +0,0 @@ -package blockrelay - -import ( - "fmt" - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/common" - "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" -) - -func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash) error { - err := flow.Domain().InitStagingConsensus() - if err != nil { - return err - } - - err = flow.downloadHeadersAndPruningUTXOSet(highHash) - if err != nil { - if !flow.IsRecoverableError(err) { - return err - } - - deleteStagingConsensusErr := flow.Domain().DeleteStagingConsensus() - if deleteStagingConsensusErr != nil { - return deleteStagingConsensusErr - } - - return err - } - - err = flow.Domain().CommitStagingConsensus() - if err != nil { - return err - } - - err = flow.OnPruningPointUTXOSetOverride() - if err != nil { - return err - } - - return nil -} - -func (flow *handleIBDFlow) shouldSyncAndShouldDownloadHeadersProof(highBlock *externalapi.DomainBlock, - highestSharedBlockFound bool) (shouldDownload, shouldSync bool, err error) { - - if !highestSharedBlockFound { - hasMoreBlueWorkThanSelectedTipAndPruningDepthMoreBlueScore, err := flow.checkIfHighHashHasMoreBlueWorkThanSelectedTipAndPruningDepthMoreBlueScore(highBlock) - if err != nil { - return false, false, err - } - - if hasMoreBlueWorkThanSelectedTipAndPruningDepthMoreBlueScore { - return true, true, nil - } - - return false, false, nil - } - - return false, true, nil -} - -func (flow *handleIBDFlow) checkIfHighHashHasMoreBlueWorkThanSelectedTipAndPruningDepthMoreBlueScore(highBlock *externalapi.DomainBlock) (bool, error) { - headersSelectedTip, err := flow.Domain().Consensus().GetHeadersSelectedTip() - if err != nil { - return false, err - } - - headersSelectedTipInfo, err := flow.Domain().Consensus().GetBlockInfo(headersSelectedTip) - if err != nil { - return false, err - } - - if highBlock.Header.BlueScore() < headersSelectedTipInfo.BlueScore+flow.Config().NetParams().PruningDepth() { - return false, nil - } - - return highBlock.Header.BlueWork().Cmp(headersSelectedTipInfo.BlueWork) > 0, nil -} - -func (flow *handleIBDFlow) 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 nil, err - } - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, err - } - pruningPointProofMessage, ok := message.(*appmessage.MsgPruningPointProof) - if !ok { - return nil, protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdPruningPointProof, message.Command()) - } - pruningPointProof := appmessage.MsgPruningPointProofToDomainPruningPointProof(pruningPointProofMessage) - 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 *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash) error { - proofPruningPoint, err := flow.syncAndValidatePruningPointProof() - if err != nil { - return err - } - - 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 proofPruningPoint.Equal(flow.Config().NetParams().GenesisHash) { - return protocolerrors.Errorf(true, "the genesis pruning point violates finality") - } - - err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), proofPruningPoint, highHash) - if err != nil { - return err - } - - log.Infof("Headers downloaded from peer %s", flow.peer) - - highHashInfo, err := flow.Domain().StagingConsensus().GetBlockInfo(highHash) - if err != nil { - return err - } - - if !highHashInfo.Exists { - return protocolerrors.Errorf(true, "the triggering IBD block was not sent") - } - - err = flow.validatePruningPointFutureHeaderTimestamps() - if err != nil { - return err - } - - log.Debugf("Syncing the current pruning point UTXO set") - syncedPruningPointUTXOSetSuccessfully, err := flow.syncPruningPointUTXOSet(flow.Domain().StagingConsensus(), proofPruningPoint) - if err != nil { - return err - } - if !syncedPruningPointUTXOSetSuccessfully { - log.Debugf("Aborting IBD because the pruning point UTXO set failed to sync") - return nil - } - log.Debugf("Finished syncing the current pruning point UTXO set") - return nil -} - -func (flow *handleIBDFlow) 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 err - } - - err = flow.validateAndInsertPruningPoints(proofPruningPoint) - if err != nil { - return err - } - - pruningPointWithMetaData, done, err := flow.receiveBlockWithTrustedData() - if err != nil { - return err - } - - if done { - return protocolerrors.Errorf(true, "got `done` message before receiving the pruning point") - } - - 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 err - } - - for { - blockWithTrustedData, done, err := flow.receiveBlockWithTrustedData() - if err != nil { - return err - } - - if done { - break - } - - err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), blockWithTrustedData) - if err != nil { - return err - } - } - - log.Infof("Finished downloading pruning point and its anticone from %s", flow.peer) - return nil -} - -func (flow *handleIBDFlow) processBlockWithTrustedData( - consensus externalapi.Consensus, block *appmessage.MsgBlockWithTrustedData) error { - - _, err := consensus.ValidateAndInsertBlockWithTrustedData(appmessage.BlockWithTrustedDataToDomainBlockWithTrustedData(block), false) - return err -} - -func (flow *handleIBDFlow) receiveBlockWithTrustedData() (*appmessage.MsgBlockWithTrustedData, bool, error) { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, false, err - } - - switch downCastedMessage := message.(type) { - case *appmessage.MsgBlockWithTrustedData: - return downCastedMessage, false, nil - case *appmessage.MsgDoneBlocksWithTrustedData: - return nil, true, nil - default: - return nil, false, - protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s or %s, got: %s", - (&appmessage.MsgBlockWithTrustedData{}).Command(), - (&appmessage.MsgDoneBlocksWithTrustedData{}).Command(), - downCastedMessage.Command()) - } -} - -func (flow *handleIBDFlow) receivePruningPoints() (*appmessage.MsgPruningPoints, error) { - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) - if err != nil { - return nil, err - } - - msgPruningPoints, ok := message.(*appmessage.MsgPruningPoints) - if !ok { - return nil, - protocolerrors.Errorf(true, "received unexpected message type. "+ - "expected: %s, got: %s", appmessage.CmdPruningPoints, message.Command()) - } - - return msgPruningPoints, nil -} - -func (flow *handleIBDFlow) 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 - } - - headers := make([]externalapi.BlockHeader, len(pruningPoints.Headers)) - for i, header := range pruningPoints.Headers { - headers[i] = appmessage.BlockHeaderToDomainBlockHeader(header) - } - - arePruningPointsViolatingFinality, err := flow.Domain().Consensus().ArePruningPointsViolatingFinality(headers) - if err != nil { - return err - } - - if arePruningPointsViolatingFinality { - // TODO: Find a better way to deal with finality conflicts. - 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 - } - - return nil -} - -func (flow *handleIBDFlow) syncPruningPointUTXOSet(consensus externalapi.Consensus, - pruningPoint *externalapi.DomainHash) (bool, error) { - - log.Infof("Checking if the suggested pruning point %s is compatible to the node DAG", pruningPoint) - isValid, err := flow.Domain().StagingConsensus().IsValidPruningPoint(pruningPoint) - if err != nil { - return false, err - } - - if !isValid { - return false, protocolerrors.Errorf(true, "invalid pruning point %s", pruningPoint) - } - - log.Info("Fetching the pruning point UTXO set") - isSuccessful, err := flow.fetchMissingUTXOSet(consensus, pruningPoint) - if err != nil { - return false, err - } - - if !isSuccessful { - log.Infof("Couldn't successfully fetch the pruning point UTXO set. Stopping IBD.") - return false, nil - } - - log.Info("Fetched the new pruning point UTXO set") - return true, nil -} - -func (flow *handleIBDFlow) fetchMissingUTXOSet(consensus externalapi.Consensus, pruningPointHash *externalapi.DomainHash) (succeed bool, err error) { - defer func() { - err := flow.Domain().StagingConsensus().ClearImportedPruningPointData() - if err != nil { - panic(fmt.Sprintf("failed to clear imported pruning point data: %s", err)) - } - }() - - err = flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointUTXOSet(pruningPointHash)) - if err != nil { - return false, err - } - - receivedAll, err := flow.receiveAndInsertPruningPointUTXOSet(consensus, pruningPointHash) - if err != nil { - return false, err - } - if !receivedAll { - return false, nil - } - - err = flow.Domain().StagingConsensus().ValidateAndInsertImportedPruningPoint(pruningPointHash) - if err != nil { - // TODO: Find a better way to deal with finality conflicts. - if errors.Is(err, ruleerrors.ErrSuggestedPruningViolatesFinality) { - return false, nil - } - return false, protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "error with pruning point UTXO set") - } - - return true, nil -} diff --git a/app/protocol/flows/v3/blockrelay/log.go b/app/protocol/flows/v3/blockrelay/log.go deleted file mode 100644 index 6c57009900..0000000000 --- a/app/protocol/flows/v3/blockrelay/log.go +++ /dev/null @@ -1,9 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/infrastructure/logger" - "github.com/kaspanet/kaspad/util/panics" -) - -var log = logger.RegisterSubSystem("PROT") -var spawn = panics.GoroutineWrapperFunc(log) diff --git a/app/protocol/flows/v3/blockrelay/send_virtual_selected_parent_inv.go b/app/protocol/flows/v3/blockrelay/send_virtual_selected_parent_inv.go deleted file mode 100644 index fd5a22e8d3..0000000000 --- a/app/protocol/flows/v3/blockrelay/send_virtual_selected_parent_inv.go +++ /dev/null @@ -1,35 +0,0 @@ -package blockrelay - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - "github.com/kaspanet/kaspad/domain" - "github.com/kaspanet/kaspad/infrastructure/config" - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -// SendVirtualSelectedParentInvContext is the interface for the context needed for the SendVirtualSelectedParentInv flow. -type SendVirtualSelectedParentInvContext interface { - Domain() domain.Domain - Config() *config.Config -} - -// SendVirtualSelectedParentInv sends a peer the selected parent hash of the virtual -func SendVirtualSelectedParentInv(context SendVirtualSelectedParentInvContext, - outgoingRoute *router.Route, peer *peerpkg.Peer) error { - - virtualSelectedParent, err := context.Domain().Consensus().GetVirtualSelectedParent() - if err != nil { - return err - } - - if virtualSelectedParent.Equal(context.Config().NetParams().GenesisHash) { - log.Debugf("Skipping sending the virtual selected parent hash to peer %s because it's the genesis", peer) - return nil - } - - log.Debugf("Sending virtual selected parent hash %s to peer %s", virtualSelectedParent, peer) - - virtualSelectedParentInv := appmessage.NewMsgInvBlock(virtualSelectedParent) - return outgoingRoute.Enqueue(virtualSelectedParentInv) -} diff --git a/app/protocol/flows/v3/register.go b/app/protocol/flows/v3/register.go deleted file mode 100644 index 3f55a9a2b3..0000000000 --- a/app/protocol/flows/v3/register.go +++ /dev/null @@ -1,187 +0,0 @@ -package v3 - -import ( - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/common" - "github.com/kaspanet/kaspad/app/protocol/flowcontext" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/addressexchange" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/blockrelay" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/ping" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/rejects" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/transactionrelay" - peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" - routerpkg "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" -) - -type protocolManager interface { - RegisterFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand, isStopping *uint32, - errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow - RegisterOneTimeFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand, - isStopping *uint32, stopChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow - RegisterFlowWithCapacity(name string, capacity int, router *routerpkg.Router, - messageTypes []appmessage.MessageCommand, isStopping *uint32, - errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow - Context() *flowcontext.FlowContext -} - -// Register is used in order to register all the protocol flows to the given router. -func Register(m protocolManager, router *routerpkg.Router, errChan chan error, isStopping *uint32) (flows []*common.Flow) { - flows = registerAddressFlows(m, router, isStopping, errChan) - flows = append(flows, registerBlockRelayFlows(m, router, isStopping, errChan)...) - flows = append(flows, registerPingFlows(m, router, isStopping, errChan)...) - flows = append(flows, registerTransactionRelayFlow(m, router, isStopping, errChan)...) - flows = append(flows, registerRejectsFlow(m, router, isStopping, errChan)...) - - return flows -} - -func registerAddressFlows(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow { - outgoingRoute := router.OutgoingRoute() - - return []*common.Flow{ - m.RegisterOneTimeFlow("ReceiveAddresses", router, []appmessage.MessageCommand{appmessage.CmdAddresses}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return addressexchange.ReceiveAddresses(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - } -} - -func registerBlockRelayFlows(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow { - outgoingRoute := router.OutgoingRoute() - - return []*common.Flow{ - m.RegisterOneTimeFlow("SendVirtualSelectedParentInv", router, []appmessage.MessageCommand{}, - isStopping, errChan, func(route *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.SendVirtualSelectedParentInv(m.Context(), outgoingRoute, peer) - }), - - m.RegisterFlow("HandleRelayInvs", router, []appmessage.MessageCommand{ - appmessage.CmdInvRelayBlock, appmessage.CmdBlock, appmessage.CmdBlockLocator, - }, - isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleRelayInvs(m.Context(), incomingRoute, - outgoingRoute, peer) - }, - ), - - m.RegisterFlow("HandleIBD", router, []appmessage.MessageCommand{ - appmessage.CmdDoneHeaders, appmessage.CmdUnexpectedPruningPoint, appmessage.CmdPruningPointUTXOSetChunk, - appmessage.CmdBlockHeaders, appmessage.CmdIBDBlockLocatorHighestHash, appmessage.CmdBlockWithTrustedData, - appmessage.CmdDoneBlocksWithTrustedData, appmessage.CmdIBDBlockLocatorHighestHashNotFound, - appmessage.CmdDonePruningPointUTXOSetChunks, appmessage.CmdIBDBlock, appmessage.CmdPruningPoints, - appmessage.CmdPruningPointProof, - }, - isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleIBD(m.Context(), incomingRoute, - outgoingRoute, peer) - }, - ), - - m.RegisterFlow("HandleRelayBlockRequests", router, []appmessage.MessageCommand{appmessage.CmdRequestRelayBlocks}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleRelayBlockRequests(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - - m.RegisterFlow("HandleRequestBlockLocator", router, - []appmessage.MessageCommand{appmessage.CmdRequestBlockLocator}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleRequestBlockLocator(m.Context(), incomingRoute, outgoingRoute) - }, - ), - - m.RegisterFlow("HandleRequestHeaders", router, - []appmessage.MessageCommand{appmessage.CmdRequestHeaders, appmessage.CmdRequestNextHeaders}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleRequestHeaders(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - - m.RegisterFlow("HandleIBDBlockRequests", router, - []appmessage.MessageCommand{appmessage.CmdRequestIBDBlocks}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleIBDBlockRequests(m.Context(), incomingRoute, outgoingRoute) - }, - ), - - m.RegisterFlow("HandleRequestPruningPointUTXOSet", router, - []appmessage.MessageCommand{appmessage.CmdRequestPruningPointUTXOSet, - appmessage.CmdRequestNextPruningPointUTXOSetChunk}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleRequestPruningPointUTXOSet(m.Context(), incomingRoute, outgoingRoute) - }, - ), - - m.RegisterFlow("HandlePruningPointAndItsAnticoneRequests", router, - []appmessage.MessageCommand{appmessage.CmdRequestPruningPointAndItsAnticone}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandlePruningPointAndItsAnticoneRequests(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - - m.RegisterFlow("HandleIBDBlockLocator", router, - []appmessage.MessageCommand{appmessage.CmdIBDBlockLocator}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandleIBDBlockLocator(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - - m.RegisterFlow("HandlePruningPointProofRequests", router, - []appmessage.MessageCommand{appmessage.CmdRequestPruningPointProof}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return blockrelay.HandlePruningPointProofRequests(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - } -} - -func registerPingFlows(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow { - outgoingRoute := router.OutgoingRoute() - - return []*common.Flow{ - m.RegisterFlow("ReceivePings", router, []appmessage.MessageCommand{appmessage.CmdPing}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return ping.ReceivePings(m.Context(), incomingRoute, outgoingRoute) - }, - ), - - m.RegisterFlow("SendPings", router, []appmessage.MessageCommand{appmessage.CmdPong}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return ping.SendPings(m.Context(), incomingRoute, outgoingRoute, peer) - }, - ), - } -} - -func registerTransactionRelayFlow(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow { - outgoingRoute := router.OutgoingRoute() - - return []*common.Flow{ - m.RegisterFlowWithCapacity("HandleRelayedTransactions", 10_000, router, - []appmessage.MessageCommand{appmessage.CmdInvTransaction, appmessage.CmdTx, appmessage.CmdTransactionNotFound}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return transactionrelay.HandleRelayedTransactions(m.Context(), incomingRoute, outgoingRoute) - }, - ), - m.RegisterFlow("HandleRequestTransactions", router, - []appmessage.MessageCommand{appmessage.CmdRequestTransactions}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return transactionrelay.HandleRequestedTransactions(m.Context(), incomingRoute, outgoingRoute) - }, - ), - } -} - -func registerRejectsFlow(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow { - outgoingRoute := router.OutgoingRoute() - - return []*common.Flow{ - m.RegisterFlow("HandleRejects", router, - []appmessage.MessageCommand{appmessage.CmdReject}, isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return rejects.HandleRejects(m.Context(), incomingRoute, outgoingRoute) - }, - ), - } -} diff --git a/app/protocol/flows/v3/addressexchange/receiveaddresses.go b/app/protocol/flows/v4/addressexchange/receiveaddresses.go similarity index 100% rename from app/protocol/flows/v3/addressexchange/receiveaddresses.go rename to app/protocol/flows/v4/addressexchange/receiveaddresses.go diff --git a/app/protocol/flows/v3/addressexchange/sendaddresses.go b/app/protocol/flows/v4/addressexchange/sendaddresses.go similarity index 100% rename from app/protocol/flows/v3/addressexchange/sendaddresses.go rename to app/protocol/flows/v4/addressexchange/sendaddresses.go diff --git a/app/protocol/flows/v4/blockrelay/ibd.go b/app/protocol/flows/v4/blockrelay/ibd.go index 9f76d82e33..02c9dd0822 100644 --- a/app/protocol/flows/v4/blockrelay/ibd.go +++ b/app/protocol/flows/v4/blockrelay/ibd.go @@ -97,7 +97,7 @@ func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) er if shouldDownloadHeadersProof { log.Infof("Starting IBD with headers proof") - err := flow.ibdWithHeadersProof(highHash) + err := flow.ibdWithHeadersProof(highHash, block.Header.DAAScore()) if err != nil { return err } @@ -115,7 +115,7 @@ func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) er } } - err = flow.syncPruningPointFutureHeaders(flow.Domain().Consensus(), highestSharedBlockHash, highHash) + err = flow.syncPruningPointFutureHeaders(flow.Domain().Consensus(), highestSharedBlockHash, highHash, block.Header.DAAScore()) if err != nil { return err } @@ -266,7 +266,7 @@ func (flow *handleIBDFlow) fetchHighestHash( } func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.Consensus, highestSharedBlockHash *externalapi.DomainHash, - highHash *externalapi.DomainHash) error { + highHash *externalapi.DomainHash, highBlockDAAScore uint64) error { log.Infof("Downloading headers from %s", flow.peer) @@ -275,6 +275,12 @@ func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.C return err } + highestSharedBlockHeader, err := consensus.GetBlockHeader(highestSharedBlockHash) + if err != nil { + return err + } + progressReporter := newIBDProgressReporter(highestSharedBlockHeader.DAAScore(), highBlockDAAScore, "block headers") + // Keep a short queue of BlockHeadersMessages so that there's // never a moment when the node is not validating and inserting // headers @@ -323,6 +329,9 @@ func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.C return err } } + + lastReceivedHeader := ibdBlocksMessage.BlockHeaders[len(ibdBlocksMessage.BlockHeaders)-1] + progressReporter.reportProgress(len(ibdBlocksMessage.BlockHeaders), lastReceivedHeader.DAAScore) case err := <-errChan: return err } @@ -491,6 +500,17 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa return nil } + lowBlockHeader, err := flow.Domain().Consensus().GetBlockHeader(hashes[0]) + if err != nil { + return err + } + highBlockHeader, err := flow.Domain().Consensus().GetBlockHeader(hashes[len(hashes)-1]) + if err != nil { + return err + } + progressReporter := newIBDProgressReporter(lowBlockHeader.DAAScore(), highBlockHeader.DAAScore(), "blocks") + highestProcessedDAAScore := lowBlockHeader.DAAScore() + for offset := 0; offset < len(hashes); offset += ibdBatchSize { var hashesToRequest []*externalapi.DomainHash if offset+ibdBatchSize < len(hashes) { @@ -539,10 +559,14 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa if err != nil { return err } + + highestProcessedDAAScore = block.Header.DAAScore() } + + progressReporter.reportProgress(len(hashesToRequest), highestProcessedDAAScore) } - return flow.resolveVirtual() + return flow.resolveVirtual(highestProcessedDAAScore) } func (flow *handleIBDFlow) banIfBlockIsHeaderOnly(block *externalapi.DomainBlock) error { @@ -554,10 +578,20 @@ func (flow *handleIBDFlow) banIfBlockIsHeaderOnly(block *externalapi.DomainBlock return nil } -func (flow *handleIBDFlow) resolveVirtual() error { +func (flow *handleIBDFlow) resolveVirtual(estimatedVirtualDAAScoreTarget uint64) error { + virtualDAAScoreStart, err := flow.Domain().Consensus().GetVirtualDAAScore() + if err != nil { + return err + } + for i := 0; ; i++ { if i%10 == 0 { - log.Infof("Resolving virtual. This may take some time...") + virtualDAAScore, err := flow.Domain().Consensus().GetVirtualDAAScore() + if err != nil { + return err + } + log.Infof("Resolving virtual. Estimated progress: %d%%", + int(float64(virtualDAAScore-virtualDAAScoreStart)/float64(estimatedVirtualDAAScoreTarget-virtualDAAScoreStart)*100)) } virtualChangeSet, isCompletelyResolved, err := flow.Domain().Consensus().ResolveVirtual() if err != nil { diff --git a/app/protocol/flows/v4/blockrelay/ibd_progress_reporter.go b/app/protocol/flows/v4/blockrelay/ibd_progress_reporter.go new file mode 100644 index 0000000000..acb8d8209c --- /dev/null +++ b/app/protocol/flows/v4/blockrelay/ibd_progress_reporter.go @@ -0,0 +1,32 @@ +package blockrelay + +type ibdProgressReporter struct { + lowDAAScore uint64 + highDAAScore uint64 + objectName string + totalDAAScoreDifference uint64 + lastReportedProgressPercent int + processed int +} + +func newIBDProgressReporter(lowDAAScore uint64, highDAAScore uint64, objectName string) *ibdProgressReporter { + return &ibdProgressReporter{ + lowDAAScore: lowDAAScore, + highDAAScore: highDAAScore, + objectName: objectName, + totalDAAScoreDifference: highDAAScore - lowDAAScore, + lastReportedProgressPercent: 0, + processed: 0, + } +} + +func (ipr *ibdProgressReporter) reportProgress(processedDelta int, highestProcessedDAAScore uint64) { + ipr.processed += processedDelta + + relativeDAAScore := highestProcessedDAAScore - ipr.lowDAAScore + progressPercent := int((float64(relativeDAAScore) / float64(ipr.totalDAAScoreDifference)) * 100) + if progressPercent > ipr.lastReportedProgressPercent { + log.Infof("IBD: Processed %d %s (%d%%)", ipr.processed, ipr.objectName, progressPercent) + ipr.lastReportedProgressPercent = progressPercent + } +} 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 e2f42a47ab..1b89fcdb82 100644 --- a/app/protocol/flows/v4/blockrelay/ibd_with_headers_proof.go +++ b/app/protocol/flows/v4/blockrelay/ibd_with_headers_proof.go @@ -9,15 +9,16 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/ruleerrors" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/pkg/errors" + "time" ) -func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash) error { +func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash, highBlockDAAScore uint64) error { err := flow.Domain().InitStagingConsensus() if err != nil { return err } - err = flow.downloadHeadersAndPruningUTXOSet(highHash) + err = flow.downloadHeadersAndPruningUTXOSet(highHash, highBlockDAAScore) if err != nil { if !flow.IsRecoverableError(err) { return err @@ -87,7 +88,7 @@ func (flow *handleIBDFlow) syncAndValidatePruningPointProof() (*externalapi.Doma if err != nil { return nil, err } - message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout) + message, err := flow.incomingRoute.DequeueWithTimeout(10 * time.Minute) if err != nil { return nil, err } @@ -113,7 +114,7 @@ func (flow *handleIBDFlow) syncAndValidatePruningPointProof() (*externalapi.Doma return consensushashing.HeaderHash(pruningPointProof.Headers[0][len(pruningPointProof.Headers[0])-1]), nil } -func (flow *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash) error { +func (flow *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash, highBlockDAAScore uint64) error { proofPruningPoint, err := flow.syncAndValidatePruningPointProof() if err != nil { return err @@ -130,7 +131,7 @@ func (flow *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalap return protocolerrors.Errorf(true, "the genesis pruning point violates finality") } - err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), proofPruningPoint, highHash) + err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), proofPruningPoint, highHash, highBlockDAAScore) if err != nil { return err } diff --git a/app/protocol/flows/v3/ping/receive.go b/app/protocol/flows/v4/ping/receive.go similarity index 100% rename from app/protocol/flows/v3/ping/receive.go rename to app/protocol/flows/v4/ping/receive.go diff --git a/app/protocol/flows/v3/ping/send.go b/app/protocol/flows/v4/ping/send.go similarity index 100% rename from app/protocol/flows/v3/ping/send.go rename to app/protocol/flows/v4/ping/send.go diff --git a/app/protocol/flows/v4/register.go b/app/protocol/flows/v4/register.go index 596ca9d92f..fd2c914581 100644 --- a/app/protocol/flows/v4/register.go +++ b/app/protocol/flows/v4/register.go @@ -4,11 +4,11 @@ import ( "github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/protocol/common" "github.com/kaspanet/kaspad/app/protocol/flowcontext" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/addressexchange" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/ping" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/rejects" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/transactionrelay" + "github.com/kaspanet/kaspad/app/protocol/flows/v4/addressexchange" "github.com/kaspanet/kaspad/app/protocol/flows/v4/blockrelay" + "github.com/kaspanet/kaspad/app/protocol/flows/v4/ping" + "github.com/kaspanet/kaspad/app/protocol/flows/v4/rejects" + "github.com/kaspanet/kaspad/app/protocol/flows/v4/transactionrelay" peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" routerpkg "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" ) @@ -39,13 +39,11 @@ func registerAddressFlows(m protocolManager, router *routerpkg.Router, isStoppin outgoingRoute := router.OutgoingRoute() return []*common.Flow{ - // TODO: This code was moved to the upper level to prevent a race condition when connecting to v3 peers. This should be uncommented - // and removed from the upper level once v3 is obsolete. - //m.RegisterFlow("SendAddresses", router, []appmessage.MessageCommand{appmessage.CmdRequestAddresses}, isStopping, errChan, - // func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - // return addressexchange.SendAddresses(m.Context(), incomingRoute, outgoingRoute) - // }, - //), + m.RegisterFlow("SendAddresses", router, []appmessage.MessageCommand{appmessage.CmdRequestAddresses}, isStopping, errChan, + func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { + return addressexchange.SendAddresses(m.Context(), incomingRoute, outgoingRoute) + }, + ), m.RegisterOneTimeFlow("ReceiveAddresses", router, []appmessage.MessageCommand{appmessage.CmdAddresses}, isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { diff --git a/app/protocol/flows/v3/rejects/handle_rejects.go b/app/protocol/flows/v4/rejects/handle_rejects.go similarity index 100% rename from app/protocol/flows/v3/rejects/handle_rejects.go rename to app/protocol/flows/v4/rejects/handle_rejects.go diff --git a/app/protocol/flows/v3/testing/common_test.go b/app/protocol/flows/v4/testing/common_test.go similarity index 100% rename from app/protocol/flows/v3/testing/common_test.go rename to app/protocol/flows/v4/testing/common_test.go diff --git a/app/protocol/flows/v3/testing/receiveaddresses_test.go b/app/protocol/flows/v4/testing/receiveaddresses_test.go similarity index 96% rename from app/protocol/flows/v3/testing/receiveaddresses_test.go rename to app/protocol/flows/v4/testing/receiveaddresses_test.go index 5eb56c41ec..5e5c5c0a31 100644 --- a/app/protocol/flows/v3/testing/receiveaddresses_test.go +++ b/app/protocol/flows/v4/testing/receiveaddresses_test.go @@ -1,11 +1,11 @@ package testing import ( + "github.com/kaspanet/kaspad/app/protocol/flows/v4/addressexchange" "testing" "time" "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/addressexchange" peerpkg "github.com/kaspanet/kaspad/app/protocol/peer" "github.com/kaspanet/kaspad/domain/consensus" "github.com/kaspanet/kaspad/domain/consensus/utils/testutils" diff --git a/app/protocol/flows/v3/testing/testing.go b/app/protocol/flows/v4/testing/testing.go similarity index 100% rename from app/protocol/flows/v3/testing/testing.go rename to app/protocol/flows/v4/testing/testing.go diff --git a/app/protocol/flows/v3/transactionrelay/handle_relayed_transactions.go b/app/protocol/flows/v4/transactionrelay/handle_relayed_transactions.go similarity index 100% rename from app/protocol/flows/v3/transactionrelay/handle_relayed_transactions.go rename to app/protocol/flows/v4/transactionrelay/handle_relayed_transactions.go diff --git a/app/protocol/flows/v3/transactionrelay/handle_relayed_transactions_test.go b/app/protocol/flows/v4/transactionrelay/handle_relayed_transactions_test.go similarity index 99% rename from app/protocol/flows/v3/transactionrelay/handle_relayed_transactions_test.go rename to app/protocol/flows/v4/transactionrelay/handle_relayed_transactions_test.go index 42da627747..33f6d0a069 100644 --- a/app/protocol/flows/v3/transactionrelay/handle_relayed_transactions_test.go +++ b/app/protocol/flows/v4/transactionrelay/handle_relayed_transactions_test.go @@ -3,10 +3,10 @@ package transactionrelay_test import ( "errors" "github.com/kaspanet/kaspad/app/protocol/flowcontext" + "github.com/kaspanet/kaspad/app/protocol/flows/v4/transactionrelay" "strings" "testing" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/transactionrelay" "github.com/kaspanet/kaspad/app/protocol/protocolerrors" "github.com/kaspanet/kaspad/domain" "github.com/kaspanet/kaspad/domain/consensus" diff --git a/app/protocol/flows/v3/transactionrelay/handle_requested_transactions.go b/app/protocol/flows/v4/transactionrelay/handle_requested_transactions.go similarity index 100% rename from app/protocol/flows/v3/transactionrelay/handle_requested_transactions.go rename to app/protocol/flows/v4/transactionrelay/handle_requested_transactions.go diff --git a/app/protocol/flows/v3/transactionrelay/handle_requested_transactions_test.go b/app/protocol/flows/v4/transactionrelay/handle_requested_transactions_test.go similarity index 98% rename from app/protocol/flows/v3/transactionrelay/handle_requested_transactions_test.go rename to app/protocol/flows/v4/transactionrelay/handle_requested_transactions_test.go index af66d3cc59..13ab42c36a 100644 --- a/app/protocol/flows/v3/transactionrelay/handle_requested_transactions_test.go +++ b/app/protocol/flows/v4/transactionrelay/handle_requested_transactions_test.go @@ -2,10 +2,10 @@ package transactionrelay_test import ( "github.com/kaspanet/kaspad/app/protocol/flowcontext" + "github.com/kaspanet/kaspad/app/protocol/flows/v4/transactionrelay" "testing" "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/transactionrelay" "github.com/kaspanet/kaspad/domain" "github.com/kaspanet/kaspad/domain/consensus" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" diff --git a/app/protocol/protocol.go b/app/protocol/protocol.go index cb567a27bf..c827e84de0 100644 --- a/app/protocol/protocol.go +++ b/app/protocol/protocol.go @@ -3,8 +3,6 @@ package protocol import ( "github.com/kaspanet/kaspad/app/protocol/common" "github.com/kaspanet/kaspad/app/protocol/flows/ready" - v3 "github.com/kaspanet/kaspad/app/protocol/flows/v3" - "github.com/kaspanet/kaspad/app/protocol/flows/v3/addressexchange" v4 "github.com/kaspanet/kaspad/app/protocol/flows/v4" "sync" "sync/atomic" @@ -55,14 +53,6 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net } }) - // TODO: This code was moved here to prevent a race condition when connecting to v3 peers. This should be moved to v4.registerAddressFlows - // once v3 is obsolete. - sendAddressesFlow := m.RegisterFlow("SendAddresses", router, []appmessage.MessageCommand{appmessage.CmdRequestAddresses}, &isStopping, errChan, - func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error { - return addressexchange.SendAddresses(m.Context(), incomingRoute, router.OutgoingRoute()) - }, - ) - peer, err := handshake.HandleHandshake(m.context, netConnection, receiveVersionRoute, sendVersionRoute, router.OutgoingRoute()) @@ -86,21 +76,16 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net var flows []*common.Flow log.Infof("Registering p2p flows for peer %s for protocol version %d", peer, peer.ProtocolVersion()) switch peer.ProtocolVersion() { - case 3: - flows = v3.Register(m, router, errChan, &isStopping) case 4: flows = v4.Register(m, router, errChan, &isStopping) default: panic(errors.Errorf("no way to handle protocol version %d", peer.ProtocolVersion())) } - flows = append(flows, sendAddressesFlow) - if peer.ProtocolVersion() > 3 { - err = ready.HandleReady(receiveReadyRoute, router.OutgoingRoute(), peer) - if err != nil { - m.handleError(err, netConnection, router.OutgoingRoute()) - return - } + err = ready.HandleReady(receiveReadyRoute, router.OutgoingRoute(), peer) + if err != nil { + m.handleError(err, netConnection, router.OutgoingRoute()) + return } removeHandshakeRoutes(router) diff --git a/app/rpc/rpc.go b/app/rpc/rpc.go index 3bd78af3fa..f4f7da3bd2 100644 --- a/app/rpc/rpc.go +++ b/app/rpc/rpc.go @@ -38,6 +38,7 @@ var handlers = map[appmessage.MessageCommand]handler{ appmessage.CmdNotifyUTXOsChangedRequestMessage: rpchandlers.HandleNotifyUTXOsChanged, appmessage.CmdStopNotifyingUTXOsChangedRequestMessage: rpchandlers.HandleStopNotifyingUTXOsChanged, appmessage.CmdGetUTXOsByAddressesRequestMessage: rpchandlers.HandleGetUTXOsByAddresses, + appmessage.CmdGetBalancesByAddressesRequestMessage: rpchandlers.HandleGetBalancesByAddresses, appmessage.CmdGetVirtualSelectedParentBlueScoreRequestMessage: rpchandlers.HandleGetVirtualSelectedParentBlueScore, appmessage.CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: rpchandlers.HandleNotifyVirtualSelectedParentBlueScoreChanged, appmessage.CmdBanRequestMessage: rpchandlers.HandleBan, diff --git a/app/rpc/rpchandlers/get_balance_by_address.go b/app/rpc/rpchandlers/get_balance_by_address.go index 67f2959607..ace958132d 100644 --- a/app/rpc/rpchandlers/get_balance_by_address.go +++ b/app/rpc/rpchandlers/get_balance_by_address.go @@ -6,6 +6,7 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/utils/txscript" "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" "github.com/kaspanet/kaspad/util" + "github.com/pkg/errors" ) // HandleGetBalanceByAddress handles the respectively named RPC command @@ -18,30 +19,39 @@ func HandleGetBalanceByAddress(context *rpccontext.Context, _ *router.Router, re getBalanceByAddressRequest := request.(*appmessage.GetBalanceByAddressRequestMessage) - var balance uint64 = 0 - addressString := getBalanceByAddressRequest.Address - - address, err := util.DecodeAddress(addressString, context.Config.ActiveNetParams.Prefix) + balance, err := getBalanceByAddress(context, getBalanceByAddressRequest.Address) if err != nil { + rpcError := &appmessage.RPCError{} + if !errors.As(err, rpcError) { + return nil, err + } errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{} - errorMessage.Error = appmessage.RPCErrorf("Could decode address '%s': %s", addressString, err) + errorMessage.Error = rpcError return errorMessage, nil } + response := appmessage.NewGetBalanceByAddressResponse(balance) + return response, nil +} + +func getBalanceByAddress(context *rpccontext.Context, addressString string) (uint64, error) { + address, err := util.DecodeAddress(addressString, context.Config.ActiveNetParams.Prefix) + if err != nil { + return 0, appmessage.RPCErrorf("Couldn't decode address '%s': %s", addressString, err) + } + scriptPublicKey, err := txscript.PayToAddrScript(address) if err != nil { - errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{} - errorMessage.Error = appmessage.RPCErrorf("Could not create a scriptPublicKey for address '%s': %s", addressString, err) - return errorMessage, nil + return 0, appmessage.RPCErrorf("Could not create a scriptPublicKey for address '%s': %s", addressString, err) } utxoOutpointEntryPairs, err := context.UTXOIndex.UTXOs(scriptPublicKey) if err != nil { - return nil, err + return 0, err } + + balance := uint64(0) for _, utxoOutpointEntryPair := range utxoOutpointEntryPairs { balance += utxoOutpointEntryPair.Amount() } - - response := appmessage.NewGetBalanceByAddressResponse(balance) - return response, nil + return balance, nil } diff --git a/app/rpc/rpchandlers/get_balances_by_addresses.go b/app/rpc/rpchandlers/get_balances_by_addresses.go new file mode 100644 index 0000000000..27e37ecfdb --- /dev/null +++ b/app/rpc/rpchandlers/get_balances_by_addresses.go @@ -0,0 +1,41 @@ +package rpchandlers + +import ( + "github.com/kaspanet/kaspad/app/appmessage" + "github.com/kaspanet/kaspad/app/rpc/rpccontext" + "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" + "github.com/pkg/errors" +) + +// HandleGetBalancesByAddresses handles the respectively named RPC command +func HandleGetBalancesByAddresses(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) { + if !context.Config.UTXOIndex { + errorMessage := &appmessage.GetBalancesByAddressesResponseMessage{} + errorMessage.Error = appmessage.RPCErrorf("Method unavailable when kaspad is run without --utxoindex") + return errorMessage, nil + } + + getBalancesByAddressesRequest := request.(*appmessage.GetBalancesByAddressesRequestMessage) + + allEntries := make([]*appmessage.BalancesByAddressesEntry, len(getBalancesByAddressesRequest.Addresses)) + for i, address := range getBalancesByAddressesRequest.Addresses { + balance, err := getBalanceByAddress(context, address) + + if err != nil { + rpcError := &appmessage.RPCError{} + if !errors.As(err, rpcError) { + return nil, err + } + errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{} + errorMessage.Error = rpcError + return errorMessage, nil + } + allEntries[i] = &appmessage.BalancesByAddressesEntry{ + Address: address, + Balance: balance, + } + } + + response := appmessage.NewGetBalancesByAddressesResponse(allEntries) + return response, nil +} diff --git a/cmd/kaspactl/config.go b/cmd/kaspactl/config.go index 7053d4573f..c37f8874b6 100644 --- a/cmd/kaspactl/config.go +++ b/cmd/kaspactl/config.go @@ -12,11 +12,12 @@ var ( ) type configFlags struct { - RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"` - Timeout uint64 `short:"t" long:"timeout" description:"Timeout for the request (in seconds)"` - RequestJSON string `short:"j" long:"json" description:"The request in JSON format"` - ListCommands bool `short:"l" long:"list-commands" description:"List all commands and exit"` - CommandAndParameters []string + RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"` + Timeout uint64 `short:"t" long:"timeout" description:"Timeout for the request (in seconds)"` + RequestJSON string `short:"j" long:"json" description:"The request in JSON format"` + ListCommands bool `short:"l" long:"list-commands" description:"List all commands and exit"` + AllowConnectionToDifferentVersions bool `short:"a" long:"allow-connection-to-different-versions" description:"Allow connections to versions different than kaspactl's version'"` + CommandAndParameters []string config.NetworkFlags } diff --git a/cmd/kaspactl/main.go b/cmd/kaspactl/main.go index c69db51bca..df01b794da 100644 --- a/cmd/kaspactl/main.go +++ b/cmd/kaspactl/main.go @@ -34,16 +34,18 @@ func main() { } defer client.Disconnect() - kaspadMessage, err := client.Post(&protowire.KaspadMessage{Payload: &protowire.KaspadMessage_GetInfoRequest{GetInfoRequest: &protowire.GetInfoRequestMessage{}}}) - if err != nil { - printErrorAndExit(fmt.Sprintf("Cannot post GetInfo message: %s", err)) - } - - localVersion := version.Version() - remoteVersion := kaspadMessage.GetGetInfoResponse().ServerVersion - - if localVersion != remoteVersion { - printErrorAndExit(fmt.Sprintf("Server version mismatch, expect: %s, got: %s", localVersion, remoteVersion)) + if !cfg.AllowConnectionToDifferentVersions { + kaspadMessage, err := client.Post(&protowire.KaspadMessage{Payload: &protowire.KaspadMessage_GetInfoRequest{GetInfoRequest: &protowire.GetInfoRequestMessage{}}}) + if err != nil { + printErrorAndExit(fmt.Sprintf("Cannot post GetInfo message: %s", err)) + } + + localVersion := version.Version() + remoteVersion := kaspadMessage.GetGetInfoResponse().ServerVersion + + if localVersion != remoteVersion { + printErrorAndExit(fmt.Sprintf("Server version mismatch, expect: %s, got: %s", localVersion, remoteVersion)) + } } responseChan := make(chan string) diff --git a/cmd/kaspawallet/daemon/server/balance.go b/cmd/kaspawallet/daemon/server/balance.go index 608d9b8542..5ba109c977 100644 --- a/cmd/kaspawallet/daemon/server/balance.go +++ b/cmd/kaspawallet/daemon/server/balance.go @@ -2,6 +2,7 @@ package server import ( "context" + "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb" "github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet" ) @@ -21,7 +22,7 @@ func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.Get maturity := s.params.BlockCoinbaseMaturity balancesMap := make(balancesMapType, 0) - for _, entry := range s.utxos { + for _, entry := range s.utxosSortedByAmount { amount := entry.UTXOEntry.Amount() address := entry.address balances, ok := balancesMap[address] diff --git a/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go b/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go index da1377fdbe..68e6364ef6 100644 --- a/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go +++ b/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go @@ -2,6 +2,7 @@ package server import ( "context" + "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb" "github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet" "github.com/kaspanet/kaspad/domain/consensus/utils/constants" @@ -17,7 +18,7 @@ func (s *server) CreateUnsignedTransaction(_ context.Context, request *pb.Create return nil, errors.New("server is not synced") } - err := s.refreshExistingUTXOs() + err := s.refreshUTXOs() if err != nil { return nil, err } @@ -66,7 +67,7 @@ func (s *server) selectUTXOs(spendAmount uint64, feePerInput uint64) ( return nil, 0, err } - for _, utxo := range s.utxos { + for _, utxo := range s.utxosSortedByAmount { if !isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, s.params.BlockCoinbaseMaturity) { continue } diff --git a/cmd/kaspawallet/daemon/server/server.go b/cmd/kaspawallet/daemon/server/server.go index dc5f4efc92..d9fe254624 100644 --- a/cmd/kaspawallet/daemon/server/server.go +++ b/cmd/kaspawallet/daemon/server/server.go @@ -2,15 +2,15 @@ package server import ( "fmt" - "github.com/kaspanet/kaspad/util/profiling" "net" "os" "sync" "time" + "github.com/kaspanet/kaspad/util/profiling" + "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb" "github.com/kaspanet/kaspad/cmd/kaspawallet/keys" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/dagconfig" "github.com/kaspanet/kaspad/infrastructure/network/rpcclient" "github.com/kaspanet/kaspad/infrastructure/os/signal" @@ -26,11 +26,12 @@ type server struct { rpcClient *rpcclient.RPCClient params *dagconfig.Params - lock sync.RWMutex - utxos map[externalapi.DomainOutpoint]*walletUTXO - nextSyncStartIndex uint32 - keysFile *keys.File - shutdown chan struct{} + lock sync.RWMutex + utxosSortedByAmount []*walletUTXO + nextSyncStartIndex uint32 + keysFile *keys.File + shutdown chan struct{} + addressSet walletAddressSet } // Start starts the kaspawalletd server @@ -61,12 +62,13 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri } serverInstance := &server{ - rpcClient: rpcClient, - params: params, - utxos: make(map[externalapi.DomainOutpoint]*walletUTXO), - nextSyncStartIndex: 0, - keysFile: keysFile, - shutdown: make(chan struct{}), + rpcClient: rpcClient, + params: params, + utxosSortedByAmount: []*walletUTXO{}, + nextSyncStartIndex: 0, + keysFile: keysFile, + shutdown: make(chan struct{}), + addressSet: make(walletAddressSet), } spawn("serverInstance.sync", func() { diff --git a/cmd/kaspawallet/daemon/server/sync.go b/cmd/kaspawallet/daemon/server/sync.go index 03a4dd1120..00fdef1cc3 100644 --- a/cmd/kaspawallet/daemon/server/sync.go +++ b/cmd/kaspawallet/daemon/server/sync.go @@ -1,12 +1,12 @@ package server import ( + "sort" "time" "github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet" "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/pkg/errors" ) @@ -27,17 +27,18 @@ func (s *server) sync() error { defer ticker.Stop() for range ticker.C { - err := s.collectUTXOsFromRecentAddresses() + err := s.collectRecentAddresses() if err != nil { return err } - err = s.collectUTXOsFromFarAddresses() + err = s.collectFarAddresses() if err != nil { return err } err = s.refreshExistingUTXOsWithLock() + if err != nil { return err } @@ -74,12 +75,12 @@ func (s *server) addressesToQuery(start, end uint32) (walletAddressSet, error) { return addresses, nil } -// collectUTXOsFromFarAddresses collects numIndexesToQuery UTXOs +// collectFarAddresses collects numIndexesToQuery addresses // from the last point it stopped in the previous call. -func (s *server) collectUTXOsFromFarAddresses() error { +func (s *server) collectFarAddresses() error { s.lock.Lock() defer s.lock.Unlock() - err := s.collectUTXOs(s.nextSyncStartIndex, s.nextSyncStartIndex+numIndexesToQuery) + err := s.collectAddresses(s.nextSyncStartIndex, s.nextSyncStartIndex+numIndexesToQuery) if err != nil { return err } @@ -100,14 +101,14 @@ func (s *server) maxUsedIndex() uint32 { return maxUsedIndex } -// collectUTXOsFromRecentAddresses collects UTXOs from used addresses until +// collectRecentAddresses collects addresses from used addresses until // the address with the index of the last used address + 1000. -// collectUTXOsFromRecentAddresses scans addresses in batches of numIndexesToQuery, +// collectRecentAddresses scans addresses in batches of numIndexesToQuery, // and releases the lock between scans. -func (s *server) collectUTXOsFromRecentAddresses() error { +func (s *server) collectRecentAddresses() error { maxUsedIndex := s.maxUsedIndex() for i := uint32(0); i < maxUsedIndex+1000; i += numIndexesToQuery { - err := s.collectUTXOsWithLock(i, i+numIndexesToQuery) + err := s.collectAddressesWithLock(i, i+numIndexesToQuery) if err != nil { return err } @@ -116,30 +117,25 @@ func (s *server) collectUTXOsFromRecentAddresses() error { return nil } -func (s *server) collectUTXOsWithLock(start, end uint32) error { +func (s *server) collectAddressesWithLock(start, end uint32) error { s.lock.Lock() defer s.lock.Unlock() - return s.collectUTXOs(start, end) + return s.collectAddresses(start, end) } -func (s *server) collectUTXOs(start, end uint32) error { +func (s *server) collectAddresses(start, end uint32) error { addressSet, err := s.addressesToQuery(start, end) if err != nil { return err } - getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(addressSet.strings()) - if err != nil { - return err - } - - err = s.updateLastUsedIndexes(addressSet, getUTXOsByAddressesResponse) + getBalancesByAddressesResponse, err := s.rpcClient.GetBalancesByAddresses(addressSet.strings()) if err != nil { return err } - err = s.updateUTXOs(addressSet, getUTXOsByAddressesResponse) + err = s.updateAddressesAndLastUsedIndexes(addressSet, getBalancesByAddressesResponse) if err != nil { return err } @@ -147,35 +143,28 @@ func (s *server) collectUTXOs(start, end uint32) error { return nil } -func (s *server) updateUTXOs(addressSet walletAddressSet, - getUTXOsByAddressesResponse *appmessage.GetUTXOsByAddressesResponseMessage) error { - - for _, entry := range getUTXOsByAddressesResponse.Entries { - err := s.addEntryToUTXOSet(entry, addressSet) - if err != nil { - return err - } - } - - return nil -} - -func (s *server) updateLastUsedIndexes(addressSet walletAddressSet, - getUTXOsByAddressesResponse *appmessage.GetUTXOsByAddressesResponseMessage) error { +func (s *server) updateAddressesAndLastUsedIndexes(requestedAddressSet walletAddressSet, + getBalancesByAddressesResponse *appmessage.GetBalancesByAddressesResponseMessage) error { lastUsedExternalIndex := s.keysFile.LastUsedExternalIndex() lastUsedInternalIndex := s.keysFile.LastUsedInternalIndex() - for _, entry := range getUTXOsByAddressesResponse.Entries { - walletAddress, ok := addressSet[entry.Address] + for _, entry := range getBalancesByAddressesResponse.Entries { + walletAddress, ok := requestedAddressSet[entry.Address] if !ok { return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address) } + if entry.Balance == 0 { + continue + } + if walletAddress.cosignerIndex != s.keysFile.CosignerIndex { continue } + s.addressSet[entry.Address] = walletAddress + if walletAddress.keyChain == libkaspawallet.ExternalKeychain { if walletAddress.index > lastUsedExternalIndex { lastUsedExternalIndex = walletAddress.index @@ -200,58 +189,49 @@ func (s *server) refreshExistingUTXOsWithLock() error { s.lock.Lock() defer s.lock.Unlock() - return s.refreshExistingUTXOs() + return s.refreshUTXOs() } -func (s *server) addEntryToUTXOSet(entry *appmessage.UTXOsByAddressesEntry, addressSet walletAddressSet) error { - outpoint, err := appmessage.RPCOutpointToDomainOutpoint(entry.Outpoint) - if err != nil { - return err - } - - utxoEntry, err := appmessage.RPCUTXOEntryToUTXOEntry(entry.UTXOEntry) - if err != nil { - return err - } - - address, ok := addressSet[entry.Address] - if !ok { - return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address) - } - - s.utxos[*outpoint] = &walletUTXO{ - Outpoint: outpoint, - UTXOEntry: utxoEntry, - address: address, - } +// updateUTXOSet clears the current UTXO set, and re-fills it with the given entries +func (s *server) updateUTXOSet(entries []*appmessage.UTXOsByAddressesEntry) error { + utxos := make([]*walletUTXO, len(entries)) - return nil -} + for i, entry := range entries { + outpoint, err := appmessage.RPCOutpointToDomainOutpoint(entry.Outpoint) + if err != nil { + return err + } -func (s *server) refreshExistingUTXOs() error { - addressSet := make(walletAddressSet, len(s.utxos)) - for _, utxo := range s.utxos { - addressString, err := s.walletAddressString(utxo.address) + utxoEntry, err := appmessage.RPCUTXOEntryToUTXOEntry(entry.UTXOEntry) if err != nil { return err } - addressSet[addressString] = utxo.address + address, ok := s.addressSet[entry.Address] + if !ok { + return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address) + } + utxos[i] = &walletUTXO{ + Outpoint: outpoint, + UTXOEntry: utxoEntry, + address: address, + } } - getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(addressSet.strings()) + sort.Slice(utxos, func(i, j int) bool { return utxos[i].UTXOEntry.Amount() > utxos[j].UTXOEntry.Amount() }) + + s.utxosSortedByAmount = utxos + + return nil +} + +func (s *server) refreshUTXOs() error { + getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(s.addressSet.strings()) if err != nil { return err } - s.utxos = make(map[externalapi.DomainOutpoint]*walletUTXO, len(getUTXOsByAddressesResponse.Entries)) - for _, entry := range getUTXOsByAddressesResponse.Entries { - err := s.addEntryToUTXOSet(entry, addressSet) - if err != nil { - return err - } - } - return nil + return s.updateUTXOSet(getUTXOsByAddressesResponse.Entries) } func (s *server) isSynced() bool { diff --git a/domain/consensus/consensus.go b/domain/consensus/consensus.go index 18a9c732d2..79f01d0ed3 100644 --- a/domain/consensus/consensus.go +++ b/domain/consensus/consensus.go @@ -190,7 +190,12 @@ func (s *consensus) ValidateTransactionAndPopulateWithConsensusData(transaction return err } - err = s.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, transaction, model.VirtualBlockHash) + virtualPastMedianTime, err := s.pastMedianTimeManager.PastMedianTime(stagingArea, model.VirtualBlockHash) + if err != nil { + return err + } + + err = s.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, transaction, model.VirtualBlockHash, virtualPastMedianTime) if err != nil { return err } @@ -741,24 +746,27 @@ func (s *consensus) ValidatePruningPointProof(pruningPointProof *externalapi.Pru s.lock.Lock() defer s.lock.Unlock() - return s.pruningProofManager.ValidatePruningPointProof(pruningPointProof) + log.Infof("Validating the pruning point proof") + err := s.pruningProofManager.ValidatePruningPointProof(pruningPointProof) + if err != nil { + return err + } + + log.Infof("Done validating the pruning point proof") + return nil } func (s *consensus) ApplyPruningPointProof(pruningPointProof *externalapi.PruningPointProof) error { s.lock.Lock() defer s.lock.Unlock() - stagingArea := model.NewStagingArea() - err := s.pruningProofManager.ApplyPruningPointProof(stagingArea, pruningPointProof) - if err != nil { - return err - } - - err = staging.CommitAllChanges(s.databaseContext, stagingArea) + log.Infof("Applying the pruning point proof") + err := s.pruningProofManager.ApplyPruningPointProof(pruningPointProof) if err != nil { return err } + log.Infof("Done applying the pruning point proof") return nil } diff --git a/domain/consensus/model/interface_processes_pruningproofmanager.go b/domain/consensus/model/interface_processes_pruningproofmanager.go index c8ada22a4b..de876c6db5 100644 --- a/domain/consensus/model/interface_processes_pruningproofmanager.go +++ b/domain/consensus/model/interface_processes_pruningproofmanager.go @@ -6,5 +6,5 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" type PruningProofManager interface { BuildPruningPointProof(stagingArea *StagingArea) (*externalapi.PruningPointProof, error) ValidatePruningPointProof(pruningPointProof *externalapi.PruningPointProof) error - ApplyPruningPointProof(stagingArea *StagingArea, pruningPointProof *externalapi.PruningPointProof) error + ApplyPruningPointProof(pruningPointProof *externalapi.PruningPointProof) error } diff --git a/domain/consensus/model/interface_processes_transactionvalidator.go b/domain/consensus/model/interface_processes_transactionvalidator.go index 679bf157ed..a7c8d9adda 100644 --- a/domain/consensus/model/interface_processes_transactionvalidator.go +++ b/domain/consensus/model/interface_processes_transactionvalidator.go @@ -9,7 +9,7 @@ import ( type TransactionValidator interface { ValidateTransactionInIsolation(transaction *externalapi.DomainTransaction) error ValidateTransactionInContextIgnoringUTXO(stagingArea *StagingArea, tx *externalapi.DomainTransaction, - povBlockHash *externalapi.DomainHash) error + povBlockHash *externalapi.DomainHash, povBlockPastMedianTime int64) error ValidateTransactionInContextAndPopulateFee(stagingArea *StagingArea, tx *externalapi.DomainTransaction, povBlockHash *externalapi.DomainHash) error PopulateMass(transaction *externalapi.DomainTransaction) diff --git a/domain/consensus/processes/blockbuilder/block_builder.go b/domain/consensus/processes/blockbuilder/block_builder.go index 041454abb0..fa31b1dfda 100644 --- a/domain/consensus/processes/blockbuilder/block_builder.go +++ b/domain/consensus/processes/blockbuilder/block_builder.go @@ -166,7 +166,12 @@ func (bb *blockBuilder) validateTransaction( return err } - err = bb.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, transaction, model.VirtualBlockHash) + virtualPastMedianTime, err := bb.pastMedianTimeManager.PastMedianTime(stagingArea, model.VirtualBlockHash) + if err != nil { + return err + } + + err = bb.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, transaction, model.VirtualBlockHash, virtualPastMedianTime) if err != nil { return err } diff --git a/domain/consensus/processes/blockvalidator/block_body_in_context.go b/domain/consensus/processes/blockvalidator/block_body_in_context.go index a652c8d870..f032fd96fd 100644 --- a/domain/consensus/processes/blockvalidator/block_body_in_context.go +++ b/domain/consensus/processes/blockvalidator/block_body_in_context.go @@ -136,8 +136,12 @@ func (v *blockValidator) checkBlockTransactions( } // Ensure all transactions in the block are finalized. + pastMedianTime, err := v.pastMedianTimeManager.PastMedianTime(stagingArea, blockHash) + if err != nil { + return err + } for _, tx := range block.Transactions { - if err = v.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, tx, blockHash); err != nil { + if err = v.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, tx, blockHash, pastMedianTime); err != nil { return err } } diff --git a/domain/consensus/processes/pruningproofmanager/pruningproofmanager.go b/domain/consensus/processes/pruningproofmanager/pruningproofmanager.go index 214a7ce02a..589bb5e884 100644 --- a/domain/consensus/processes/pruningproofmanager/pruningproofmanager.go +++ b/domain/consensus/processes/pruningproofmanager/pruningproofmanager.go @@ -17,6 +17,7 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/utils/hashset" "github.com/kaspanet/kaspad/infrastructure/db/database" "github.com/kaspanet/kaspad/infrastructure/logger" + "github.com/kaspanet/kaspad/util/staging" "github.com/pkg/errors" "math/big" ) @@ -346,6 +347,7 @@ func (ppm *pruningProofManager) ValidatePruningPointProof(pruningPointProof *ext selectedTipByLevel := make([]*externalapi.DomainHash, maxLevel+1) for blockLevel := maxLevel; blockLevel >= 0; blockLevel-- { + log.Infof("Validating level %d from the pruning point proof", blockLevel) headers := make([]externalapi.BlockHeader, len(pruningPointProof.Headers[blockLevel])) copy(headers, pruningPointProof.Headers[blockLevel]) @@ -607,13 +609,23 @@ func (ppm *pruningProofManager) dagProcesses( return reachabilityManagers, dagTopologyManagers, ghostdagManagers } -func (ppm *pruningProofManager) ApplyPruningPointProof(stagingArea *model.StagingArea, pruningPointProof *externalapi.PruningPointProof) error { +// ApplyPruningPointProof applies the given pruning proof to the current consensus. Specifically, +// it's meant to be used against the StagingConsensus during headers-proof IBD. Note that for +// performance reasons this operation is NOT atomic. If the process fails for whatever reason +// (e.g. the process was killed) then the database for this consensus MUST be discarded. +func (ppm *pruningProofManager) ApplyPruningPointProof(pruningPointProof *externalapi.PruningPointProof) error { onEnd := logger.LogAndMeasureExecutionTime(log, "ApplyPruningPointProof") defer onEnd() for blockLevel, headers := range pruningPointProof.Headers { + log.Infof("Applying level %d from the pruning point proof", blockLevel) var selectedTip *externalapi.DomainHash for i, header := range headers { + if i%1000 == 0 { + log.Infof("Applying level %d from the pruning point proof - applied %d headers out of %d", blockLevel, i, len(headers)) + } + stagingArea := model.NewStagingArea() + blockHash := consensushashing.HeaderHash(header) if header.BlockLevel() < blockLevel { return errors.Wrapf(ruleerrors.ErrPruningProofWrongBlockLevel, "block %s level is %d when it's "+ @@ -693,11 +705,18 @@ func (ppm *pruningProofManager) ApplyPruningPointProof(stagingArea *model.Stagin return err } } + + err = staging.CommitAllChanges(ppm.databaseContext, stagingArea) + if err != nil { + return err + } } } pruningPointHeader := pruningPointProof.Headers[0][len(pruningPointProof.Headers[0])-1] pruningPoint := consensushashing.HeaderHash(pruningPointHeader) + + stagingArea := model.NewStagingArea() ppm.consensusStateStore.StageTips(stagingArea, []*externalapi.DomainHash{pruningPoint}) - return nil + return staging.CommitAllChanges(ppm.databaseContext, stagingArea) } diff --git a/domain/consensus/processes/transactionvalidator/transaction_in_context.go b/domain/consensus/processes/transactionvalidator/transaction_in_context.go index ba9ee2b6db..6b4df117aa 100644 --- a/domain/consensus/processes/transactionvalidator/transaction_in_context.go +++ b/domain/consensus/processes/transactionvalidator/transaction_in_context.go @@ -48,16 +48,12 @@ func (v *transactionValidator) IsFinalizedTransaction(tx *externalapi.DomainTran // ValidateTransactionInContextIgnoringUTXO validates the transaction with consensus context but ignoring UTXO func (v *transactionValidator) ValidateTransactionInContextIgnoringUTXO(stagingArea *model.StagingArea, tx *externalapi.DomainTransaction, - povBlockHash *externalapi.DomainHash) error { + povBlockHash *externalapi.DomainHash, povBlockPastMedianTime int64) error { povBlockDAAScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, stagingArea, povBlockHash) if err != nil { return err } - povBlockPastMedianTime, err := v.pastMedianTimeManager.PastMedianTime(stagingArea, povBlockHash) - if err != nil { - return err - } if isFinalized := v.IsFinalizedTransaction(tx, povBlockDAAScore, povBlockPastMedianTime); !isFinalized { return errors.Wrapf(ruleerrors.ErrUnfinalizedTx, "unfinalized transaction %v", tx) } diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/messages.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/messages.pb.go index 416a04f183..6305e555f9 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/messages.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/messages.pb.go @@ -1,13 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 +// protoc-gen-go v1.26.0 // protoc v3.12.3 // source: messages.proto package protowire import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -21,10 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - type KaspadMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -148,6 +143,8 @@ type KaspadMessage struct { // *KaspadMessage_VirtualDaaScoreChangedNotification // *KaspadMessage_GetBalanceByAddressRequest // *KaspadMessage_GetBalanceByAddressResponse + // *KaspadMessage_GetBalancesByAddressesRequest + // *KaspadMessage_GetBalancesByAddressesResponse Payload isKaspadMessage_Payload `protobuf_oneof:"payload"` } @@ -1009,6 +1006,20 @@ func (x *KaspadMessage) GetGetBalanceByAddressResponse() *GetBalanceByAddressRes return nil } +func (x *KaspadMessage) GetGetBalancesByAddressesRequest() *GetBalancesByAddressesRequestMessage { + if x, ok := x.GetPayload().(*KaspadMessage_GetBalancesByAddressesRequest); ok { + return x.GetBalancesByAddressesRequest + } + return nil +} + +func (x *KaspadMessage) GetGetBalancesByAddressesResponse() *GetBalancesByAddressesResponseMessage { + if x, ok := x.GetPayload().(*KaspadMessage_GetBalancesByAddressesResponse); ok { + return x.GetBalancesByAddressesResponse + } + return nil +} + type isKaspadMessage_Payload interface { isKaspadMessage_Payload() } @@ -1481,6 +1492,14 @@ type KaspadMessage_GetBalanceByAddressResponse struct { GetBalanceByAddressResponse *GetBalanceByAddressResponseMessage `protobuf:"bytes,1078,opt,name=getBalanceByAddressResponse,proto3,oneof"` } +type KaspadMessage_GetBalancesByAddressesRequest struct { + GetBalancesByAddressesRequest *GetBalancesByAddressesRequestMessage `protobuf:"bytes,1079,opt,name=getBalancesByAddressesRequest,proto3,oneof"` +} + +type KaspadMessage_GetBalancesByAddressesResponse struct { + GetBalancesByAddressesResponse *GetBalancesByAddressesResponseMessage `protobuf:"bytes,1080,opt,name=getBalancesByAddressesResponse,proto3,oneof"` +} + func (*KaspadMessage_Addresses) isKaspadMessage_Payload() {} func (*KaspadMessage_Block) isKaspadMessage_Payload() {} @@ -1715,13 +1734,17 @@ func (*KaspadMessage_GetBalanceByAddressRequest) isKaspadMessage_Payload() {} func (*KaspadMessage_GetBalanceByAddressResponse) isKaspadMessage_Payload() {} +func (*KaspadMessage_GetBalancesByAddressesRequest) isKaspadMessage_Payload() {} + +func (*KaspadMessage_GetBalancesByAddressesResponse) isKaspadMessage_Payload() {} + var File_messages_proto protoreflect.FileDescriptor var file_messages_proto_rawDesc = []byte{ 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x1a, 0x09, 0x70, 0x32, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x09, 0x72, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xb8, 0x61, 0x0a, 0x0d, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, + 0x6f, 0x22, 0xaf, 0x63, 0x0a, 0x0d, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x4d, 0x65, 0x73, 0x73, @@ -2500,20 +2523,36 @@ var file_messages_proto_rawDesc = []byte{ 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x1b, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x32, 0x50, 0x0a, 0x03, - 0x50, 0x32, 0x50, 0x12, 0x49, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, - 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x32, 0x50, - 0x0a, 0x03, 0x52, 0x50, 0x43, 0x12, 0x49, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, - 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, - 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, - 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x12, 0x78, 0x0a, 0x1d, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0xb7, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x1d, 0x67, 0x65, + 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x7b, 0x0a, 0x1e, 0x67, + 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0xb8, 0x08, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x1e, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x32, 0x50, 0x0a, 0x03, 0x50, 0x32, 0x50, 0x12, 0x49, 0x0a, 0x0d, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, + 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x00, 0x28, 0x01, 0x30, 0x01, 0x32, 0x50, 0x0a, 0x03, 0x52, 0x50, 0x43, 0x12, 0x49, 0x0a, 0x0d, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, + 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, + 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2647,6 +2686,8 @@ var file_messages_proto_goTypes = []interface{}{ (*VirtualDaaScoreChangedNotificationMessage)(nil), // 114: protowire.VirtualDaaScoreChangedNotificationMessage (*GetBalanceByAddressRequestMessage)(nil), // 115: protowire.GetBalanceByAddressRequestMessage (*GetBalanceByAddressResponseMessage)(nil), // 116: protowire.GetBalanceByAddressResponseMessage + (*GetBalancesByAddressesRequestMessage)(nil), // 117: protowire.GetBalancesByAddressesRequestMessage + (*GetBalancesByAddressesResponseMessage)(nil), // 118: protowire.GetBalancesByAddressesResponseMessage } var file_messages_proto_depIdxs = []int32{ 1, // 0: protowire.KaspadMessage.addresses:type_name -> protowire.AddressesMessage @@ -2766,15 +2807,17 @@ var file_messages_proto_depIdxs = []int32{ 114, // 114: protowire.KaspadMessage.virtualDaaScoreChangedNotification:type_name -> protowire.VirtualDaaScoreChangedNotificationMessage 115, // 115: protowire.KaspadMessage.getBalanceByAddressRequest:type_name -> protowire.GetBalanceByAddressRequestMessage 116, // 116: protowire.KaspadMessage.getBalanceByAddressResponse:type_name -> protowire.GetBalanceByAddressResponseMessage - 0, // 117: protowire.P2P.MessageStream:input_type -> protowire.KaspadMessage - 0, // 118: protowire.RPC.MessageStream:input_type -> protowire.KaspadMessage - 0, // 119: protowire.P2P.MessageStream:output_type -> protowire.KaspadMessage - 0, // 120: protowire.RPC.MessageStream:output_type -> protowire.KaspadMessage - 119, // [119:121] is the sub-list for method output_type - 117, // [117:119] is the sub-list for method input_type - 117, // [117:117] is the sub-list for extension type_name - 117, // [117:117] is the sub-list for extension extendee - 0, // [0:117] is the sub-list for field type_name + 117, // 117: protowire.KaspadMessage.getBalancesByAddressesRequest:type_name -> protowire.GetBalancesByAddressesRequestMessage + 118, // 118: protowire.KaspadMessage.getBalancesByAddressesResponse:type_name -> protowire.GetBalancesByAddressesResponseMessage + 0, // 119: protowire.P2P.MessageStream:input_type -> protowire.KaspadMessage + 0, // 120: protowire.RPC.MessageStream:input_type -> protowire.KaspadMessage + 0, // 121: protowire.P2P.MessageStream:output_type -> protowire.KaspadMessage + 0, // 122: protowire.RPC.MessageStream:output_type -> protowire.KaspadMessage + 121, // [121:123] is the sub-list for method output_type + 119, // [119:121] is the sub-list for method input_type + 119, // [119:119] is the sub-list for extension type_name + 119, // [119:119] is the sub-list for extension extendee + 0, // [0:119] is the sub-list for field type_name } func init() { file_messages_proto_init() } @@ -2916,6 +2959,8 @@ func file_messages_proto_init() { (*KaspadMessage_VirtualDaaScoreChangedNotification)(nil), (*KaspadMessage_GetBalanceByAddressRequest)(nil), (*KaspadMessage_GetBalanceByAddressResponse)(nil), + (*KaspadMessage_GetBalancesByAddressesRequest)(nil), + (*KaspadMessage_GetBalancesByAddressesResponse)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto b/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto index a960dbb640..8f99f9330a 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto @@ -126,6 +126,8 @@ message KaspadMessage { VirtualDaaScoreChangedNotificationMessage virtualDaaScoreChangedNotification = 1076; GetBalanceByAddressRequestMessage getBalanceByAddressRequest = 1077; GetBalanceByAddressResponseMessage getBalanceByAddressResponse = 1078; + GetBalancesByAddressesRequestMessage getBalancesByAddressesRequest = 1079; + GetBalancesByAddressesResponseMessage getBalancesByAddressesResponse = 1080; } } diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go index 102e61cfdc..09653ed689 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go @@ -11,7 +11,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 // P2PClient is the client API for P2P service. // @@ -29,7 +30,7 @@ func NewP2PClient(cc grpc.ClientConnInterface) P2PClient { } func (c *p2PClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (P2P_MessageStreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_P2P_serviceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...) + stream, err := c.cc.NewStream(ctx, &P2P_ServiceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...) if err != nil { return nil, err } @@ -71,13 +72,20 @@ type P2PServer interface { type UnimplementedP2PServer struct { } -func (*UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error { +func (UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error { return status.Errorf(codes.Unimplemented, "method MessageStream not implemented") } -func (*UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {} +func (UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {} -func RegisterP2PServer(s *grpc.Server, srv P2PServer) { - s.RegisterService(&_P2P_serviceDesc, srv) +// UnsafeP2PServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to P2PServer will +// result in compilation errors. +type UnsafeP2PServer interface { + mustEmbedUnimplementedP2PServer() +} + +func RegisterP2PServer(s grpc.ServiceRegistrar, srv P2PServer) { + s.RegisterService(&P2P_ServiceDesc, srv) } func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error { @@ -106,7 +114,10 @@ func (x *p2PMessageStreamServer) Recv() (*KaspadMessage, error) { return m, nil } -var _P2P_serviceDesc = grpc.ServiceDesc{ +// P2P_ServiceDesc is the grpc.ServiceDesc for P2P service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var P2P_ServiceDesc = grpc.ServiceDesc{ ServiceName: "protowire.P2P", HandlerType: (*P2PServer)(nil), Methods: []grpc.MethodDesc{}, @@ -137,7 +148,7 @@ func NewRPCClient(cc grpc.ClientConnInterface) RPCClient { } func (c *rPCClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (RPC_MessageStreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_RPC_serviceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...) + stream, err := c.cc.NewStream(ctx, &RPC_ServiceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...) if err != nil { return nil, err } @@ -179,13 +190,20 @@ type RPCServer interface { type UnimplementedRPCServer struct { } -func (*UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error { +func (UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error { return status.Errorf(codes.Unimplemented, "method MessageStream not implemented") } -func (*UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {} +func (UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {} + +// UnsafeRPCServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RPCServer will +// result in compilation errors. +type UnsafeRPCServer interface { + mustEmbedUnimplementedRPCServer() +} -func RegisterRPCServer(s *grpc.Server, srv RPCServer) { - s.RegisterService(&_RPC_serviceDesc, srv) +func RegisterRPCServer(s grpc.ServiceRegistrar, srv RPCServer) { + s.RegisterService(&RPC_ServiceDesc, srv) } func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error { @@ -214,7 +232,10 @@ func (x *rPCMessageStreamServer) Recv() (*KaspadMessage, error) { return m, nil } -var _RPC_serviceDesc = grpc.ServiceDesc{ +// RPC_ServiceDesc is the grpc.ServiceDesc for RPC service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var RPC_ServiceDesc = grpc.ServiceDesc{ ServiceName: "protowire.RPC", HandlerType: (*RPCServer)(nil), Methods: []grpc.MethodDesc{}, diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go index 30691c3adb..bb5365e5a4 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go @@ -1,13 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 +// protoc-gen-go v1.26.0 // protoc v3.12.3 // source: p2p.proto package protowire import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -21,10 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - type RequestAddressesMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go index 687bbe400c..e19dd9c366 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go @@ -10,14 +10,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 +// protoc-gen-go v1.26.0 // protoc v3.12.3 // source: rpc.proto package protowire import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -31,10 +30,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - type SubmitBlockResponseMessage_RejectReason int32 const ( @@ -4349,6 +4344,171 @@ func (x *GetBalanceByAddressResponseMessage) GetError() *RPCError { return nil } +type GetBalancesByAddressesRequestMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"` +} + +func (x *GetBalancesByAddressesRequestMessage) Reset() { + *x = GetBalancesByAddressesRequestMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBalancesByAddressesRequestMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBalancesByAddressesRequestMessage) ProtoMessage() {} + +func (x *GetBalancesByAddressesRequestMessage) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[75] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBalancesByAddressesRequestMessage.ProtoReflect.Descriptor instead. +func (*GetBalancesByAddressesRequestMessage) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{75} +} + +func (x *GetBalancesByAddressesRequestMessage) GetAddresses() []string { + if x != nil { + return x.Addresses + } + return nil +} + +type BalancesByAddressEntry struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Balance uint64 `protobuf:"varint,2,opt,name=balance,proto3" json:"balance,omitempty"` + Error *RPCError `protobuf:"bytes,1000,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *BalancesByAddressEntry) Reset() { + *x = BalancesByAddressEntry{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[76] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BalancesByAddressEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BalancesByAddressEntry) ProtoMessage() {} + +func (x *BalancesByAddressEntry) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[76] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BalancesByAddressEntry.ProtoReflect.Descriptor instead. +func (*BalancesByAddressEntry) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{76} +} + +func (x *BalancesByAddressEntry) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *BalancesByAddressEntry) GetBalance() uint64 { + if x != nil { + return x.Balance + } + return 0 +} + +func (x *BalancesByAddressEntry) GetError() *RPCError { + if x != nil { + return x.Error + } + return nil +} + +type GetBalancesByAddressesResponseMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Entries []*BalancesByAddressEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` + Error *RPCError `protobuf:"bytes,1000,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *GetBalancesByAddressesResponseMessage) Reset() { + *x = GetBalancesByAddressesResponseMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBalancesByAddressesResponseMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBalancesByAddressesResponseMessage) ProtoMessage() {} + +func (x *GetBalancesByAddressesResponseMessage) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[77] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBalancesByAddressesResponseMessage.ProtoReflect.Descriptor instead. +func (*GetBalancesByAddressesResponseMessage) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{77} +} + +func (x *GetBalancesByAddressesResponseMessage) GetEntries() []*BalancesByAddressEntry { + if x != nil { + return x.Entries + } + return nil +} + +func (x *GetBalancesByAddressesResponseMessage) GetError() *RPCError { + if x != nil { + return x.Error + } + return nil +} + // GetVirtualSelectedParentBlueScoreRequestMessage requests the blue score of the current selected parent // of the virtual block. type GetVirtualSelectedParentBlueScoreRequestMessage struct { @@ -4360,7 +4520,7 @@ type GetVirtualSelectedParentBlueScoreRequestMessage struct { func (x *GetVirtualSelectedParentBlueScoreRequestMessage) Reset() { *x = GetVirtualSelectedParentBlueScoreRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[75] + mi := &file_rpc_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4373,7 +4533,7 @@ func (x *GetVirtualSelectedParentBlueScoreRequestMessage) String() string { func (*GetVirtualSelectedParentBlueScoreRequestMessage) ProtoMessage() {} func (x *GetVirtualSelectedParentBlueScoreRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[75] + mi := &file_rpc_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4386,7 +4546,7 @@ func (x *GetVirtualSelectedParentBlueScoreRequestMessage) ProtoReflect() protore // Deprecated: Use GetVirtualSelectedParentBlueScoreRequestMessage.ProtoReflect.Descriptor instead. func (*GetVirtualSelectedParentBlueScoreRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{75} + return file_rpc_proto_rawDescGZIP(), []int{78} } type GetVirtualSelectedParentBlueScoreResponseMessage struct { @@ -4401,7 +4561,7 @@ type GetVirtualSelectedParentBlueScoreResponseMessage struct { func (x *GetVirtualSelectedParentBlueScoreResponseMessage) Reset() { *x = GetVirtualSelectedParentBlueScoreResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[76] + mi := &file_rpc_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4414,7 +4574,7 @@ func (x *GetVirtualSelectedParentBlueScoreResponseMessage) String() string { func (*GetVirtualSelectedParentBlueScoreResponseMessage) ProtoMessage() {} func (x *GetVirtualSelectedParentBlueScoreResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[76] + mi := &file_rpc_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4427,7 +4587,7 @@ func (x *GetVirtualSelectedParentBlueScoreResponseMessage) ProtoReflect() protor // Deprecated: Use GetVirtualSelectedParentBlueScoreResponseMessage.ProtoReflect.Descriptor instead. func (*GetVirtualSelectedParentBlueScoreResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{76} + return file_rpc_proto_rawDescGZIP(), []int{79} } func (x *GetVirtualSelectedParentBlueScoreResponseMessage) GetBlueScore() uint64 { @@ -4457,7 +4617,7 @@ type NotifyVirtualSelectedParentBlueScoreChangedRequestMessage struct { func (x *NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) Reset() { *x = NotifyVirtualSelectedParentBlueScoreChangedRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[77] + mi := &file_rpc_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4470,7 +4630,7 @@ func (x *NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) String() str func (*NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) ProtoMessage() {} func (x *NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[77] + mi := &file_rpc_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4483,7 +4643,7 @@ func (x *NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) ProtoReflect // Deprecated: Use NotifyVirtualSelectedParentBlueScoreChangedRequestMessage.ProtoReflect.Descriptor instead. func (*NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{77} + return file_rpc_proto_rawDescGZIP(), []int{80} } type NotifyVirtualSelectedParentBlueScoreChangedResponseMessage struct { @@ -4497,7 +4657,7 @@ type NotifyVirtualSelectedParentBlueScoreChangedResponseMessage struct { func (x *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) Reset() { *x = NotifyVirtualSelectedParentBlueScoreChangedResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[78] + mi := &file_rpc_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4510,7 +4670,7 @@ func (x *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) String() st func (*NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) ProtoMessage() {} func (x *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[78] + mi := &file_rpc_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4523,7 +4683,7 @@ func (x *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) ProtoReflec // Deprecated: Use NotifyVirtualSelectedParentBlueScoreChangedResponseMessage.ProtoReflect.Descriptor instead. func (*NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{78} + return file_rpc_proto_rawDescGZIP(), []int{81} } func (x *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) GetError() *RPCError { @@ -4548,7 +4708,7 @@ type VirtualSelectedParentBlueScoreChangedNotificationMessage struct { func (x *VirtualSelectedParentBlueScoreChangedNotificationMessage) Reset() { *x = VirtualSelectedParentBlueScoreChangedNotificationMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[79] + mi := &file_rpc_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4561,7 +4721,7 @@ func (x *VirtualSelectedParentBlueScoreChangedNotificationMessage) String() stri func (*VirtualSelectedParentBlueScoreChangedNotificationMessage) ProtoMessage() {} func (x *VirtualSelectedParentBlueScoreChangedNotificationMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[79] + mi := &file_rpc_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4574,7 +4734,7 @@ func (x *VirtualSelectedParentBlueScoreChangedNotificationMessage) ProtoReflect( // Deprecated: Use VirtualSelectedParentBlueScoreChangedNotificationMessage.ProtoReflect.Descriptor instead. func (*VirtualSelectedParentBlueScoreChangedNotificationMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{79} + return file_rpc_proto_rawDescGZIP(), []int{82} } func (x *VirtualSelectedParentBlueScoreChangedNotificationMessage) GetVirtualSelectedParentBlueScore() uint64 { @@ -4597,7 +4757,7 @@ type NotifyVirtualDaaScoreChangedRequestMessage struct { func (x *NotifyVirtualDaaScoreChangedRequestMessage) Reset() { *x = NotifyVirtualDaaScoreChangedRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[80] + mi := &file_rpc_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4610,7 +4770,7 @@ func (x *NotifyVirtualDaaScoreChangedRequestMessage) String() string { func (*NotifyVirtualDaaScoreChangedRequestMessage) ProtoMessage() {} func (x *NotifyVirtualDaaScoreChangedRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[80] + mi := &file_rpc_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4623,7 +4783,7 @@ func (x *NotifyVirtualDaaScoreChangedRequestMessage) ProtoReflect() protoreflect // Deprecated: Use NotifyVirtualDaaScoreChangedRequestMessage.ProtoReflect.Descriptor instead. func (*NotifyVirtualDaaScoreChangedRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{80} + return file_rpc_proto_rawDescGZIP(), []int{83} } type NotifyVirtualDaaScoreChangedResponseMessage struct { @@ -4637,7 +4797,7 @@ type NotifyVirtualDaaScoreChangedResponseMessage struct { func (x *NotifyVirtualDaaScoreChangedResponseMessage) Reset() { *x = NotifyVirtualDaaScoreChangedResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[81] + mi := &file_rpc_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4650,7 +4810,7 @@ func (x *NotifyVirtualDaaScoreChangedResponseMessage) String() string { func (*NotifyVirtualDaaScoreChangedResponseMessage) ProtoMessage() {} func (x *NotifyVirtualDaaScoreChangedResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[81] + mi := &file_rpc_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4663,7 +4823,7 @@ func (x *NotifyVirtualDaaScoreChangedResponseMessage) ProtoReflect() protoreflec // Deprecated: Use NotifyVirtualDaaScoreChangedResponseMessage.ProtoReflect.Descriptor instead. func (*NotifyVirtualDaaScoreChangedResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{81} + return file_rpc_proto_rawDescGZIP(), []int{84} } func (x *NotifyVirtualDaaScoreChangedResponseMessage) GetError() *RPCError { @@ -4688,7 +4848,7 @@ type VirtualDaaScoreChangedNotificationMessage struct { func (x *VirtualDaaScoreChangedNotificationMessage) Reset() { *x = VirtualDaaScoreChangedNotificationMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[82] + mi := &file_rpc_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4701,7 +4861,7 @@ func (x *VirtualDaaScoreChangedNotificationMessage) String() string { func (*VirtualDaaScoreChangedNotificationMessage) ProtoMessage() {} func (x *VirtualDaaScoreChangedNotificationMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[82] + mi := &file_rpc_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4714,7 +4874,7 @@ func (x *VirtualDaaScoreChangedNotificationMessage) ProtoReflect() protoreflect. // Deprecated: Use VirtualDaaScoreChangedNotificationMessage.ProtoReflect.Descriptor instead. func (*VirtualDaaScoreChangedNotificationMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{82} + return file_rpc_proto_rawDescGZIP(), []int{85} } func (x *VirtualDaaScoreChangedNotificationMessage) GetVirtualDaaScore() uint64 { @@ -4739,7 +4899,7 @@ type NotifyPruningPointUTXOSetOverrideRequestMessage struct { func (x *NotifyPruningPointUTXOSetOverrideRequestMessage) Reset() { *x = NotifyPruningPointUTXOSetOverrideRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[83] + mi := &file_rpc_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4752,7 +4912,7 @@ func (x *NotifyPruningPointUTXOSetOverrideRequestMessage) String() string { func (*NotifyPruningPointUTXOSetOverrideRequestMessage) ProtoMessage() {} func (x *NotifyPruningPointUTXOSetOverrideRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[83] + mi := &file_rpc_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4765,7 +4925,7 @@ func (x *NotifyPruningPointUTXOSetOverrideRequestMessage) ProtoReflect() protore // Deprecated: Use NotifyPruningPointUTXOSetOverrideRequestMessage.ProtoReflect.Descriptor instead. func (*NotifyPruningPointUTXOSetOverrideRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{83} + return file_rpc_proto_rawDescGZIP(), []int{86} } type NotifyPruningPointUTXOSetOverrideResponseMessage struct { @@ -4779,7 +4939,7 @@ type NotifyPruningPointUTXOSetOverrideResponseMessage struct { func (x *NotifyPruningPointUTXOSetOverrideResponseMessage) Reset() { *x = NotifyPruningPointUTXOSetOverrideResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[84] + mi := &file_rpc_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4792,7 +4952,7 @@ func (x *NotifyPruningPointUTXOSetOverrideResponseMessage) String() string { func (*NotifyPruningPointUTXOSetOverrideResponseMessage) ProtoMessage() {} func (x *NotifyPruningPointUTXOSetOverrideResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[84] + mi := &file_rpc_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4805,7 +4965,7 @@ func (x *NotifyPruningPointUTXOSetOverrideResponseMessage) ProtoReflect() protor // Deprecated: Use NotifyPruningPointUTXOSetOverrideResponseMessage.ProtoReflect.Descriptor instead. func (*NotifyPruningPointUTXOSetOverrideResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{84} + return file_rpc_proto_rawDescGZIP(), []int{87} } func (x *NotifyPruningPointUTXOSetOverrideResponseMessage) GetError() *RPCError { @@ -4828,7 +4988,7 @@ type PruningPointUTXOSetOverrideNotificationMessage struct { func (x *PruningPointUTXOSetOverrideNotificationMessage) Reset() { *x = PruningPointUTXOSetOverrideNotificationMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[85] + mi := &file_rpc_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4841,7 +5001,7 @@ func (x *PruningPointUTXOSetOverrideNotificationMessage) String() string { func (*PruningPointUTXOSetOverrideNotificationMessage) ProtoMessage() {} func (x *PruningPointUTXOSetOverrideNotificationMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[85] + mi := &file_rpc_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4854,7 +5014,7 @@ func (x *PruningPointUTXOSetOverrideNotificationMessage) ProtoReflect() protoref // Deprecated: Use PruningPointUTXOSetOverrideNotificationMessage.ProtoReflect.Descriptor instead. func (*PruningPointUTXOSetOverrideNotificationMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{85} + return file_rpc_proto_rawDescGZIP(), []int{88} } // StopNotifyingPruningPointUTXOSetOverrideRequestMessage unregisters this connection for @@ -4872,7 +5032,7 @@ type StopNotifyingPruningPointUTXOSetOverrideRequestMessage struct { func (x *StopNotifyingPruningPointUTXOSetOverrideRequestMessage) Reset() { *x = StopNotifyingPruningPointUTXOSetOverrideRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[86] + mi := &file_rpc_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4885,7 +5045,7 @@ func (x *StopNotifyingPruningPointUTXOSetOverrideRequestMessage) String() string func (*StopNotifyingPruningPointUTXOSetOverrideRequestMessage) ProtoMessage() {} func (x *StopNotifyingPruningPointUTXOSetOverrideRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[86] + mi := &file_rpc_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4898,7 +5058,7 @@ func (x *StopNotifyingPruningPointUTXOSetOverrideRequestMessage) ProtoReflect() // Deprecated: Use StopNotifyingPruningPointUTXOSetOverrideRequestMessage.ProtoReflect.Descriptor instead. func (*StopNotifyingPruningPointUTXOSetOverrideRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{86} + return file_rpc_proto_rawDescGZIP(), []int{89} } type StopNotifyingPruningPointUTXOSetOverrideResponseMessage struct { @@ -4912,7 +5072,7 @@ type StopNotifyingPruningPointUTXOSetOverrideResponseMessage struct { func (x *StopNotifyingPruningPointUTXOSetOverrideResponseMessage) Reset() { *x = StopNotifyingPruningPointUTXOSetOverrideResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[87] + mi := &file_rpc_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4925,7 +5085,7 @@ func (x *StopNotifyingPruningPointUTXOSetOverrideResponseMessage) String() strin func (*StopNotifyingPruningPointUTXOSetOverrideResponseMessage) ProtoMessage() {} func (x *StopNotifyingPruningPointUTXOSetOverrideResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[87] + mi := &file_rpc_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4938,7 +5098,7 @@ func (x *StopNotifyingPruningPointUTXOSetOverrideResponseMessage) ProtoReflect() // Deprecated: Use StopNotifyingPruningPointUTXOSetOverrideResponseMessage.ProtoReflect.Descriptor instead. func (*StopNotifyingPruningPointUTXOSetOverrideResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{87} + return file_rpc_proto_rawDescGZIP(), []int{90} } func (x *StopNotifyingPruningPointUTXOSetOverrideResponseMessage) GetError() *RPCError { @@ -4960,7 +5120,7 @@ type BanRequestMessage struct { func (x *BanRequestMessage) Reset() { *x = BanRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[88] + mi := &file_rpc_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4973,7 +5133,7 @@ func (x *BanRequestMessage) String() string { func (*BanRequestMessage) ProtoMessage() {} func (x *BanRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[88] + mi := &file_rpc_proto_msgTypes[91] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4986,7 +5146,7 @@ func (x *BanRequestMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use BanRequestMessage.ProtoReflect.Descriptor instead. func (*BanRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{88} + return file_rpc_proto_rawDescGZIP(), []int{91} } func (x *BanRequestMessage) GetIp() string { @@ -5007,7 +5167,7 @@ type BanResponseMessage struct { func (x *BanResponseMessage) Reset() { *x = BanResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[89] + mi := &file_rpc_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5020,7 +5180,7 @@ func (x *BanResponseMessage) String() string { func (*BanResponseMessage) ProtoMessage() {} func (x *BanResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[89] + mi := &file_rpc_proto_msgTypes[92] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5033,7 +5193,7 @@ func (x *BanResponseMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use BanResponseMessage.ProtoReflect.Descriptor instead. func (*BanResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{89} + return file_rpc_proto_rawDescGZIP(), []int{92} } func (x *BanResponseMessage) GetError() *RPCError { @@ -5055,7 +5215,7 @@ type UnbanRequestMessage struct { func (x *UnbanRequestMessage) Reset() { *x = UnbanRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[90] + mi := &file_rpc_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5068,7 +5228,7 @@ func (x *UnbanRequestMessage) String() string { func (*UnbanRequestMessage) ProtoMessage() {} func (x *UnbanRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[90] + mi := &file_rpc_proto_msgTypes[93] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5081,7 +5241,7 @@ func (x *UnbanRequestMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanRequestMessage.ProtoReflect.Descriptor instead. func (*UnbanRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{90} + return file_rpc_proto_rawDescGZIP(), []int{93} } func (x *UnbanRequestMessage) GetIp() string { @@ -5102,7 +5262,7 @@ type UnbanResponseMessage struct { func (x *UnbanResponseMessage) Reset() { *x = UnbanResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[91] + mi := &file_rpc_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5115,7 +5275,7 @@ func (x *UnbanResponseMessage) String() string { func (*UnbanResponseMessage) ProtoMessage() {} func (x *UnbanResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[91] + mi := &file_rpc_proto_msgTypes[94] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5128,7 +5288,7 @@ func (x *UnbanResponseMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanResponseMessage.ProtoReflect.Descriptor instead. func (*UnbanResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{91} + return file_rpc_proto_rawDescGZIP(), []int{94} } func (x *UnbanResponseMessage) GetError() *RPCError { @@ -5148,7 +5308,7 @@ type GetInfoRequestMessage struct { func (x *GetInfoRequestMessage) Reset() { *x = GetInfoRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[92] + mi := &file_rpc_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5161,7 +5321,7 @@ func (x *GetInfoRequestMessage) String() string { func (*GetInfoRequestMessage) ProtoMessage() {} func (x *GetInfoRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[92] + mi := &file_rpc_proto_msgTypes[95] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5174,7 +5334,7 @@ func (x *GetInfoRequestMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use GetInfoRequestMessage.ProtoReflect.Descriptor instead. func (*GetInfoRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{92} + return file_rpc_proto_rawDescGZIP(), []int{95} } type GetInfoResponseMessage struct { @@ -5191,7 +5351,7 @@ type GetInfoResponseMessage struct { func (x *GetInfoResponseMessage) Reset() { *x = GetInfoResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[93] + mi := &file_rpc_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5204,7 +5364,7 @@ func (x *GetInfoResponseMessage) String() string { func (*GetInfoResponseMessage) ProtoMessage() {} func (x *GetInfoResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[93] + mi := &file_rpc_proto_msgTypes[96] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5217,7 +5377,7 @@ func (x *GetInfoResponseMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use GetInfoResponseMessage.ProtoReflect.Descriptor instead. func (*GetInfoResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{93} + return file_rpc_proto_rawDescGZIP(), []int{96} } func (x *GetInfoResponseMessage) GetP2PId() string { @@ -5260,7 +5420,7 @@ type EstimateNetworkHashesPerSecondRequestMessage struct { func (x *EstimateNetworkHashesPerSecondRequestMessage) Reset() { *x = EstimateNetworkHashesPerSecondRequestMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[94] + mi := &file_rpc_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5273,7 +5433,7 @@ func (x *EstimateNetworkHashesPerSecondRequestMessage) String() string { func (*EstimateNetworkHashesPerSecondRequestMessage) ProtoMessage() {} func (x *EstimateNetworkHashesPerSecondRequestMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[94] + mi := &file_rpc_proto_msgTypes[97] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5286,7 +5446,7 @@ func (x *EstimateNetworkHashesPerSecondRequestMessage) ProtoReflect() protorefle // Deprecated: Use EstimateNetworkHashesPerSecondRequestMessage.ProtoReflect.Descriptor instead. func (*EstimateNetworkHashesPerSecondRequestMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{94} + return file_rpc_proto_rawDescGZIP(), []int{97} } func (x *EstimateNetworkHashesPerSecondRequestMessage) GetWindowSize() uint32 { @@ -5315,7 +5475,7 @@ type EstimateNetworkHashesPerSecondResponseMessage struct { func (x *EstimateNetworkHashesPerSecondResponseMessage) Reset() { *x = EstimateNetworkHashesPerSecondResponseMessage{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[95] + mi := &file_rpc_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5328,7 +5488,7 @@ func (x *EstimateNetworkHashesPerSecondResponseMessage) String() string { func (*EstimateNetworkHashesPerSecondResponseMessage) ProtoMessage() {} func (x *EstimateNetworkHashesPerSecondResponseMessage) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[95] + mi := &file_rpc_proto_msgTypes[98] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5341,7 +5501,7 @@ func (x *EstimateNetworkHashesPerSecondResponseMessage) ProtoReflect() protorefl // Deprecated: Use EstimateNetworkHashesPerSecondResponseMessage.ProtoReflect.Descriptor instead. func (*EstimateNetworkHashesPerSecondResponseMessage) Descriptor() ([]byte, []int) { - return file_rpc_proto_rawDescGZIP(), []int{95} + return file_rpc_proto_rawDescGZIP(), []int{98} } func (x *EstimateNetworkHashesPerSecondResponseMessage) GetNetworkHashesPerSecond() uint64 { @@ -5923,118 +6083,139 @@ var file_rpc_proto_rawDesc = []byte{ 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, - 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x31, - 0x0a, 0x2f, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, - 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x22, 0x7c, 0x0a, 0x30, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, + 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x44, + 0x0a, 0x24, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x22, 0x78, 0x0a, 0x16, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, + 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x90, + 0x01, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, + 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x22, 0x31, 0x0a, 0x2f, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, - 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, - 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, - 0x6f, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, - 0x3b, 0x0a, 0x39, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, + 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x7c, 0x0a, 0x30, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, + 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, + 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x3b, 0x0a, 0x39, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, + 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x68, 0x0a, 0x3a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x68, 0x0a, 0x3a, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, - 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x82, 0x01, 0x0a, 0x38, 0x56, 0x69, 0x72, 0x74, 0x75, - 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x1e, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, - 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, 0x76, 0x69, 0x72, - 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x2c, 0x0a, 0x2a, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, - 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x59, 0x0a, 0x2b, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, - 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x29, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, - 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, - 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x76, 0x69, 0x72, 0x74, - 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x31, 0x0a, 0x2f, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x5e, - 0x0a, 0x30, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x82, 0x01, 0x0a, 0x38, 0x56, 0x69, + 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x1e, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, + 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, + 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, + 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x2c, + 0x0a, 0x2a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, + 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x59, 0x0a, 0x2b, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x29, 0x56, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, + 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x76, + 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x31, + 0x0a, 0x2f, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, - 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x30, - 0x0a, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, - 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x38, 0x0a, 0x36, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, - 0x67, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, - 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, 0x37, 0x53, 0x74, - 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x75, 0x6e, 0x69, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x5e, 0x0a, 0x30, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x23, 0x0a, 0x11, 0x42, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, 0x40, 0x0a, 0x12, 0x42, 0x61, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, + 0x72, 0x22, 0x30, 0x0a, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x22, 0x38, 0x0a, 0x36, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, + 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, + 0x37, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, + 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, + 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0x23, 0x0a, 0x11, 0x42, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, 0x40, 0x0a, 0x12, 0x42, 0x61, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x25, 0x0a, 0x13, 0x55, + 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x70, 0x22, 0x42, 0x0a, 0x14, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0xa2, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x32, + 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x32, 0x70, 0x49, 0x64, + 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6c, 0x0a, 0x2c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, + 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, + 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, + 0x73, 0x68, 0x22, 0x93, 0x01, 0x0a, 0x2d, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x25, 0x0a, 0x13, 0x55, 0x6e, 0x62, 0x61, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, - 0x42, 0x0a, 0x14, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa2, 0x01, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x32, 0x70, 0x49, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x32, 0x70, 0x49, 0x64, 0x12, 0x20, 0x0a, - 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x24, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, - 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x6c, 0x0a, 0x2c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, - 0x93, 0x01, 0x0a, 0x2d, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x36, 0x0a, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, - 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, - 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, + 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -6050,7 +6231,7 @@ func file_rpc_proto_rawDescGZIP() []byte { } var file_rpc_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 96) +var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 99) var file_rpc_proto_goTypes = []interface{}{ (SubmitBlockResponseMessage_RejectReason)(0), // 0: protowire.SubmitBlockResponseMessage.RejectReason (*RPCError)(nil), // 1: protowire.RPCError @@ -6128,27 +6309,30 @@ var file_rpc_proto_goTypes = []interface{}{ (*GetUtxosByAddressesResponseMessage)(nil), // 73: protowire.GetUtxosByAddressesResponseMessage (*GetBalanceByAddressRequestMessage)(nil), // 74: protowire.GetBalanceByAddressRequestMessage (*GetBalanceByAddressResponseMessage)(nil), // 75: protowire.GetBalanceByAddressResponseMessage - (*GetVirtualSelectedParentBlueScoreRequestMessage)(nil), // 76: protowire.GetVirtualSelectedParentBlueScoreRequestMessage - (*GetVirtualSelectedParentBlueScoreResponseMessage)(nil), // 77: protowire.GetVirtualSelectedParentBlueScoreResponseMessage - (*NotifyVirtualSelectedParentBlueScoreChangedRequestMessage)(nil), // 78: protowire.NotifyVirtualSelectedParentBlueScoreChangedRequestMessage - (*NotifyVirtualSelectedParentBlueScoreChangedResponseMessage)(nil), // 79: protowire.NotifyVirtualSelectedParentBlueScoreChangedResponseMessage - (*VirtualSelectedParentBlueScoreChangedNotificationMessage)(nil), // 80: protowire.VirtualSelectedParentBlueScoreChangedNotificationMessage - (*NotifyVirtualDaaScoreChangedRequestMessage)(nil), // 81: protowire.NotifyVirtualDaaScoreChangedRequestMessage - (*NotifyVirtualDaaScoreChangedResponseMessage)(nil), // 82: protowire.NotifyVirtualDaaScoreChangedResponseMessage - (*VirtualDaaScoreChangedNotificationMessage)(nil), // 83: protowire.VirtualDaaScoreChangedNotificationMessage - (*NotifyPruningPointUTXOSetOverrideRequestMessage)(nil), // 84: protowire.NotifyPruningPointUTXOSetOverrideRequestMessage - (*NotifyPruningPointUTXOSetOverrideResponseMessage)(nil), // 85: protowire.NotifyPruningPointUTXOSetOverrideResponseMessage - (*PruningPointUTXOSetOverrideNotificationMessage)(nil), // 86: protowire.PruningPointUTXOSetOverrideNotificationMessage - (*StopNotifyingPruningPointUTXOSetOverrideRequestMessage)(nil), // 87: protowire.StopNotifyingPruningPointUTXOSetOverrideRequestMessage - (*StopNotifyingPruningPointUTXOSetOverrideResponseMessage)(nil), // 88: protowire.StopNotifyingPruningPointUTXOSetOverrideResponseMessage - (*BanRequestMessage)(nil), // 89: protowire.BanRequestMessage - (*BanResponseMessage)(nil), // 90: protowire.BanResponseMessage - (*UnbanRequestMessage)(nil), // 91: protowire.UnbanRequestMessage - (*UnbanResponseMessage)(nil), // 92: protowire.UnbanResponseMessage - (*GetInfoRequestMessage)(nil), // 93: protowire.GetInfoRequestMessage - (*GetInfoResponseMessage)(nil), // 94: protowire.GetInfoResponseMessage - (*EstimateNetworkHashesPerSecondRequestMessage)(nil), // 95: protowire.EstimateNetworkHashesPerSecondRequestMessage - (*EstimateNetworkHashesPerSecondResponseMessage)(nil), // 96: protowire.EstimateNetworkHashesPerSecondResponseMessage + (*GetBalancesByAddressesRequestMessage)(nil), // 76: protowire.GetBalancesByAddressesRequestMessage + (*BalancesByAddressEntry)(nil), // 77: protowire.BalancesByAddressEntry + (*GetBalancesByAddressesResponseMessage)(nil), // 78: protowire.GetBalancesByAddressesResponseMessage + (*GetVirtualSelectedParentBlueScoreRequestMessage)(nil), // 79: protowire.GetVirtualSelectedParentBlueScoreRequestMessage + (*GetVirtualSelectedParentBlueScoreResponseMessage)(nil), // 80: protowire.GetVirtualSelectedParentBlueScoreResponseMessage + (*NotifyVirtualSelectedParentBlueScoreChangedRequestMessage)(nil), // 81: protowire.NotifyVirtualSelectedParentBlueScoreChangedRequestMessage + (*NotifyVirtualSelectedParentBlueScoreChangedResponseMessage)(nil), // 82: protowire.NotifyVirtualSelectedParentBlueScoreChangedResponseMessage + (*VirtualSelectedParentBlueScoreChangedNotificationMessage)(nil), // 83: protowire.VirtualSelectedParentBlueScoreChangedNotificationMessage + (*NotifyVirtualDaaScoreChangedRequestMessage)(nil), // 84: protowire.NotifyVirtualDaaScoreChangedRequestMessage + (*NotifyVirtualDaaScoreChangedResponseMessage)(nil), // 85: protowire.NotifyVirtualDaaScoreChangedResponseMessage + (*VirtualDaaScoreChangedNotificationMessage)(nil), // 86: protowire.VirtualDaaScoreChangedNotificationMessage + (*NotifyPruningPointUTXOSetOverrideRequestMessage)(nil), // 87: protowire.NotifyPruningPointUTXOSetOverrideRequestMessage + (*NotifyPruningPointUTXOSetOverrideResponseMessage)(nil), // 88: protowire.NotifyPruningPointUTXOSetOverrideResponseMessage + (*PruningPointUTXOSetOverrideNotificationMessage)(nil), // 89: protowire.PruningPointUTXOSetOverrideNotificationMessage + (*StopNotifyingPruningPointUTXOSetOverrideRequestMessage)(nil), // 90: protowire.StopNotifyingPruningPointUTXOSetOverrideRequestMessage + (*StopNotifyingPruningPointUTXOSetOverrideResponseMessage)(nil), // 91: protowire.StopNotifyingPruningPointUTXOSetOverrideResponseMessage + (*BanRequestMessage)(nil), // 92: protowire.BanRequestMessage + (*BanResponseMessage)(nil), // 93: protowire.BanResponseMessage + (*UnbanRequestMessage)(nil), // 94: protowire.UnbanRequestMessage + (*UnbanResponseMessage)(nil), // 95: protowire.UnbanResponseMessage + (*GetInfoRequestMessage)(nil), // 96: protowire.GetInfoRequestMessage + (*GetInfoResponseMessage)(nil), // 97: protowire.GetInfoResponseMessage + (*EstimateNetworkHashesPerSecondRequestMessage)(nil), // 98: protowire.EstimateNetworkHashesPerSecondRequestMessage + (*EstimateNetworkHashesPerSecondResponseMessage)(nil), // 99: protowire.EstimateNetworkHashesPerSecondResponseMessage } var file_rpc_proto_depIdxs = []int32{ 3, // 0: protowire.RpcBlock.header:type_name -> protowire.RpcBlockHeader @@ -6207,20 +6391,23 @@ var file_rpc_proto_depIdxs = []int32{ 69, // 53: protowire.GetUtxosByAddressesResponseMessage.entries:type_name -> protowire.UtxosByAddressesEntry 1, // 54: protowire.GetUtxosByAddressesResponseMessage.error:type_name -> protowire.RPCError 1, // 55: protowire.GetBalanceByAddressResponseMessage.error:type_name -> protowire.RPCError - 1, // 56: protowire.GetVirtualSelectedParentBlueScoreResponseMessage.error:type_name -> protowire.RPCError - 1, // 57: protowire.NotifyVirtualSelectedParentBlueScoreChangedResponseMessage.error:type_name -> protowire.RPCError - 1, // 58: protowire.NotifyVirtualDaaScoreChangedResponseMessage.error:type_name -> protowire.RPCError - 1, // 59: protowire.NotifyPruningPointUTXOSetOverrideResponseMessage.error:type_name -> protowire.RPCError - 1, // 60: protowire.StopNotifyingPruningPointUTXOSetOverrideResponseMessage.error:type_name -> protowire.RPCError - 1, // 61: protowire.BanResponseMessage.error:type_name -> protowire.RPCError - 1, // 62: protowire.UnbanResponseMessage.error:type_name -> protowire.RPCError - 1, // 63: protowire.GetInfoResponseMessage.error:type_name -> protowire.RPCError - 1, // 64: protowire.EstimateNetworkHashesPerSecondResponseMessage.error:type_name -> protowire.RPCError - 65, // [65:65] is the sub-list for method output_type - 65, // [65:65] is the sub-list for method input_type - 65, // [65:65] is the sub-list for extension type_name - 65, // [65:65] is the sub-list for extension extendee - 0, // [0:65] is the sub-list for field type_name + 1, // 56: protowire.BalancesByAddressEntry.error:type_name -> protowire.RPCError + 77, // 57: protowire.GetBalancesByAddressesResponseMessage.entries:type_name -> protowire.BalancesByAddressEntry + 1, // 58: protowire.GetBalancesByAddressesResponseMessage.error:type_name -> protowire.RPCError + 1, // 59: protowire.GetVirtualSelectedParentBlueScoreResponseMessage.error:type_name -> protowire.RPCError + 1, // 60: protowire.NotifyVirtualSelectedParentBlueScoreChangedResponseMessage.error:type_name -> protowire.RPCError + 1, // 61: protowire.NotifyVirtualDaaScoreChangedResponseMessage.error:type_name -> protowire.RPCError + 1, // 62: protowire.NotifyPruningPointUTXOSetOverrideResponseMessage.error:type_name -> protowire.RPCError + 1, // 63: protowire.StopNotifyingPruningPointUTXOSetOverrideResponseMessage.error:type_name -> protowire.RPCError + 1, // 64: protowire.BanResponseMessage.error:type_name -> protowire.RPCError + 1, // 65: protowire.UnbanResponseMessage.error:type_name -> protowire.RPCError + 1, // 66: protowire.GetInfoResponseMessage.error:type_name -> protowire.RPCError + 1, // 67: protowire.EstimateNetworkHashesPerSecondResponseMessage.error:type_name -> protowire.RPCError + 68, // [68:68] is the sub-list for method output_type + 68, // [68:68] is the sub-list for method input_type + 68, // [68:68] is the sub-list for extension type_name + 68, // [68:68] is the sub-list for extension extendee + 0, // [0:68] is the sub-list for field type_name } func init() { file_rpc_proto_init() } @@ -7130,7 +7317,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVirtualSelectedParentBlueScoreRequestMessage); i { + switch v := v.(*GetBalancesByAddressesRequestMessage); i { case 0: return &v.state case 1: @@ -7142,7 +7329,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVirtualSelectedParentBlueScoreResponseMessage); i { + switch v := v.(*BalancesByAddressEntry); i { case 0: return &v.state case 1: @@ -7154,7 +7341,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyVirtualSelectedParentBlueScoreChangedRequestMessage); i { + switch v := v.(*GetBalancesByAddressesResponseMessage); i { case 0: return &v.state case 1: @@ -7166,7 +7353,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyVirtualSelectedParentBlueScoreChangedResponseMessage); i { + switch v := v.(*GetVirtualSelectedParentBlueScoreRequestMessage); i { case 0: return &v.state case 1: @@ -7178,7 +7365,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VirtualSelectedParentBlueScoreChangedNotificationMessage); i { + switch v := v.(*GetVirtualSelectedParentBlueScoreResponseMessage); i { case 0: return &v.state case 1: @@ -7190,7 +7377,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyVirtualDaaScoreChangedRequestMessage); i { + switch v := v.(*NotifyVirtualSelectedParentBlueScoreChangedRequestMessage); i { case 0: return &v.state case 1: @@ -7202,7 +7389,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyVirtualDaaScoreChangedResponseMessage); i { + switch v := v.(*NotifyVirtualSelectedParentBlueScoreChangedResponseMessage); i { case 0: return &v.state case 1: @@ -7214,7 +7401,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VirtualDaaScoreChangedNotificationMessage); i { + switch v := v.(*VirtualSelectedParentBlueScoreChangedNotificationMessage); i { case 0: return &v.state case 1: @@ -7226,7 +7413,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyPruningPointUTXOSetOverrideRequestMessage); i { + switch v := v.(*NotifyVirtualDaaScoreChangedRequestMessage); i { case 0: return &v.state case 1: @@ -7238,7 +7425,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyPruningPointUTXOSetOverrideResponseMessage); i { + switch v := v.(*NotifyVirtualDaaScoreChangedResponseMessage); i { case 0: return &v.state case 1: @@ -7250,7 +7437,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PruningPointUTXOSetOverrideNotificationMessage); i { + switch v := v.(*VirtualDaaScoreChangedNotificationMessage); i { case 0: return &v.state case 1: @@ -7262,7 +7449,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopNotifyingPruningPointUTXOSetOverrideRequestMessage); i { + switch v := v.(*NotifyPruningPointUTXOSetOverrideRequestMessage); i { case 0: return &v.state case 1: @@ -7274,7 +7461,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopNotifyingPruningPointUTXOSetOverrideResponseMessage); i { + switch v := v.(*NotifyPruningPointUTXOSetOverrideResponseMessage); i { case 0: return &v.state case 1: @@ -7286,7 +7473,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BanRequestMessage); i { + switch v := v.(*PruningPointUTXOSetOverrideNotificationMessage); i { case 0: return &v.state case 1: @@ -7298,7 +7485,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BanResponseMessage); i { + switch v := v.(*StopNotifyingPruningPointUTXOSetOverrideRequestMessage); i { case 0: return &v.state case 1: @@ -7310,7 +7497,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnbanRequestMessage); i { + switch v := v.(*StopNotifyingPruningPointUTXOSetOverrideResponseMessage); i { case 0: return &v.state case 1: @@ -7322,7 +7509,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnbanResponseMessage); i { + switch v := v.(*BanRequestMessage); i { case 0: return &v.state case 1: @@ -7334,7 +7521,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoRequestMessage); i { + switch v := v.(*BanResponseMessage); i { case 0: return &v.state case 1: @@ -7346,7 +7533,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoResponseMessage); i { + switch v := v.(*UnbanRequestMessage); i { case 0: return &v.state case 1: @@ -7358,7 +7545,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EstimateNetworkHashesPerSecondRequestMessage); i { + switch v := v.(*UnbanResponseMessage); i { case 0: return &v.state case 1: @@ -7370,6 +7557,42 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetInfoRequestMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetInfoResponseMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EstimateNetworkHashesPerSecondRequestMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EstimateNetworkHashesPerSecondResponseMessage); i { case 0: return &v.state @@ -7388,7 +7611,7 @@ func file_rpc_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_rpc_proto_rawDesc, NumEnums: 1, - NumMessages: 96, + NumMessages: 99, NumExtensions: 0, NumServices: 0, }, diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto index f17f1e7d40..b1dd4a8614 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto @@ -512,6 +512,23 @@ message GetBalanceByAddressResponseMessage { RPCError error = 1000; } +message GetBalancesByAddressesRequestMessage { + repeated string addresses = 1; +} + +message BalancesByAddressEntry{ + string address = 1; + uint64 balance = 2; + + RPCError error = 1000; +} + +message GetBalancesByAddressesResponseMessage { + repeated BalancesByAddressEntry entries = 1; + + RPCError error = 1000; +} + // GetVirtualSelectedParentBlueScoreRequestMessage requests the blue score of the current selected parent // of the virtual block. message GetVirtualSelectedParentBlueScoreRequestMessage { diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_balances_by_addresses.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_balances_by_addresses.go new file mode 100644 index 0000000000..7b7d23c05e --- /dev/null +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_balances_by_addresses.go @@ -0,0 +1,99 @@ +package protowire + +import ( + "github.com/kaspanet/kaspad/app/appmessage" + "github.com/pkg/errors" +) + +func (x *KaspadMessage_GetBalancesByAddressesRequest) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "KaspadMessage_GetBalanceByAddressRequest is nil") + } + return x.GetBalancesByAddressesRequest.toAppMessage() +} + +func (x *KaspadMessage_GetBalancesByAddressesRequest) fromAppMessage(message *appmessage.GetBalancesByAddressesRequestMessage) error { + x.GetBalancesByAddressesRequest = &GetBalancesByAddressesRequestMessage{ + Addresses: message.Addresses, + } + return nil +} + +func (x *GetBalancesByAddressesRequestMessage) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "GetBalanceByAddressRequest is nil") + } + return &appmessage.GetBalancesByAddressesRequestMessage{ + Addresses: x.Addresses, + }, nil +} + +func (x *KaspadMessage_GetBalancesByAddressesResponse) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "GetBalanceByAddressResponse is nil") + } + return x.GetBalancesByAddressesResponse.toAppMessage() +} + +func (x *KaspadMessage_GetBalancesByAddressesResponse) fromAppMessage(message *appmessage.GetBalancesByAddressesResponseMessage) error { + var err *RPCError + if message.Error != nil { + err = &RPCError{Message: message.Error.Message} + } + entries := make([]*BalancesByAddressEntry, len(message.Entries)) + for i, entry := range message.Entries { + entries[i] = &BalancesByAddressEntry{} + entries[i].fromAppMessage(entry) + } + x.GetBalancesByAddressesResponse = &GetBalancesByAddressesResponseMessage{ + Entries: entries, + Error: err, + } + return nil +} + +func (x *GetBalancesByAddressesResponseMessage) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "GetBalancesByAddressesResponseMessage is nil") + } + rpcErr, err := x.Error.toAppMessage() + // Error is an optional field + if err != nil && !errors.Is(err, errorNil) { + return nil, err + } + + if rpcErr != nil && len(x.Entries) != 0 { + return nil, errors.New("GetBalancesByAddressesResponseMessage contains both an error and a response") + } + + entries := make([]*appmessage.BalancesByAddressesEntry, len(x.Entries)) + for i, entry := range x.Entries { + entryAsAppMessage, err := entry.toAppMessage() + if err != nil { + return nil, err + } + entries[i] = entryAsAppMessage + } + + return &appmessage.GetBalancesByAddressesResponseMessage{ + Entries: entries, + Error: rpcErr, + }, nil +} + +func (x *BalancesByAddressEntry) toAppMessage() (*appmessage.BalancesByAddressesEntry, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "BalancesByAddressesEntry is nil") + } + return &appmessage.BalancesByAddressesEntry{ + Address: x.Address, + Balance: x.Balance, + }, nil +} + +func (x *BalancesByAddressEntry) fromAppMessage(message *appmessage.BalancesByAddressesEntry) { + *x = BalancesByAddressEntry{ + Address: message.Address, + Balance: message.Balance, + } +} diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go b/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go index b090e2692a..277980e4e8 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go @@ -877,6 +877,20 @@ func toRPCPayload(message appmessage.Message) (isKaspadMessage_Payload, error) { return nil, err } return payload, nil + case *appmessage.GetBalancesByAddressesRequestMessage: + payload := new(KaspadMessage_GetBalancesByAddressesRequest) + err := payload.fromAppMessage(message) + if err != nil { + return nil, err + } + return payload, nil + case *appmessage.GetBalancesByAddressesResponseMessage: + payload := new(KaspadMessage_GetBalancesByAddressesResponse) + err := payload.fromAppMessage(message) + if err != nil { + return nil, err + } + return payload, nil default: return nil, nil } diff --git a/infrastructure/network/rpcclient/rpc_get_balances_by_addresses.go b/infrastructure/network/rpcclient/rpc_get_balances_by_addresses.go new file mode 100644 index 0000000000..f852065e92 --- /dev/null +++ b/infrastructure/network/rpcclient/rpc_get_balances_by_addresses.go @@ -0,0 +1,20 @@ +package rpcclient + +import "github.com/kaspanet/kaspad/app/appmessage" + +// GetBalancesByAddresses sends an RPC request respective to the function's name and returns the RPC server's response +func (c *RPCClient) GetBalancesByAddresses(addresses []string) (*appmessage.GetBalancesByAddressesResponseMessage, error) { + err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetBalancesByAddressesRequest(addresses)) + if err != nil { + return nil, err + } + response, err := c.route(appmessage.CmdGetBalancesByAddressesResponseMessage).DequeueWithTimeout(c.timeout) + if err != nil { + return nil, err + } + getBalancesByAddressesResponse := response.(*appmessage.GetBalancesByAddressesResponseMessage) + if getBalancesByAddressesResponse.Error != nil { + return nil, c.convertRPCError(getBalancesByAddressesResponse.Error) + } + return getBalancesByAddressesResponse, nil +} diff --git a/stability-tests/simple-sync/mineloop.go b/stability-tests/simple-sync/mineloop.go index d910abb94c..e14c1785e3 100644 --- a/stability-tests/simple-sync/mineloop.go +++ b/stability-tests/simple-sync/mineloop.go @@ -37,7 +37,7 @@ func mineLoop(syncerRPCClient, syncedRPCClient *rpc.Client) error { } start := time.Now() - const timeToPropagate = 10 * time.Second + const timeToPropagate = 30 * time.Second select { case <-syncedRPCClient.OnBlockAdded: case <-time.After(timeToPropagate): diff --git a/testing/integration/address_exchange_test.go b/testing/integration/address_exchange_test.go index 862e3256ab..f391853e84 100644 --- a/testing/integration/address_exchange_test.go +++ b/testing/integration/address_exchange_test.go @@ -50,7 +50,6 @@ func TestAddressExchangeV3V4(t *testing.T) { rpcAddress: rpcAddress3, miningAddress: miningAddress3, miningAddressPrivateKey: miningAddress3PrivateKey, - protocolVersion: 3, }, }) defer teardown() diff --git a/testing/integration/ibd_test.go b/testing/integration/ibd_test.go index ab8b53fdd6..bd08004d39 100644 --- a/testing/integration/ibd_test.go +++ b/testing/integration/ibd_test.go @@ -89,7 +89,7 @@ func TestIBDWithPruning(t *testing.T) { start := time.Now() for range ticker.C { - if time.Since(start) > 2*defaultTimeout { + if time.Since(start) > 30*time.Second { t.Fatalf("Timeout waiting for IBD to finish.") } @@ -178,27 +178,10 @@ func TestIBDWithPruning(t *testing.T) { overrideDAGParams: &overrideDAGParams, utxoIndex: true, }, - { - p2pAddress: p2pAddress4, - rpcAddress: rpcAddress4, - miningAddress: miningAddress3, - miningAddressPrivateKey: miningAddress3PrivateKey, - overrideDAGParams: &overrideDAGParams, - utxoIndex: true, - protocolVersion: 3, - }, - { - p2pAddress: p2pAddress5, - rpcAddress: rpcAddress5, - miningAddress: miningAddress3, - miningAddressPrivateKey: miningAddress3PrivateKey, - overrideDAGParams: &overrideDAGParams, - utxoIndex: true, - }, }) defer teardown() - syncer, syncee1, syncee2, synceeV3, synceeV4 := harnesses[0], harnesses[1], harnesses[2], harnesses[3], harnesses[4] + syncer, syncee1, syncee2 := harnesses[0], harnesses[1], harnesses[2] // Let syncee1 have two blocks that the syncer // doesn't have to test a situation where @@ -219,12 +202,6 @@ func TestIBDWithPruning(t *testing.T) { // Test a situation where a node with pruned headers syncs another fresh node. testSync(syncee1, syncee2) - - // Test syncing from p2p v4 to p2p v3 - testSync(syncee2, synceeV3) - - // Test syncing from p2p v3 to p2p v4 - testSync(synceeV3, synceeV4) } var currentMockTimestamp int64 = 0 diff --git a/util/profiling/profiling.go b/util/profiling/profiling.go index 29b6b13ca5..b77969f2ca 100644 --- a/util/profiling/profiling.go +++ b/util/profiling/profiling.go @@ -18,8 +18,9 @@ import ( ) // heapDumpFileName is the name of the heap dump file. We want every run to have its own -// file, so we append the timestamp of the program launch time to the file name. -var heapDumpFileName = fmt.Sprintf("heap-%s.pprof", time.Now().Format(time.RFC3339)) +// file, so we append the timestamp of the program launch time to the file name (note the +// custom format for compliance with file name rules on all OSes). +var heapDumpFileName = fmt.Sprintf("heap-%s.pprof", time.Now().Format("01-02-2006T15.04.05")) // Start starts the profiling server func Start(port string, log *logger.Logger) { @@ -43,7 +44,7 @@ func TrackHeap(appDir string, log *logger.Logger) { log.Errorf("Could not create heap dumps folder at %s", dumpFolder) return } - const limitInGigabytes = 8 + const limitInGigabytes = 7 // We want to support 8 GB RAM, so we profile at 7 trackHeapSize(limitInGigabytes*1024*1024*1024, dumpFolder, log) }) } diff --git a/version/version.go b/version/version.go index 80a2cb4aeb..01f6001790 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs const ( appMajor uint = 0 appMinor uint = 11 - appPatch uint = 11 + appPatch uint = 12 ) // appBuild is defined as a variable so it can be overridden during the build