mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-03-17 21:58:48 +00:00
Compare commits
2 Commits
v0.7.0-dev
...
bignet-deb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53706c2f9f | ||
|
|
917fa11706 |
126
app/app.go
126
app/app.go
@@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/app/protocol"
|
"github.com/kaspanet/kaspad/app/protocol"
|
||||||
"github.com/kaspanet/kaspad/app/rpc"
|
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
"github.com/kaspanet/kaspad/domain/blockdag"
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag/indexers"
|
"github.com/kaspanet/kaspad/domain/blockdag/indexers"
|
||||||
"github.com/kaspanet/kaspad/domain/mempool"
|
"github.com/kaspanet/kaspad/domain/mempool"
|
||||||
@@ -21,6 +20,8 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/dnsseed"
|
"github.com/kaspanet/kaspad/infrastructure/network/dnsseed"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
||||||
|
"github.com/kaspanet/kaspad/infrastructure/network/rpc"
|
||||||
|
"github.com/kaspanet/kaspad/infrastructure/os/signal"
|
||||||
"github.com/kaspanet/kaspad/util"
|
"github.com/kaspanet/kaspad/util"
|
||||||
"github.com/kaspanet/kaspad/util/panics"
|
"github.com/kaspanet/kaspad/util/panics"
|
||||||
)
|
)
|
||||||
@@ -28,9 +29,9 @@ import (
|
|||||||
// App is a wrapper for all the kaspad services
|
// App is a wrapper for all the kaspad services
|
||||||
type App struct {
|
type App struct {
|
||||||
cfg *config.Config
|
cfg *config.Config
|
||||||
|
rpcServer *rpc.Server
|
||||||
addressManager *addressmanager.AddressManager
|
addressManager *addressmanager.AddressManager
|
||||||
protocolManager *protocol.Manager
|
protocolManager *protocol.Manager
|
||||||
rpcManager *rpc.Manager
|
|
||||||
connectionManager *connmanager.ConnectionManager
|
connectionManager *connmanager.ConnectionManager
|
||||||
netAdapter *netadapter.NetAdapter
|
netAdapter *netadapter.NetAdapter
|
||||||
|
|
||||||
@@ -46,14 +47,18 @@ func (a *App) Start() {
|
|||||||
|
|
||||||
log.Trace("Starting kaspad")
|
log.Trace("Starting kaspad")
|
||||||
|
|
||||||
err := a.netAdapter.Start()
|
err := a.protocolManager.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panics.Exit(log, fmt.Sprintf("Error starting the net adapter: %+v", err))
|
panics.Exit(log, fmt.Sprintf("Error starting the p2p protocol: %+v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
a.maybeSeedFromDNS()
|
a.maybeSeedFromDNS()
|
||||||
|
|
||||||
a.connectionManager.Start()
|
a.connectionManager.Start()
|
||||||
|
|
||||||
|
if !a.cfg.DisableRPC {
|
||||||
|
a.rpcServer.Start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop gracefully shuts down all the kaspad services.
|
// Stop gracefully shuts down all the kaspad services.
|
||||||
@@ -68,9 +73,17 @@ func (a *App) Stop() {
|
|||||||
|
|
||||||
a.connectionManager.Stop()
|
a.connectionManager.Stop()
|
||||||
|
|
||||||
err := a.netAdapter.Stop()
|
err := a.protocolManager.Stop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error stopping the net adapter: %+v", err)
|
log.Errorf("Error stopping the p2p protocol: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown the RPC server if it's not disabled.
|
||||||
|
if !a.cfg.DisableRPC {
|
||||||
|
err := a.rpcServer.Stop()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error stopping rpcServer: %+v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.addressManager.Stop()
|
err = a.addressManager.Stop()
|
||||||
@@ -113,72 +126,22 @@ func New(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrup
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rpcManager := setupRPC(cfg, txMempool, dag, sigCache, netAdapter, protocolManager, connectionManager, addressManager, acceptanceIndex)
|
rpcServer, err := setupRPC(
|
||||||
|
cfg, dag, txMempool, sigCache, acceptanceIndex, connectionManager, addressManager, protocolManager)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &App{
|
return &App{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
rpcServer: rpcServer,
|
||||||
protocolManager: protocolManager,
|
protocolManager: protocolManager,
|
||||||
rpcManager: rpcManager,
|
|
||||||
connectionManager: connectionManager,
|
connectionManager: connectionManager,
|
||||||
netAdapter: netAdapter,
|
netAdapter: netAdapter,
|
||||||
addressManager: addressManager,
|
addressManager: addressManager,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupRPC(
|
|
||||||
cfg *config.Config,
|
|
||||||
txMempool *mempool.TxPool,
|
|
||||||
dag *blockdag.BlockDAG,
|
|
||||||
sigCache *txscript.SigCache,
|
|
||||||
netAdapter *netadapter.NetAdapter,
|
|
||||||
protocolManager *protocol.Manager,
|
|
||||||
connectionManager *connmanager.ConnectionManager,
|
|
||||||
addressManager *addressmanager.AddressManager,
|
|
||||||
acceptanceIndex *indexers.AcceptanceIndex) *rpc.Manager {
|
|
||||||
|
|
||||||
blockTemplateGenerator := mining.NewBlkTmplGenerator(&mining.Policy{BlockMaxMass: cfg.BlockMaxMass}, txMempool, dag, sigCache)
|
|
||||||
rpcManager := rpc.NewManager(cfg, netAdapter, dag, protocolManager, connectionManager, blockTemplateGenerator, txMempool, addressManager, acceptanceIndex)
|
|
||||||
protocolManager.SetOnBlockAddedToDAGHandler(rpcManager.NotifyBlockAddedToDAG)
|
|
||||||
protocolManager.SetOnTransactionAddedToMempoolHandler(rpcManager.NotifyTransactionAddedToMempool)
|
|
||||||
dag.Subscribe(func(notification *blockdag.Notification) {
|
|
||||||
err := handleBlockDAGNotifications(notification, acceptanceIndex, rpcManager)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return rpcManager
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleBlockDAGNotifications(notification *blockdag.Notification,
|
|
||||||
acceptanceIndex *indexers.AcceptanceIndex, rpcManager *rpc.Manager) error {
|
|
||||||
|
|
||||||
switch notification.Type {
|
|
||||||
case blockdag.NTChainChanged:
|
|
||||||
if acceptanceIndex == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
chainChangedNotificationData := notification.Data.(*blockdag.ChainChangedNotificationData)
|
|
||||||
err := rpcManager.NotifyChainChanged(chainChangedNotificationData.RemovedChainBlockHashes,
|
|
||||||
chainChangedNotificationData.AddedChainBlockHashes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case blockdag.NTFinalityConflict:
|
|
||||||
finalityConflictNotificationData := notification.Data.(*blockdag.FinalityConflictNotificationData)
|
|
||||||
err := rpcManager.NotifyFinalityConflict(finalityConflictNotificationData.ViolatingBlockHash.String())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case blockdag.NTFinalityConflictResolved:
|
|
||||||
finalityConflictResolvedNotificationData := notification.Data.(*blockdag.FinalityConflictResolvedNotificationData)
|
|
||||||
err := rpcManager.NotifyFinalityConflictResolved(finalityConflictResolvedNotificationData.FinalityBlockHash.String())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) maybeSeedFromDNS() {
|
func (a *App) maybeSeedFromDNS() {
|
||||||
if !a.cfg.DisableDNSSeed {
|
if !a.cfg.DisableDNSSeed {
|
||||||
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, appmessage.SFNodeNetwork, false, nil,
|
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, appmessage.SFNodeNetwork, false, nil,
|
||||||
@@ -189,13 +152,6 @@ func (a *App) maybeSeedFromDNS() {
|
|||||||
a.addressManager.AddAddresses(addresses, addresses[0], nil)
|
a.addressManager.AddAddresses(addresses, addresses[0], nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.cfg.GRPCSeed != "" {
|
|
||||||
dnsseed.SeedFromGRPC(a.cfg.NetParams(), a.cfg.GRPCSeed, appmessage.SFNodeNetwork, false, nil,
|
|
||||||
func(addresses []*appmessage.NetAddress) {
|
|
||||||
a.addressManager.AddAddresses(addresses, addresses[0], nil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
func setupDAG(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrupt <-chan struct{},
|
func setupDAG(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrupt <-chan struct{},
|
||||||
sigCache *txscript.SigCache, indexManager blockdag.IndexManager) (*blockdag.BlockDAG, error) {
|
sigCache *txscript.SigCache, indexManager blockdag.IndexManager) (*blockdag.BlockDAG, error) {
|
||||||
@@ -249,6 +205,38 @@ func setupMempool(cfg *config.Config, dag *blockdag.BlockDAG, sigCache *txscript
|
|||||||
return mempool.New(&mempoolConfig)
|
return mempool.New(&mempoolConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupRPC(cfg *config.Config,
|
||||||
|
dag *blockdag.BlockDAG,
|
||||||
|
txMempool *mempool.TxPool,
|
||||||
|
sigCache *txscript.SigCache,
|
||||||
|
acceptanceIndex *indexers.AcceptanceIndex,
|
||||||
|
connectionManager *connmanager.ConnectionManager,
|
||||||
|
addressManager *addressmanager.AddressManager,
|
||||||
|
protocolManager *protocol.Manager) (*rpc.Server, error) {
|
||||||
|
|
||||||
|
if !cfg.DisableRPC {
|
||||||
|
policy := mining.Policy{
|
||||||
|
BlockMaxMass: cfg.BlockMaxMass,
|
||||||
|
}
|
||||||
|
blockTemplateGenerator := mining.NewBlkTmplGenerator(&policy, txMempool, dag, sigCache)
|
||||||
|
|
||||||
|
rpcServer, err := rpc.NewRPCServer(cfg, dag, txMempool, acceptanceIndex, blockTemplateGenerator,
|
||||||
|
connectionManager, addressManager, protocolManager)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal process shutdown when the RPC server requests it.
|
||||||
|
spawn("setupRPC-handleShutdownRequest", func() {
|
||||||
|
<-rpcServer.RequestedProcessShutdown()
|
||||||
|
signal.ShutdownRequestChannel <- struct{}{}
|
||||||
|
})
|
||||||
|
|
||||||
|
return rpcServer, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// P2PNodeID returns the network ID associated with this App
|
// P2PNodeID returns the network ID associated with this App
|
||||||
func (a *App) P2PNodeID() *id.ID {
|
func (a *App) P2PNodeID() *id.ID {
|
||||||
return a.netAdapter.ID()
|
return a.netAdapter.ID()
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ package appmessage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/util/daghash"
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"io"
|
|
||||||
"math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseBlockHeaderPayload is the base number of bytes a block header can be,
|
// BaseBlockHeaderPayload is the base number of bytes a block header can be,
|
||||||
@@ -61,11 +60,7 @@ type BlockHeader struct {
|
|||||||
|
|
||||||
// NumParentBlocks return the number of entries in ParentHashes
|
// NumParentBlocks return the number of entries in ParentHashes
|
||||||
func (h *BlockHeader) NumParentBlocks() byte {
|
func (h *BlockHeader) NumParentBlocks() byte {
|
||||||
numParents := len(h.ParentHashes)
|
return byte(len(h.ParentHashes))
|
||||||
if numParents > math.MaxUint8 {
|
|
||||||
panic(errors.Errorf("number of parents is %d, which is more than one byte can fit", numParents))
|
|
||||||
}
|
|
||||||
return byte(numParents)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockHash computes the block identifier hash for the given block header.
|
// BlockHash computes the block identifier hash for the given block header.
|
||||||
@@ -375,31 +375,30 @@ func ReadVarInt(r io.Reader) (uint64, error) {
|
|||||||
// on its value.
|
// on its value.
|
||||||
func WriteVarInt(w io.Writer, val uint64) error {
|
func WriteVarInt(w io.Writer, val uint64) error {
|
||||||
if val < 0xfd {
|
if val < 0xfd {
|
||||||
_, err := w.Write([]byte{uint8(val)})
|
return binaryserializer.PutUint8(w, uint8(val))
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if val <= math.MaxUint16 {
|
if val <= math.MaxUint16 {
|
||||||
var buf [3]byte
|
err := binaryserializer.PutUint8(w, 0xfd)
|
||||||
buf[0] = 0xfd
|
if err != nil {
|
||||||
littleEndian.PutUint16(buf[1:], uint16(val))
|
return err
|
||||||
_, err := w.Write(buf[:])
|
}
|
||||||
return errors.WithStack(err)
|
return binaryserializer.PutUint16(w, littleEndian, uint16(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
if val <= math.MaxUint32 {
|
if val <= math.MaxUint32 {
|
||||||
var buf [5]byte
|
err := binaryserializer.PutUint8(w, 0xfe)
|
||||||
buf[0] = 0xfe
|
if err != nil {
|
||||||
littleEndian.PutUint32(buf[1:], uint32(val))
|
return err
|
||||||
_, err := w.Write(buf[:])
|
}
|
||||||
return errors.WithStack(err)
|
return binaryserializer.PutUint32(w, littleEndian, uint32(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [9]byte
|
err := binaryserializer.PutUint8(w, 0xff)
|
||||||
buf[0] = 0xff
|
if err != nil {
|
||||||
littleEndian.PutUint64(buf[1:], val)
|
return err
|
||||||
_, err := w.Write(buf[:])
|
}
|
||||||
return errors.WithStack(err)
|
return binaryserializer.PutUint64(w, littleEndian, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VarIntSerializeSize returns the number of bytes it would take to serialize
|
// VarIntSerializeSize returns the number of bytes it would take to serialize
|
||||||
|
|||||||
@@ -32,16 +32,3 @@ func (e *MessageError) Error() string {
|
|||||||
func messageError(f string, desc string) *MessageError {
|
func messageError(f string, desc string) *MessageError {
|
||||||
return &MessageError{Func: f, Description: desc}
|
return &MessageError{Func: f, Description: desc}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCError represents an error arriving from the RPC
|
|
||||||
type RPCError struct {
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RPCErrorf formats according to a format specifier and returns the string
|
|
||||||
// as an RPCError.
|
|
||||||
func RPCErrorf(format string, args ...interface{}) *RPCError {
|
|
||||||
return &RPCError{
|
|
||||||
Message: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
56
app/appmessage/fakemessage_test.go
Normal file
56
app/appmessage/fakemessage_test.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) 2013-2016 The btcsuite developers
|
||||||
|
// Use of this source code is governed by an ISC
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package appmessage
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
// fakeMessage implements the Message interface and is used to force encode
|
||||||
|
// errors in messages.
|
||||||
|
type fakeMessage struct {
|
||||||
|
command MessageCommand
|
||||||
|
payload []byte
|
||||||
|
forceEncodeErr bool
|
||||||
|
forceLenErr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// KaspaDecode doesn't do anything. It just satisfies the appmessage.Message
|
||||||
|
// interface.
|
||||||
|
func (msg *fakeMessage) KaspaDecode(r io.Reader, pver uint32) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KaspaEncode writes the payload field of the fake message or forces an error
|
||||||
|
// if the forceEncodeErr flag of the fake message is set. It also satisfies the
|
||||||
|
// appmessage.Message interface.
|
||||||
|
func (msg *fakeMessage) KaspaEncode(w io.Writer, pver uint32) error {
|
||||||
|
if msg.forceEncodeErr {
|
||||||
|
err := &MessageError{
|
||||||
|
Func: "fakeMessage.KaspaEncode",
|
||||||
|
Description: "intentional error",
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := w.Write(msg.payload)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the command field of the fake message and satisfies the
|
||||||
|
// Message interface.
|
||||||
|
func (msg *fakeMessage) Command() MessageCommand {
|
||||||
|
return msg.command
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxPayloadLength returns the length of the payload field of fake message
|
||||||
|
// or a smaller value if the forceLenErr flag of the fake message is set. It
|
||||||
|
// satisfies the Message interface.
|
||||||
|
func (msg *fakeMessage) MaxPayloadLength(pver uint32) uint32 {
|
||||||
|
lenp := uint32(len(msg.payload))
|
||||||
|
if msg.forceLenErr {
|
||||||
|
return lenp - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return lenp
|
||||||
|
}
|
||||||
@@ -11,16 +11,13 @@ import (
|
|||||||
|
|
||||||
// MaxMessagePayload is the maximum bytes a message can be regardless of other
|
// MaxMessagePayload is the maximum bytes a message can be regardless of other
|
||||||
// individual limits imposed by messages themselves.
|
// individual limits imposed by messages themselves.
|
||||||
const MaxMessagePayload = 1024 * 1024 * 32 // 32MB
|
const MaxMessagePayload = (1024 * 1024 * 32) // 32MB
|
||||||
|
|
||||||
// MessageCommand is a number in the header of a message that represents its type.
|
// MessageCommand is a number in the header of a message that represents its type.
|
||||||
type MessageCommand uint32
|
type MessageCommand uint32
|
||||||
|
|
||||||
func (cmd MessageCommand) String() string {
|
func (cmd MessageCommand) String() string {
|
||||||
cmdString, ok := ProtocolMessageCommandToString[cmd]
|
cmdString, ok := MessageCommandToString[cmd]
|
||||||
if !ok {
|
|
||||||
cmdString, ok = RPCMessageCommandToString[cmd]
|
|
||||||
}
|
|
||||||
if !ok {
|
if !ok {
|
||||||
cmdString = "unknown command"
|
cmdString = "unknown command"
|
||||||
}
|
}
|
||||||
@@ -29,7 +26,6 @@ func (cmd MessageCommand) String() string {
|
|||||||
|
|
||||||
// Commands used in kaspa message headers which describe the type of message.
|
// Commands used in kaspa message headers which describe the type of message.
|
||||||
const (
|
const (
|
||||||
// protocol
|
|
||||||
CmdVersion MessageCommand = iota
|
CmdVersion MessageCommand = iota
|
||||||
CmdVerAck
|
CmdVerAck
|
||||||
CmdRequestAddresses
|
CmdRequestAddresses
|
||||||
@@ -52,55 +48,10 @@ const (
|
|||||||
CmdDoneIBDBlocks
|
CmdDoneIBDBlocks
|
||||||
CmdTransactionNotFound
|
CmdTransactionNotFound
|
||||||
CmdReject
|
CmdReject
|
||||||
|
|
||||||
// rpc
|
|
||||||
CmdGetCurrentNetworkRequestMessage
|
|
||||||
CmdGetCurrentNetworkResponseMessage
|
|
||||||
CmdSubmitBlockRequestMessage
|
|
||||||
CmdSubmitBlockResponseMessage
|
|
||||||
CmdGetBlockTemplateRequestMessage
|
|
||||||
CmdGetBlockTemplateResponseMessage
|
|
||||||
CmdGetBlockTemplateTransactionMessage
|
|
||||||
CmdNotifyBlockAddedRequestMessage
|
|
||||||
CmdNotifyBlockAddedResponseMessage
|
|
||||||
CmdBlockAddedNotificationMessage
|
|
||||||
CmdGetPeerAddressesRequestMessage
|
|
||||||
CmdGetPeerAddressesResponseMessage
|
|
||||||
CmdGetSelectedTipHashRequestMessage
|
|
||||||
CmdGetSelectedTipHashResponseMessage
|
|
||||||
CmdGetMempoolEntryRequestMessage
|
|
||||||
CmdGetMempoolEntryResponseMessage
|
|
||||||
CmdGetConnectedPeerInfoRequestMessage
|
|
||||||
CmdGetConnectedPeerInfoResponseMessage
|
|
||||||
CmdAddPeerRequestMessage
|
|
||||||
CmdAddPeerResponseMessage
|
|
||||||
CmdSubmitTransactionRequestMessage
|
|
||||||
CmdSubmitTransactionResponseMessage
|
|
||||||
CmdNotifyChainChangedRequestMessage
|
|
||||||
CmdNotifyChainChangedResponseMessage
|
|
||||||
CmdChainChangedNotificationMessage
|
|
||||||
CmdGetBlockRequestMessage
|
|
||||||
CmdGetBlockResponseMessage
|
|
||||||
CmdGetSubnetworkRequestMessage
|
|
||||||
CmdGetSubnetworkResponseMessage
|
|
||||||
CmdGetChainFromBlockRequestMessage
|
|
||||||
CmdGetChainFromBlockResponseMessage
|
|
||||||
CmdGetBlocksRequestMessage
|
|
||||||
CmdGetBlocksResponseMessage
|
|
||||||
CmdGetBlockCountRequestMessage
|
|
||||||
CmdGetBlockCountResponseMessage
|
|
||||||
CmdGetBlockDAGInfoRequestMessage
|
|
||||||
CmdGetBlockDAGInfoResponseMessage
|
|
||||||
CmdResolveFinalityConflictRequestMessage
|
|
||||||
CmdResolveFinalityConflictResponseMessage
|
|
||||||
CmdNotifyFinalityConflictsRequestMessage
|
|
||||||
CmdNotifyFinalityConflictsResponseMessage
|
|
||||||
CmdFinalityConflictNotificationMessage
|
|
||||||
CmdFinalityConflictResolvedNotificationMessage
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
|
// MessageCommandToString maps all MessageCommands to their string representation
|
||||||
var ProtocolMessageCommandToString = map[MessageCommand]string{
|
var MessageCommandToString = map[MessageCommand]string{
|
||||||
CmdVersion: "Version",
|
CmdVersion: "Version",
|
||||||
CmdVerAck: "VerAck",
|
CmdVerAck: "VerAck",
|
||||||
CmdRequestAddresses: "RequestAddresses",
|
CmdRequestAddresses: "RequestAddresses",
|
||||||
@@ -125,53 +76,6 @@ var ProtocolMessageCommandToString = map[MessageCommand]string{
|
|||||||
CmdReject: "Reject",
|
CmdReject: "Reject",
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCMessageCommandToString maps all MessageCommands to their string representation
|
|
||||||
var RPCMessageCommandToString = map[MessageCommand]string{
|
|
||||||
CmdGetCurrentNetworkRequestMessage: "GetCurrentNetworkRequest",
|
|
||||||
CmdGetCurrentNetworkResponseMessage: "GetCurrentNetworkResponse",
|
|
||||||
CmdSubmitBlockRequestMessage: "SubmitBlockRequest",
|
|
||||||
CmdSubmitBlockResponseMessage: "SubmitBlockResponse",
|
|
||||||
CmdGetBlockTemplateRequestMessage: "GetBlockTemplateRequest",
|
|
||||||
CmdGetBlockTemplateResponseMessage: "GetBlockTemplateResponse",
|
|
||||||
CmdGetBlockTemplateTransactionMessage: "CmdGetBlockTemplateTransaction",
|
|
||||||
CmdNotifyBlockAddedRequestMessage: "NotifyBlockAddedRequest",
|
|
||||||
CmdNotifyBlockAddedResponseMessage: "NotifyBlockAddedResponse",
|
|
||||||
CmdBlockAddedNotificationMessage: "BlockAddedNotification",
|
|
||||||
CmdGetPeerAddressesRequestMessage: "GetPeerAddressesRequest",
|
|
||||||
CmdGetPeerAddressesResponseMessage: "GetPeerAddressesResponse",
|
|
||||||
CmdGetSelectedTipHashRequestMessage: "GetSelectedTipHashRequest",
|
|
||||||
CmdGetSelectedTipHashResponseMessage: "GetSelectedTipHashResponse",
|
|
||||||
CmdGetMempoolEntryRequestMessage: "GetMempoolEntryRequest",
|
|
||||||
CmdGetMempoolEntryResponseMessage: "GetMempoolEntryResponse",
|
|
||||||
CmdGetConnectedPeerInfoRequestMessage: "GetConnectedPeerInfoRequest",
|
|
||||||
CmdGetConnectedPeerInfoResponseMessage: "GetConnectedPeerInfoResponse",
|
|
||||||
CmdAddPeerRequestMessage: "AddPeerRequest",
|
|
||||||
CmdAddPeerResponseMessage: "AddPeerResponse",
|
|
||||||
CmdSubmitTransactionRequestMessage: "SubmitTransactionRequest",
|
|
||||||
CmdSubmitTransactionResponseMessage: "SubmitTransactionResponse",
|
|
||||||
CmdNotifyChainChangedRequestMessage: "NotifyChainChangedRequest",
|
|
||||||
CmdNotifyChainChangedResponseMessage: "NotifyChainChangedResponse",
|
|
||||||
CmdChainChangedNotificationMessage: "ChainChangedNotification",
|
|
||||||
CmdGetBlockRequestMessage: "GetBlockRequest",
|
|
||||||
CmdGetBlockResponseMessage: "GetBlockResponse",
|
|
||||||
CmdGetSubnetworkRequestMessage: "GetSubnetworkRequest",
|
|
||||||
CmdGetSubnetworkResponseMessage: "GetSubnetworkResponse",
|
|
||||||
CmdGetChainFromBlockRequestMessage: "GetChainFromBlockRequest",
|
|
||||||
CmdGetChainFromBlockResponseMessage: "GetChainFromBlockResponse",
|
|
||||||
CmdGetBlocksRequestMessage: "GetBlocksRequest",
|
|
||||||
CmdGetBlocksResponseMessage: "GetBlocksResponse",
|
|
||||||
CmdGetBlockCountRequestMessage: "GetBlockCountRequest",
|
|
||||||
CmdGetBlockCountResponseMessage: "GetBlockCountResponse",
|
|
||||||
CmdGetBlockDAGInfoRequestMessage: "GetBlockDAGInfoRequest",
|
|
||||||
CmdGetBlockDAGInfoResponseMessage: "GetBlockDAGInfoResponse",
|
|
||||||
CmdResolveFinalityConflictRequestMessage: "ResolveFinalityConflictRequest",
|
|
||||||
CmdResolveFinalityConflictResponseMessage: "ResolveFinalityConflictResponse",
|
|
||||||
CmdNotifyFinalityConflictsRequestMessage: "NotifyFinalityConflictsRequest",
|
|
||||||
CmdNotifyFinalityConflictsResponseMessage: "NotifyFinalityConflictsResponse",
|
|
||||||
CmdFinalityConflictNotificationMessage: "FinalityConflictNotification",
|
|
||||||
CmdFinalityConflictResolvedNotificationMessage: "FinalityConflictResolvedNotification",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message is an interface that describes a kaspa message. A type that
|
// Message is an interface that describes a kaspa message. A type that
|
||||||
// implements Message has complete control over the representation of its data
|
// implements Message has complete control over the representation of its data
|
||||||
// and may therefore contain additional or fewer fields than those which
|
// and may therefore contain additional or fewer fields than those which
|
||||||
|
|||||||
@@ -21,18 +21,15 @@ import (
|
|||||||
// backing array multiple times.
|
// backing array multiple times.
|
||||||
const defaultTransactionAlloc = 2048
|
const defaultTransactionAlloc = 2048
|
||||||
|
|
||||||
// MaxMassAcceptedByBlock is the maximum total transaction mass a block may accept.
|
// MaxMassPerBlock is the maximum total transaction mass a block may have.
|
||||||
const MaxMassAcceptedByBlock = 10000000
|
const MaxMassPerBlock = 10000000
|
||||||
|
|
||||||
// MaxMassPerTx is the maximum total mass a transaction may have.
|
// MaxMassPerTx is the maximum total mass a transaction may have.
|
||||||
const MaxMassPerTx = MaxMassAcceptedByBlock / 2
|
const MaxMassPerTx = MaxMassPerBlock / 2
|
||||||
|
|
||||||
// MaxTxPerBlock is the maximum number of transactions that could
|
// MaxTxPerBlock is the maximum number of transactions that could
|
||||||
// possibly fit into a block.
|
// possibly fit into a block.
|
||||||
const MaxTxPerBlock = (MaxMassAcceptedByBlock / minTxPayload) + 1
|
const MaxTxPerBlock = (MaxMassPerBlock / minTxPayload) + 1
|
||||||
|
|
||||||
// MaxBlockParents is the maximum allowed number of parents for block.
|
|
||||||
const MaxBlockParents = 10
|
|
||||||
|
|
||||||
// TxLoc holds locator data for the offset and length of where a transaction is
|
// TxLoc holds locator data for the offset and length of where a transaction is
|
||||||
// located within a MsgBlock data buffer.
|
// located within a MsgBlock data buffer.
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// AddPeerRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type AddPeerRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Address string
|
|
||||||
IsPermanent bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *AddPeerRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdAddPeerRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAddPeerRequestMessage returns a instance of the message
|
|
||||||
func NewAddPeerRequestMessage(address string, isPermanent bool) *AddPeerRequestMessage {
|
|
||||||
return &AddPeerRequestMessage{
|
|
||||||
Address: address,
|
|
||||||
IsPermanent: isPermanent,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPeerResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type AddPeerResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *AddPeerResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdAddPeerResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAddPeerResponseMessage returns a instance of the message
|
|
||||||
func NewAddPeerResponseMessage() *AddPeerResponseMessage {
|
|
||||||
return &AddPeerResponseMessage{}
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBlockRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Hash string
|
|
||||||
SubnetworkID string
|
|
||||||
IncludeBlockHex bool
|
|
||||||
IncludeBlockVerboseData bool
|
|
||||||
IncludeTransactionVerboseData bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockRequestMessage returns a instance of the message
|
|
||||||
func NewGetBlockRequestMessage(hash string, subnetworkID string, includeBlockHex bool,
|
|
||||||
includeBlockVerboseData bool, includeTransactionVerboseData bool) *GetBlockRequestMessage {
|
|
||||||
return &GetBlockRequestMessage{
|
|
||||||
Hash: hash,
|
|
||||||
SubnetworkID: subnetworkID,
|
|
||||||
IncludeBlockHex: includeBlockHex,
|
|
||||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
|
||||||
IncludeTransactionVerboseData: includeTransactionVerboseData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
BlockHex string
|
|
||||||
BlockVerboseData *BlockVerboseData
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockResponseMessage returns a instance of the message
|
|
||||||
func NewGetBlockResponseMessage() *GetBlockResponseMessage {
|
|
||||||
return &GetBlockResponseMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockVerboseData holds verbose data about a block
|
|
||||||
type BlockVerboseData struct {
|
|
||||||
Hash string
|
|
||||||
Confirmations uint64
|
|
||||||
Size int32
|
|
||||||
BlueScore uint64
|
|
||||||
IsChainBlock bool
|
|
||||||
Version int32
|
|
||||||
VersionHex string
|
|
||||||
HashMerkleRoot string
|
|
||||||
AcceptedIDMerkleRoot string
|
|
||||||
UTXOCommitment string
|
|
||||||
TxIDs []string
|
|
||||||
TransactionVerboseData []*TransactionVerboseData
|
|
||||||
Time int64
|
|
||||||
Nonce uint64
|
|
||||||
Bits string
|
|
||||||
Difficulty float64
|
|
||||||
ParentHashes []string
|
|
||||||
SelectedParentHash string
|
|
||||||
ChildHashes []string
|
|
||||||
AcceptedBlockHashes []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransactionVerboseData holds verbose data about a transaction
|
|
||||||
type TransactionVerboseData struct {
|
|
||||||
Hex string
|
|
||||||
TxID string
|
|
||||||
Hash string
|
|
||||||
Size int32
|
|
||||||
Version int32
|
|
||||||
LockTime uint64
|
|
||||||
SubnetworkID string
|
|
||||||
Gas uint64
|
|
||||||
PayloadHash string
|
|
||||||
Payload string
|
|
||||||
TransactionVerboseInputs []*TransactionVerboseInput
|
|
||||||
TransactionVerboseOutputs []*TransactionVerboseOutput
|
|
||||||
BlockHash string
|
|
||||||
AcceptedBy string
|
|
||||||
IsInMempool bool
|
|
||||||
Time uint64
|
|
||||||
BlockTime uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransactionVerboseInput holds data about a transaction input
|
|
||||||
type TransactionVerboseInput struct {
|
|
||||||
TxID string
|
|
||||||
OutputIndex uint32
|
|
||||||
ScriptSig *ScriptSig
|
|
||||||
Sequence uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScriptSig holds data about a script signature
|
|
||||||
type ScriptSig struct {
|
|
||||||
Asm string
|
|
||||||
Hex string
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransactionVerboseOutput holds data about a transaction output
|
|
||||||
type TransactionVerboseOutput struct {
|
|
||||||
Value uint64
|
|
||||||
Index uint32
|
|
||||||
ScriptPubKey *ScriptPubKeyResult
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScriptPubKeyResult holds data about a script public key
|
|
||||||
type ScriptPubKeyResult struct {
|
|
||||||
Asm string
|
|
||||||
Hex string
|
|
||||||
Type string
|
|
||||||
Address string
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBlockCountRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockCountRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockCountRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockCountRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockCountRequestMessage returns a instance of the message
|
|
||||||
func NewGetBlockCountRequestMessage() *GetBlockCountRequestMessage {
|
|
||||||
return &GetBlockCountRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockCountResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockCountResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
BlockCount uint64
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockCountResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockCountResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockCountResponseMessage returns a instance of the message
|
|
||||||
func NewGetBlockCountResponseMessage(blockCount uint64) *GetBlockCountResponseMessage {
|
|
||||||
return &GetBlockCountResponseMessage{
|
|
||||||
BlockCount: blockCount,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBlockDAGInfoRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockDAGInfoRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockDAGInfoRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockDAGInfoRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockDAGInfoRequestMessage returns a instance of the message
|
|
||||||
func NewGetBlockDAGInfoRequestMessage() *GetBlockDAGInfoRequestMessage {
|
|
||||||
return &GetBlockDAGInfoRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockDAGInfoResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockDAGInfoResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
NetworkName string
|
|
||||||
BlockCount uint64
|
|
||||||
TipHashes []string
|
|
||||||
VirtualParentHashes []string
|
|
||||||
Difficulty float64
|
|
||||||
PastMedianTime int64
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockDAGInfoResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockDAGInfoResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockDAGInfoResponseMessage returns a instance of the message
|
|
||||||
func NewGetBlockDAGInfoResponseMessage() *GetBlockDAGInfoResponseMessage {
|
|
||||||
return &GetBlockDAGInfoResponseMessage{}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBlockTemplateRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockTemplateRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
PayAddress string
|
|
||||||
LongPollID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockTemplateRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockTemplateRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockTemplateRequestMessage returns a instance of the message
|
|
||||||
func NewGetBlockTemplateRequestMessage(payAddress string, longPollID string) *GetBlockTemplateRequestMessage {
|
|
||||||
return &GetBlockTemplateRequestMessage{
|
|
||||||
PayAddress: payAddress,
|
|
||||||
LongPollID: longPollID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockTemplateResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockTemplateResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Bits string
|
|
||||||
CurrentTime int64
|
|
||||||
ParentHashes []string
|
|
||||||
MassLimit int
|
|
||||||
Transactions []GetBlockTemplateTransactionMessage
|
|
||||||
HashMerkleRoot string
|
|
||||||
AcceptedIDMerkleRoot string
|
|
||||||
UTXOCommitment string
|
|
||||||
Version int32
|
|
||||||
LongPollID string
|
|
||||||
TargetDifficulty string
|
|
||||||
MinTime int64
|
|
||||||
MaxTime int64
|
|
||||||
MutableFields []string
|
|
||||||
NonceRange string
|
|
||||||
IsSynced bool
|
|
||||||
IsConnected bool
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockTemplateResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockTemplateResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockTemplateResponseMessage returns a instance of the message
|
|
||||||
func NewGetBlockTemplateResponseMessage() *GetBlockTemplateResponseMessage {
|
|
||||||
return &GetBlockTemplateResponseMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlockTemplateTransactionMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlockTemplateTransactionMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Data string
|
|
||||||
ID string
|
|
||||||
Depends []int64
|
|
||||||
Mass uint64
|
|
||||||
Fee uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlockTemplateTransactionMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlockTemplateTransactionMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlockTemplateTransactionMessage returns a instance of the message
|
|
||||||
func NewGetBlockTemplateTransactionMessage() *GetBlockTemplateTransactionMessage {
|
|
||||||
return &GetBlockTemplateTransactionMessage{}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBlocksRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlocksRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
LowHash string
|
|
||||||
IncludeBlockHexes bool
|
|
||||||
IncludeBlockVerboseData bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlocksRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlocksRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlocksRequestMessage returns a instance of the message
|
|
||||||
func NewGetBlocksRequestMessage(lowHash string, includeBlockHexes bool, includeBlockVerboseData bool) *GetBlocksRequestMessage {
|
|
||||||
return &GetBlocksRequestMessage{
|
|
||||||
LowHash: lowHash,
|
|
||||||
IncludeBlockHexes: includeBlockHexes,
|
|
||||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBlocksResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBlocksResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
BlockHashes []string
|
|
||||||
BlockHexes []string
|
|
||||||
BlockVerboseData []*BlockVerboseData
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBlocksResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBlocksResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBlocksResponseMessage returns a instance of the message
|
|
||||||
func NewGetBlocksResponseMessage(blockHashes []string, blockHexes []string,
|
|
||||||
blockVerboseData []*BlockVerboseData) *GetBlocksResponseMessage {
|
|
||||||
|
|
||||||
return &GetBlocksResponseMessage{
|
|
||||||
BlockHashes: blockHashes,
|
|
||||||
BlockHexes: blockHexes,
|
|
||||||
BlockVerboseData: blockVerboseData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetChainFromBlockRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetChainFromBlockRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
StartHash string
|
|
||||||
IncludeBlockVerboseData bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetChainFromBlockRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetChainFromBlockRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetChainFromBlockRequestMessage returns a instance of the message
|
|
||||||
func NewGetChainFromBlockRequestMessage(startHash string, includeBlockVerboseData bool) *GetChainFromBlockRequestMessage {
|
|
||||||
return &GetChainFromBlockRequestMessage{
|
|
||||||
StartHash: startHash,
|
|
||||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetChainFromBlockResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetChainFromBlockResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
RemovedChainBlockHashes []string
|
|
||||||
AddedChainBlocks []*ChainBlock
|
|
||||||
BlockVerboseData []*BlockVerboseData
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetChainFromBlockResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetChainFromBlockResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetChainFromBlockResponseMessage returns a instance of the message
|
|
||||||
func NewGetChainFromBlockResponseMessage(removedChainBlockHashes []string,
|
|
||||||
addedChainBlocks []*ChainBlock, blockVerboseData []*BlockVerboseData) *GetChainFromBlockResponseMessage {
|
|
||||||
|
|
||||||
return &GetChainFromBlockResponseMessage{
|
|
||||||
RemovedChainBlockHashes: removedChainBlockHashes,
|
|
||||||
AddedChainBlocks: addedChainBlocks,
|
|
||||||
BlockVerboseData: blockVerboseData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetConnectedPeerInfoRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetConnectedPeerInfoRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetConnectedPeerInfoRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetConnectedPeerInfoRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetConnectedPeerInfoRequestMessage returns a instance of the message
|
|
||||||
func NewGetConnectedPeerInfoRequestMessage() *GetConnectedPeerInfoRequestMessage {
|
|
||||||
return &GetConnectedPeerInfoRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConnectedPeerInfoResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetConnectedPeerInfoResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Infos []*GetConnectedPeerInfoMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetConnectedPeerInfoResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetConnectedPeerInfoResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetConnectedPeerInfoResponseMessage returns a instance of the message
|
|
||||||
func NewGetConnectedPeerInfoResponseMessage(infos []*GetConnectedPeerInfoMessage) *GetConnectedPeerInfoResponseMessage {
|
|
||||||
return &GetConnectedPeerInfoResponseMessage{
|
|
||||||
Infos: infos,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConnectedPeerInfoMessage holds information about a connected peer
|
|
||||||
type GetConnectedPeerInfoMessage struct {
|
|
||||||
ID string
|
|
||||||
Address string
|
|
||||||
LastPingDuration int64
|
|
||||||
SelectedTipHash string
|
|
||||||
IsSyncNode bool
|
|
||||||
IsOutbound bool
|
|
||||||
TimeOffset int64
|
|
||||||
UserAgent string
|
|
||||||
AdvertisedProtocolVersion uint32
|
|
||||||
TimeConnected int64
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetCurrentNetworkRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetCurrentNetworkRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetCurrentNetworkRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetCurrentNetworkRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetCurrentNetworkRequestMessage returns a instance of the message
|
|
||||||
func NewGetCurrentNetworkRequestMessage() *GetCurrentNetworkRequestMessage {
|
|
||||||
return &GetCurrentNetworkRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCurrentNetworkResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetCurrentNetworkResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
CurrentNetwork string
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetCurrentNetworkResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetCurrentNetworkResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetCurrentNetworkResponseMessage returns a instance of the message
|
|
||||||
func NewGetCurrentNetworkResponseMessage(currentNetwork string) *GetCurrentNetworkResponseMessage {
|
|
||||||
return &GetCurrentNetworkResponseMessage{
|
|
||||||
CurrentNetwork: currentNetwork,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetMempoolEntryRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntryRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
TxID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntryRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntryRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntryRequestMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntryRequestMessage(txID string) *GetMempoolEntryRequestMessage {
|
|
||||||
return &GetMempoolEntryRequestMessage{TxID: txID}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMempoolEntryResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntryResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntryResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntryResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntryResponseMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntryResponseMessage() *GetMempoolEntryResponseMessage {
|
|
||||||
return &GetMempoolEntryResponseMessage{}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetPeerAddressesRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetPeerAddressesRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetPeerAddressesRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetPeerAddressesRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetPeerAddressesRequestMessage returns a instance of the message
|
|
||||||
func NewGetPeerAddressesRequestMessage() *GetPeerAddressesRequestMessage {
|
|
||||||
return &GetPeerAddressesRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPeerAddressesResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetPeerAddressesResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Addresses []*GetPeerAddressesKnownAddressMessage
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetPeerAddressesResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetPeerAddressesResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetPeerAddressesResponseMessage returns a instance of the message
|
|
||||||
func NewGetPeerAddressesResponseMessage(addresses []*GetPeerAddressesKnownAddressMessage) *GetPeerAddressesResponseMessage {
|
|
||||||
return &GetPeerAddressesResponseMessage{
|
|
||||||
Addresses: addresses,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPeerAddressesKnownAddressMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetPeerAddressesKnownAddressMessage struct {
|
|
||||||
Addr string
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetSelectedTipHashRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetSelectedTipHashRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetSelectedTipHashRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetSelectedTipHashRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetSelectedTipHashRequestMessage returns a instance of the message
|
|
||||||
func NewGetSelectedTipHashRequestMessage() *GetSelectedTipHashRequestMessage {
|
|
||||||
return &GetSelectedTipHashRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSelectedTipHashResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetSelectedTipHashResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
SelectedTipHash string
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetSelectedTipHashResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetSelectedTipHashResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetSelectedTipHashResponseMessage returns a instance of the message
|
|
||||||
func NewGetSelectedTipHashResponseMessage(selectedTipHash string) *GetSelectedTipHashResponseMessage {
|
|
||||||
return &GetSelectedTipHashResponseMessage{
|
|
||||||
SelectedTipHash: selectedTipHash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetSubnetworkRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetSubnetworkRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
SubnetworkID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetSubnetworkRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetSubnetworkRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetSubnetworkRequestMessage returns a instance of the message
|
|
||||||
func NewGetSubnetworkRequestMessage(subnetworkID string) *GetSubnetworkRequestMessage {
|
|
||||||
return &GetSubnetworkRequestMessage{
|
|
||||||
SubnetworkID: subnetworkID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSubnetworkResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetSubnetworkResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
GasLimit uint64
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetSubnetworkResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetSubnetworkResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetSubnetworkResponseMessage returns a instance of the message
|
|
||||||
func NewGetSubnetworkResponseMessage(gasLimit uint64) *GetSubnetworkResponseMessage {
|
|
||||||
return &GetSubnetworkResponseMessage{
|
|
||||||
GasLimit: gasLimit,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// NotifyBlockAddedRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type NotifyBlockAddedRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *NotifyBlockAddedRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdNotifyBlockAddedRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotifyBlockAddedRequestMessage returns a instance of the message
|
|
||||||
func NewNotifyBlockAddedRequestMessage() *NotifyBlockAddedRequestMessage {
|
|
||||||
return &NotifyBlockAddedRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyBlockAddedResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type NotifyBlockAddedResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *NotifyBlockAddedResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdNotifyBlockAddedResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotifyBlockAddedResponseMessage returns a instance of the message
|
|
||||||
func NewNotifyBlockAddedResponseMessage() *NotifyBlockAddedResponseMessage {
|
|
||||||
return &NotifyBlockAddedResponseMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockAddedNotificationMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type BlockAddedNotificationMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Block *MsgBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *BlockAddedNotificationMessage) Command() MessageCommand {
|
|
||||||
return CmdBlockAddedNotificationMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBlockAddedNotificationMessage returns a instance of the message
|
|
||||||
func NewBlockAddedNotificationMessage(block *MsgBlock) *BlockAddedNotificationMessage {
|
|
||||||
return &BlockAddedNotificationMessage{
|
|
||||||
Block: block,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// NotifyChainChangedRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type NotifyChainChangedRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *NotifyChainChangedRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdNotifyChainChangedRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotifyChainChangedRequestMessage returns a instance of the message
|
|
||||||
func NewNotifyChainChangedRequestMessage() *NotifyChainChangedRequestMessage {
|
|
||||||
return &NotifyChainChangedRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyChainChangedResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type NotifyChainChangedResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *NotifyChainChangedResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdNotifyChainChangedResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotifyChainChangedResponseMessage returns a instance of the message
|
|
||||||
func NewNotifyChainChangedResponseMessage() *NotifyChainChangedResponseMessage {
|
|
||||||
return &NotifyChainChangedResponseMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChainChangedNotificationMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type ChainChangedNotificationMessage struct {
|
|
||||||
baseMessage
|
|
||||||
RemovedChainBlockHashes []string
|
|
||||||
AddedChainBlocks []*ChainBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChainBlock represents a DAG chain-block
|
|
||||||
type ChainBlock struct {
|
|
||||||
Hash string
|
|
||||||
AcceptedBlocks []*AcceptedBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcceptedBlock represents a block accepted into the DAG
|
|
||||||
type AcceptedBlock struct {
|
|
||||||
Hash string
|
|
||||||
AcceptedTxIDs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *ChainChangedNotificationMessage) Command() MessageCommand {
|
|
||||||
return CmdChainChangedNotificationMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewChainChangedNotificationMessage returns a instance of the message
|
|
||||||
func NewChainChangedNotificationMessage(removedChainBlockHashes []string,
|
|
||||||
addedChainBlocks []*ChainBlock) *ChainChangedNotificationMessage {
|
|
||||||
|
|
||||||
return &ChainChangedNotificationMessage{
|
|
||||||
RemovedChainBlockHashes: removedChainBlockHashes,
|
|
||||||
AddedChainBlocks: addedChainBlocks,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// NotifyFinalityConflictsRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type NotifyFinalityConflictsRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *NotifyFinalityConflictsRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdNotifyFinalityConflictsRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotifyFinalityConflictsRequestMessage returns a instance of the message
|
|
||||||
func NewNotifyFinalityConflictsRequestMessage() *NotifyFinalityConflictsRequestMessage {
|
|
||||||
return &NotifyFinalityConflictsRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyFinalityConflictsResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type NotifyFinalityConflictsResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *NotifyFinalityConflictsResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdNotifyFinalityConflictsResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotifyFinalityConflictsResponseMessage returns a instance of the message
|
|
||||||
func NewNotifyFinalityConflictsResponseMessage() *NotifyFinalityConflictsResponseMessage {
|
|
||||||
return &NotifyFinalityConflictsResponseMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FinalityConflictNotificationMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type FinalityConflictNotificationMessage struct {
|
|
||||||
baseMessage
|
|
||||||
ViolatingBlockHash string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *FinalityConflictNotificationMessage) Command() MessageCommand {
|
|
||||||
return CmdFinalityConflictNotificationMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFinalityConflictNotificationMessage returns a instance of the message
|
|
||||||
func NewFinalityConflictNotificationMessage(violatingBlockHash string) *FinalityConflictNotificationMessage {
|
|
||||||
return &FinalityConflictNotificationMessage{
|
|
||||||
ViolatingBlockHash: violatingBlockHash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FinalityConflictResolvedNotificationMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type FinalityConflictResolvedNotificationMessage struct {
|
|
||||||
baseMessage
|
|
||||||
FinalityBlockHash string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *FinalityConflictResolvedNotificationMessage) Command() MessageCommand {
|
|
||||||
return CmdFinalityConflictResolvedNotificationMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFinalityConflictResolvedNotificationMessage returns a instance of the message
|
|
||||||
func NewFinalityConflictResolvedNotificationMessage(finalityBlockHash string) *FinalityConflictResolvedNotificationMessage {
|
|
||||||
return &FinalityConflictResolvedNotificationMessage{
|
|
||||||
FinalityBlockHash: finalityBlockHash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// ResolveFinalityConflictRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type ResolveFinalityConflictRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
FinalityBlockHash string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *ResolveFinalityConflictRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdResolveFinalityConflictRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewResolveFinalityConflictRequestMessage returns a instance of the message
|
|
||||||
func NewResolveFinalityConflictRequestMessage(finalityBlockHash string) *ResolveFinalityConflictRequestMessage {
|
|
||||||
return &ResolveFinalityConflictRequestMessage{
|
|
||||||
FinalityBlockHash: finalityBlockHash,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveFinalityConflictResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type ResolveFinalityConflictResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *ResolveFinalityConflictResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdResolveFinalityConflictResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewResolveFinalityConflictResponseMessage returns a instance of the message
|
|
||||||
func NewResolveFinalityConflictResponseMessage() *ResolveFinalityConflictResponseMessage {
|
|
||||||
return &ResolveFinalityConflictResponseMessage{}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// SubmitBlockRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type SubmitBlockRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
BlockHex string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *SubmitBlockRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdSubmitBlockRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSubmitBlockRequestMessage returns a instance of the message
|
|
||||||
func NewSubmitBlockRequestMessage(blockHex string) *SubmitBlockRequestMessage {
|
|
||||||
return &SubmitBlockRequestMessage{
|
|
||||||
BlockHex: blockHex,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubmitBlockResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type SubmitBlockResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *SubmitBlockResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdSubmitBlockResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSubmitBlockResponseMessage returns a instance of the message
|
|
||||||
func NewSubmitBlockResponseMessage() *SubmitBlockResponseMessage {
|
|
||||||
return &SubmitBlockResponseMessage{}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// SubmitTransactionRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type SubmitTransactionRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
TransactionHex string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *SubmitTransactionRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdSubmitTransactionRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSubmitTransactionRequestMessage returns a instance of the message
|
|
||||||
func NewSubmitTransactionRequestMessage(transactionHex string) *SubmitTransactionRequestMessage {
|
|
||||||
return &SubmitTransactionRequestMessage{
|
|
||||||
TransactionHex: transactionHex,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubmitTransactionResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type SubmitTransactionResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
TxID string
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *SubmitTransactionResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdSubmitTransactionResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSubmitTransactionResponseMessage returns a instance of the message
|
|
||||||
func NewSubmitTransactionResponseMessage(txID string) *SubmitTransactionResponseMessage {
|
|
||||||
return &SubmitTransactionResponseMessage{
|
|
||||||
TxID: txID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,9 +18,6 @@ func (f *FlowContext) OnNewBlock(block *util.Block) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if f.onBlockAddedToDAGHandler != nil {
|
|
||||||
f.onBlockAddedToDAGHandler(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.broadcastTransactionsAfterBlockAdded(block, transactionsAcceptedToMempool)
|
return f.broadcastTransactionsAfterBlockAdded(block, transactionsAcceptedToMempool)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func (*FlowContext) HandleError(err error, flowName string, isStopping *uint32,
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Errorf("error from %s: %+v", flowName, err)
|
log.Errorf("error from %s: %s", flowName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if atomic.AddUint32(isStopping, 1) == 1 {
|
if atomic.AddUint32(isStopping, 1) == 1 {
|
||||||
|
|||||||
@@ -18,14 +18,6 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/util/daghash"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnBlockAddedToDAGHandler is a handler function that's triggered
|
|
||||||
// when a block is added to the DAG
|
|
||||||
type OnBlockAddedToDAGHandler func(block *util.Block)
|
|
||||||
|
|
||||||
// OnTransactionAddedToMempoolHandler is a handler function that's triggered
|
|
||||||
// when a transaction is added to the mempool
|
|
||||||
type OnTransactionAddedToMempoolHandler func()
|
|
||||||
|
|
||||||
// FlowContext holds state that is relevant to more than one flow or one peer, and allows communication between
|
// FlowContext holds state that is relevant to more than one flow or one peer, and allows communication between
|
||||||
// different flows that can be associated to different peers.
|
// different flows that can be associated to different peers.
|
||||||
type FlowContext struct {
|
type FlowContext struct {
|
||||||
@@ -36,9 +28,6 @@ type FlowContext struct {
|
|||||||
addressManager *addressmanager.AddressManager
|
addressManager *addressmanager.AddressManager
|
||||||
connectionManager *connmanager.ConnectionManager
|
connectionManager *connmanager.ConnectionManager
|
||||||
|
|
||||||
onBlockAddedToDAGHandler OnBlockAddedToDAGHandler
|
|
||||||
onTransactionAddedToMempoolHandler OnTransactionAddedToMempoolHandler
|
|
||||||
|
|
||||||
transactionsToRebroadcastLock sync.Mutex
|
transactionsToRebroadcastLock sync.Mutex
|
||||||
transactionsToRebroadcast map[daghash.TxID]*util.Tx
|
transactionsToRebroadcast map[daghash.TxID]*util.Tx
|
||||||
lastRebroadcastTime time.Time
|
lastRebroadcastTime time.Time
|
||||||
@@ -72,13 +61,3 @@ func New(cfg *config.Config, dag *blockdag.BlockDAG, addressManager *addressmana
|
|||||||
transactionsToRebroadcast: make(map[daghash.TxID]*util.Tx),
|
transactionsToRebroadcast: make(map[daghash.TxID]*util.Tx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
|
||||||
func (f *FlowContext) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler OnBlockAddedToDAGHandler) {
|
|
||||||
f.onBlockAddedToDAGHandler = onBlockAddedToDAGHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnTransactionAddedToMempoolHandler sets the onTransactionAddedToMempool handler
|
|
||||||
func (f *FlowContext) SetOnTransactionAddedToMempoolHandler(onTransactionAddedToMempoolHandler OnTransactionAddedToMempoolHandler) {
|
|
||||||
f.onTransactionAddedToMempoolHandler = onTransactionAddedToMempoolHandler
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (f *FlowContext) readyPeerConnections() []*netadapter.NetConnection {
|
|||||||
|
|
||||||
// Broadcast broadcast the given message to all the ready peers.
|
// Broadcast broadcast the given message to all the ready peers.
|
||||||
func (f *FlowContext) Broadcast(message appmessage.Message) error {
|
func (f *FlowContext) Broadcast(message appmessage.Message) error {
|
||||||
return f.netAdapter.P2PBroadcast(f.readyPeerConnections(), message)
|
return f.netAdapter.Broadcast(f.readyPeerConnections(), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peers returns the currently active peers
|
// Peers returns the currently active peers
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ func (f *FlowContext) AddTransaction(tx *util.Tx) error {
|
|||||||
|
|
||||||
f.transactionsToRebroadcast[*tx.ID()] = tx
|
f.transactionsToRebroadcast[*tx.ID()] = tx
|
||||||
inv := appmessage.NewMsgInvTransaction([]*daghash.TxID{tx.ID()})
|
inv := appmessage.NewMsgInvTransaction([]*daghash.TxID{tx.ID()})
|
||||||
|
log.Criticalf("~~~~~ FlowContext.AddTransaction() broadcasting %s", tx.ID())
|
||||||
return f.Broadcast(inv)
|
return f.Broadcast(inv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +69,3 @@ func (f *FlowContext) SharedRequestedTransactions() *relaytransactions.SharedReq
|
|||||||
func (f *FlowContext) TxPool() *mempool.TxPool {
|
func (f *FlowContext) TxPool() *mempool.TxPool {
|
||||||
return f.txPool
|
return f.txPool
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTransactionAddedToMempool notifies the handler function that a transaction
|
|
||||||
// has been added to the mempool
|
|
||||||
func (f *FlowContext) OnTransactionAddedToMempool() {
|
|
||||||
if f.onTransactionAddedToMempoolHandler != nil {
|
|
||||||
f.onTransactionAddedToMempoolHandler()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ func (flow *handleIBDFlow) runIBD() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
|
log.Debugf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
|
||||||
|
if flow.DAG().IsKnownFinalizedBlock(highestSharedBlockHash) {
|
||||||
|
return protocolerrors.Errorf(false, "cannot initiate "+
|
||||||
|
"IBD with peer %s because the highest shared chain block (%s) is "+
|
||||||
|
"below the finality point", flow.peer, highestSharedBlockHash)
|
||||||
|
}
|
||||||
|
|
||||||
return flow.downloadBlocks(highestSharedBlockHash, peerSelectedTipHash)
|
return flow.downloadBlocks(highestSharedBlockHash, peerSelectedTipHash)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ type TransactionsRelayContext interface {
|
|||||||
SharedRequestedTransactions() *SharedRequestedTransactions
|
SharedRequestedTransactions() *SharedRequestedTransactions
|
||||||
TxPool() *mempool.TxPool
|
TxPool() *mempool.TxPool
|
||||||
Broadcast(message appmessage.Message) error
|
Broadcast(message appmessage.Message) error
|
||||||
OnTransactionAddedToMempool()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type handleRelayedTransactionsFlow struct {
|
type handleRelayedTransactionsFlow struct {
|
||||||
@@ -49,6 +48,10 @@ func (flow *handleRelayedTransactionsFlow) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, txID := range inv.TxIDs {
|
||||||
|
log.Criticalf("~~~~~ handleRelayedTransactionsFlow.start() got %s", txID)
|
||||||
|
}
|
||||||
|
|
||||||
requestedIDs, err := flow.requestInvTransactions(inv)
|
requestedIDs, err := flow.requestInvTransactions(inv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -138,6 +141,7 @@ func (flow *handleRelayedTransactionsFlow) readInv() (*appmessage.MsgInvTransact
|
|||||||
func (flow *handleRelayedTransactionsFlow) broadcastAcceptedTransactions(acceptedTxs []*mempool.TxDesc) error {
|
func (flow *handleRelayedTransactionsFlow) broadcastAcceptedTransactions(acceptedTxs []*mempool.TxDesc) error {
|
||||||
idsToBroadcast := make([]*daghash.TxID, len(acceptedTxs))
|
idsToBroadcast := make([]*daghash.TxID, len(acceptedTxs))
|
||||||
for i, tx := range acceptedTxs {
|
for i, tx := range acceptedTxs {
|
||||||
|
log.Criticalf("~~~~~ broadcastAcceptedTransactions() broadcasting %s", tx.Tx.ID())
|
||||||
idsToBroadcast[i] = tx.Tx.ID()
|
idsToBroadcast[i] = tx.Tx.ID()
|
||||||
}
|
}
|
||||||
inv := appmessage.NewMsgInvTransaction(idsToBroadcast)
|
inv := appmessage.NewMsgInvTransaction(idsToBroadcast)
|
||||||
@@ -188,6 +192,7 @@ func (flow *handleRelayedTransactionsFlow) receiveTransactions(requestedTransact
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tx := util.NewTx(msgTx)
|
tx := util.NewTx(msgTx)
|
||||||
|
log.Criticalf("~~~~~ receiveTransactions() got %s", tx.ID())
|
||||||
if !tx.ID().IsEqual(expectedID) {
|
if !tx.ID().IsEqual(expectedID) {
|
||||||
return protocolerrors.Errorf(true, "expected transaction %s, but got %s",
|
return protocolerrors.Errorf(true, "expected transaction %s, but got %s",
|
||||||
expectedID, tx.ID())
|
expectedID, tx.ID())
|
||||||
@@ -219,7 +224,6 @@ func (flow *handleRelayedTransactionsFlow) receiveTransactions(requestedTransact
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flow.OnTransactionAddedToMempool()
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ func (flow *handleRequestedTransactionsFlow) start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, transactionID := range msgRequestTransactions.IDs {
|
for _, transactionID := range msgRequestTransactions.IDs {
|
||||||
|
log.Criticalf("~~~~~ handleRequestedTransactionsFlow.start() tx %s was requested", transactionID)
|
||||||
tx, ok := flow.TxPool().FetchTransaction(transactionID)
|
tx, ok := flow.TxPool().FetchTransaction(transactionID)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package rpccontext
|
package relaytransactions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||||
"github.com/kaspanet/kaspad/util/panics"
|
"github.com/kaspanet/kaspad/util/panics"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log, _ = logger.Get(logger.SubsystemTags.RPCS)
|
var log, _ = logger.Get(logger.SubsystemTags.PROT)
|
||||||
var spawn = panics.GoroutineWrapperFunc(log)
|
var spawn = panics.GoroutineWrapperFunc(log)
|
||||||
@@ -27,10 +27,20 @@ func NewManager(cfg *config.Config, dag *blockdag.BlockDAG, netAdapter *netadapt
|
|||||||
manager := Manager{
|
manager := Manager{
|
||||||
context: flowcontext.New(cfg, dag, addressManager, txPool, netAdapter, connectionManager),
|
context: flowcontext.New(cfg, dag, addressManager, txPool, netAdapter, connectionManager),
|
||||||
}
|
}
|
||||||
netAdapter.SetP2PRouterInitializer(manager.routerInitializer)
|
netAdapter.SetRouterInitializer(manager.routerInitializer)
|
||||||
return &manager, nil
|
return &manager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start starts the p2p protocol
|
||||||
|
func (m *Manager) Start() error {
|
||||||
|
return m.context.NetAdapter().Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the p2p protocol
|
||||||
|
func (m *Manager) Stop() error {
|
||||||
|
return m.context.NetAdapter().Stop()
|
||||||
|
}
|
||||||
|
|
||||||
// Peers returns the currently active peers
|
// Peers returns the currently active peers
|
||||||
func (m *Manager) Peers() []*peerpkg.Peer {
|
func (m *Manager) Peers() []*peerpkg.Peer {
|
||||||
return m.context.Peers()
|
return m.context.Peers()
|
||||||
@@ -62,13 +72,3 @@ func (m *Manager) runFlows(flows []*flow, peer *peerpkg.Peer, errChan <-chan err
|
|||||||
|
|
||||||
return <-errChan
|
return <-errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
|
||||||
func (m *Manager) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler flowcontext.OnBlockAddedToDAGHandler) {
|
|
||||||
m.context.SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnTransactionAddedToMempoolHandler sets the onTransactionAddedToMempool handler
|
|
||||||
func (m *Manager) SetOnTransactionAddedToMempoolHandler(onTransactionAddedToMempoolHandler flowcontext.OnTransactionAddedToMempoolHandler) {
|
|
||||||
m.context.SetOnTransactionAddedToMempoolHandler(onTransactionAddedToMempoolHandler)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
package rpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag/indexers"
|
|
||||||
"github.com/kaspanet/kaspad/domain/mempool"
|
|
||||||
"github.com/kaspanet/kaspad/domain/mining"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Manager is an RPC manager
|
|
||||||
type Manager struct {
|
|
||||||
context *rpccontext.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewManager creates a new RPC Manager
|
|
||||||
func NewManager(
|
|
||||||
cfg *config.Config,
|
|
||||||
netAdapter *netadapter.NetAdapter,
|
|
||||||
dag *blockdag.BlockDAG,
|
|
||||||
protocolManager *protocol.Manager,
|
|
||||||
connectionManager *connmanager.ConnectionManager,
|
|
||||||
blockTemplateGenerator *mining.BlkTmplGenerator,
|
|
||||||
mempool *mempool.TxPool,
|
|
||||||
addressManager *addressmanager.AddressManager,
|
|
||||||
acceptanceIndex *indexers.AcceptanceIndex) *Manager {
|
|
||||||
|
|
||||||
manager := Manager{
|
|
||||||
context: rpccontext.NewContext(
|
|
||||||
cfg,
|
|
||||||
netAdapter,
|
|
||||||
dag,
|
|
||||||
protocolManager,
|
|
||||||
connectionManager,
|
|
||||||
blockTemplateGenerator,
|
|
||||||
mempool,
|
|
||||||
addressManager,
|
|
||||||
acceptanceIndex,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
netAdapter.SetRPCRouterInitializer(manager.routerInitializer)
|
|
||||||
|
|
||||||
return &manager
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyBlockAddedToDAG notifies the manager that a block has been added to the DAG
|
|
||||||
func (m *Manager) NotifyBlockAddedToDAG(block *util.Block) {
|
|
||||||
m.context.BlockTemplateState.NotifyBlockAdded(block)
|
|
||||||
|
|
||||||
notification := appmessage.NewBlockAddedNotificationMessage(block.MsgBlock())
|
|
||||||
m.context.NotificationManager.NotifyBlockAdded(notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyChainChanged notifies the manager that the DAG's selected parent chain has changed
|
|
||||||
func (m *Manager) NotifyChainChanged(removedChainBlockHashes []*daghash.Hash, addedChainBlockHashes []*daghash.Hash) error {
|
|
||||||
addedChainBlocks, err := m.context.CollectChainBlocks(addedChainBlockHashes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
removedChainBlockHashStrings := make([]string, len(removedChainBlockHashes))
|
|
||||||
for i, removedChainBlockHash := range removedChainBlockHashes {
|
|
||||||
removedChainBlockHashStrings[i] = removedChainBlockHash.String()
|
|
||||||
}
|
|
||||||
notification := appmessage.NewChainChangedNotificationMessage(removedChainBlockHashStrings, addedChainBlocks)
|
|
||||||
m.context.NotificationManager.NotifyChainChanged(notification)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyFinalityConflict notifies the manager that there's a finality conflict in the DAG
|
|
||||||
func (m *Manager) NotifyFinalityConflict(violatingBlockHash string) error {
|
|
||||||
notification := appmessage.NewFinalityConflictNotificationMessage(violatingBlockHash)
|
|
||||||
m.context.NotificationManager.NotifyFinalityConflict(notification)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyFinalityConflictResolved notifies the manager that a finality conflict in the DAG has been resolved
|
|
||||||
func (m *Manager) NotifyFinalityConflictResolved(finalityBlockHash string) error {
|
|
||||||
notification := appmessage.NewFinalityConflictResolvedNotificationMessage(finalityBlockHash)
|
|
||||||
m.context.NotificationManager.NotifyFinalityConflictResolved(notification)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyTransactionAddedToMempool notifies the manager that a transaction has been added to the mempool
|
|
||||||
func (m *Manager) NotifyTransactionAddedToMempool() {
|
|
||||||
m.context.BlockTemplateState.NotifyMempoolTx()
|
|
||||||
}
|
|
||||||
100
app/rpc/rpc.go
100
app/rpc/rpc.go
@@ -1,100 +0,0 @@
|
|||||||
package rpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpchandlers"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type handler func(context *rpccontext.Context, router *router.Router, request appmessage.Message) (appmessage.Message, error)
|
|
||||||
|
|
||||||
var handlers = map[appmessage.MessageCommand]handler{
|
|
||||||
appmessage.CmdGetCurrentNetworkRequestMessage: rpchandlers.HandleGetCurrentNetwork,
|
|
||||||
appmessage.CmdSubmitBlockRequestMessage: rpchandlers.HandleSubmitBlock,
|
|
||||||
appmessage.CmdGetBlockTemplateRequestMessage: rpchandlers.HandleGetBlockTemplate,
|
|
||||||
appmessage.CmdNotifyBlockAddedRequestMessage: rpchandlers.HandleNotifyBlockAdded,
|
|
||||||
appmessage.CmdGetPeerAddressesRequestMessage: rpchandlers.HandleGetPeerAddresses,
|
|
||||||
appmessage.CmdGetSelectedTipHashRequestMessage: rpchandlers.HandleGetSelectedTipHash,
|
|
||||||
appmessage.CmdGetMempoolEntryRequestMessage: rpchandlers.HandleGetMempoolEntry,
|
|
||||||
appmessage.CmdGetConnectedPeerInfoRequestMessage: rpchandlers.HandleGetConnectedPeerInfo,
|
|
||||||
appmessage.CmdAddPeerRequestMessage: rpchandlers.HandleAddPeer,
|
|
||||||
appmessage.CmdSubmitTransactionRequestMessage: rpchandlers.HandleSubmitTransaction,
|
|
||||||
appmessage.CmdNotifyChainChangedRequestMessage: rpchandlers.HandleNotifyChainChanged,
|
|
||||||
appmessage.CmdGetBlockRequestMessage: rpchandlers.HandleGetBlock,
|
|
||||||
appmessage.CmdGetSubnetworkRequestMessage: rpchandlers.HandleGetSubnetwork,
|
|
||||||
appmessage.CmdGetChainFromBlockRequestMessage: rpchandlers.HandleGetChainFromBlock,
|
|
||||||
appmessage.CmdGetBlocksRequestMessage: rpchandlers.HandleGetBlocks,
|
|
||||||
appmessage.CmdGetBlockCountRequestMessage: rpchandlers.HandleGetBlockCount,
|
|
||||||
appmessage.CmdGetBlockDAGInfoRequestMessage: rpchandlers.HandleGetBlockDAGInfo,
|
|
||||||
appmessage.CmdResolveFinalityConflictRequestMessage: rpchandlers.HandleResolveFinalityConflict,
|
|
||||||
appmessage.CmdNotifyFinalityConflictsRequestMessage: rpchandlers.HandleNotifyFinalityConflicts,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) routerInitializer(router *router.Router, netConnection *netadapter.NetConnection) {
|
|
||||||
messageTypes := make([]appmessage.MessageCommand, 0, len(handlers))
|
|
||||||
for messageType := range handlers {
|
|
||||||
messageTypes = append(messageTypes, messageType)
|
|
||||||
}
|
|
||||||
incomingRoute, err := router.AddIncomingRoute(messageTypes)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
spawn("routerInitializer-handleIncomingMessages", func() {
|
|
||||||
err := m.handleIncomingMessages(router, incomingRoute)
|
|
||||||
m.handleError(err, netConnection)
|
|
||||||
})
|
|
||||||
|
|
||||||
notificationListener := m.context.NotificationManager.AddListener(router)
|
|
||||||
spawn("routerInitializer-handleOutgoingNotifications", func() {
|
|
||||||
defer m.context.NotificationManager.RemoveListener(router)
|
|
||||||
|
|
||||||
err := m.handleOutgoingNotifications(notificationListener)
|
|
||||||
m.handleError(err, netConnection)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) handleIncomingMessages(router *router.Router, incomingRoute *router.Route) error {
|
|
||||||
outgoingRoute := router.OutgoingRoute()
|
|
||||||
for {
|
|
||||||
request, err := incomingRoute.Dequeue()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
handler, ok := handlers[request.Command()]
|
|
||||||
if !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
response, err := handler(m.context, router, request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = outgoingRoute.Enqueue(response)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) handleOutgoingNotifications(notificationListener *rpccontext.NotificationListener) error {
|
|
||||||
for {
|
|
||||||
err := notificationListener.ProcessNextNotification()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection) {
|
|
||||||
if errors.Is(err, router.ErrTimeout) {
|
|
||||||
log.Warnf("Got timeout from %s. Disconnecting...", netConnection)
|
|
||||||
netConnection.Disconnect()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if errors.Is(err, router.ErrRouteClosed) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
@@ -1,476 +0,0 @@
|
|||||||
package rpccontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/domain/mining"
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
|
||||||
"github.com/kaspanet/kaspad/util/random"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// blockTemplateNonceRange is two 64-bit big-endian hexadecimal integers which
|
|
||||||
// represent the valid ranges of nonces returned by the getBlockTemplate
|
|
||||||
// RPC.
|
|
||||||
blockTemplateNonceRange = "000000000000ffffffffffff"
|
|
||||||
|
|
||||||
// blockTemplateRegenerateSeconds is the number of seconds that must pass before
|
|
||||||
// a new template is generated when the parent block hashes has not
|
|
||||||
// changed and there have been changes to the available transactions
|
|
||||||
// in the memory pool.
|
|
||||||
blockTemplateRegenerateSeconds = 60
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// blockTemplateMutableFields are the manipulations the server allows to be made
|
|
||||||
// to block templates generated by the getBlockTemplate RPC. It is
|
|
||||||
// declared here to avoid the overhead of creating the slice on every
|
|
||||||
// invocation for constant data.
|
|
||||||
blockTemplateMutableFields = []string{
|
|
||||||
"time", "transactions/add", "parentblock", "coinbase/append",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// BlockTemplateState houses state that is used in between multiple RPC invocations to
|
|
||||||
// getBlockTemplate.
|
|
||||||
type BlockTemplateState struct {
|
|
||||||
sync.Mutex
|
|
||||||
|
|
||||||
context *Context
|
|
||||||
|
|
||||||
lastTxUpdate mstime.Time
|
|
||||||
lastGenerated mstime.Time
|
|
||||||
virtualParentHashes []*daghash.Hash
|
|
||||||
minTimestamp mstime.Time
|
|
||||||
template *mining.BlockTemplate
|
|
||||||
notifyMap map[string]map[int64]chan struct{}
|
|
||||||
payAddress util.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBlockTemplateState returns a new instance of a BlockTemplateState with all internal
|
|
||||||
// fields initialized and ready to use.
|
|
||||||
func NewBlockTemplateState(context *Context) *BlockTemplateState {
|
|
||||||
return &BlockTemplateState{
|
|
||||||
context: context,
|
|
||||||
notifyMap: make(map[string]map[int64]chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates the block template state
|
|
||||||
func (bt *BlockTemplateState) Update(payAddress util.Address) error {
|
|
||||||
generator := bt.context.BlockTemplateGenerator
|
|
||||||
lastTxUpdate := generator.TxSource().LastUpdated()
|
|
||||||
if lastTxUpdate.IsZero() {
|
|
||||||
lastTxUpdate = mstime.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a new block template when the current best block has
|
|
||||||
// changed or the transactions in the memory pool have been updated and
|
|
||||||
// it has been at least gbtRegenerateSecond since the last template was
|
|
||||||
// generated.
|
|
||||||
var msgBlock *appmessage.MsgBlock
|
|
||||||
var targetDifficulty string
|
|
||||||
virtualParentHashes := bt.context.DAG.VirtualParentHashes()
|
|
||||||
template := bt.template
|
|
||||||
if template == nil || bt.virtualParentHashes == nil ||
|
|
||||||
!daghash.AreEqual(bt.virtualParentHashes, virtualParentHashes) ||
|
|
||||||
bt.payAddress.String() != payAddress.String() ||
|
|
||||||
(bt.lastTxUpdate != lastTxUpdate &&
|
|
||||||
mstime.Now().After(bt.lastGenerated.Add(time.Second*
|
|
||||||
blockTemplateRegenerateSeconds))) {
|
|
||||||
|
|
||||||
// Reset the previous best hash the block template was generated
|
|
||||||
// against so any errors below cause the next invocation to try
|
|
||||||
// again.
|
|
||||||
bt.virtualParentHashes = nil
|
|
||||||
|
|
||||||
// Create a new block template that has a coinbase which anyone
|
|
||||||
// can redeem. This is only acceptable because the returned
|
|
||||||
// block template doesn't include the coinbase, so the caller
|
|
||||||
// will ultimately create their own coinbase which pays to the
|
|
||||||
// appropriate address(es).
|
|
||||||
|
|
||||||
extraNonce, err := random.Uint64()
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to randomize extra nonce")
|
|
||||||
}
|
|
||||||
|
|
||||||
blockTemplate, err := generator.NewBlockTemplate(payAddress, extraNonce)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to create new block template")
|
|
||||||
}
|
|
||||||
template = blockTemplate
|
|
||||||
msgBlock = template.Block
|
|
||||||
targetDifficulty = fmt.Sprintf("%064x", util.CompactToBig(msgBlock.Header.Bits))
|
|
||||||
|
|
||||||
// Get the minimum allowed timestamp for the block based on the
|
|
||||||
// median timestamp of the last several blocks per the DAG
|
|
||||||
// consensus rules.
|
|
||||||
minTimestamp := bt.context.DAG.NextBlockMinimumTime()
|
|
||||||
|
|
||||||
// Update work state to ensure another block template isn't
|
|
||||||
// generated until needed.
|
|
||||||
bt.template = template
|
|
||||||
bt.lastGenerated = mstime.Now()
|
|
||||||
bt.lastTxUpdate = lastTxUpdate
|
|
||||||
bt.virtualParentHashes = virtualParentHashes
|
|
||||||
bt.minTimestamp = minTimestamp
|
|
||||||
bt.payAddress = payAddress
|
|
||||||
|
|
||||||
log.Debugf("Generated block template (timestamp %s, "+
|
|
||||||
"target %s, merkle root %s)",
|
|
||||||
msgBlock.Header.Timestamp, targetDifficulty,
|
|
||||||
msgBlock.Header.HashMerkleRoot)
|
|
||||||
|
|
||||||
// Notify any clients that are long polling about the new
|
|
||||||
// template.
|
|
||||||
bt.notifyLongPollers(virtualParentHashes, lastTxUpdate)
|
|
||||||
} else {
|
|
||||||
// At this point, there is a saved block template and another
|
|
||||||
// request for a template was made, but either the available
|
|
||||||
// transactions haven't change or it hasn't been long enough to
|
|
||||||
// trigger a new block template to be generated. So, update the
|
|
||||||
// existing block template.
|
|
||||||
|
|
||||||
// Set locals for convenience.
|
|
||||||
msgBlock = template.Block
|
|
||||||
targetDifficulty = fmt.Sprintf("%064x",
|
|
||||||
util.CompactToBig(msgBlock.Header.Bits))
|
|
||||||
|
|
||||||
// Update the time of the block template to the current time
|
|
||||||
// while accounting for the median time of the past several
|
|
||||||
// blocks per the DAG consensus rules.
|
|
||||||
err := generator.UpdateBlockTime(msgBlock)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to update block time")
|
|
||||||
}
|
|
||||||
msgBlock.Header.Nonce = 0
|
|
||||||
|
|
||||||
log.Debugf("Updated block template (timestamp %s, "+
|
|
||||||
"target %s)", msgBlock.Header.Timestamp,
|
|
||||||
targetDifficulty)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response builds a GetBlockTemplateResponseMessage from the current state
|
|
||||||
func (bt *BlockTemplateState) Response() (*appmessage.GetBlockTemplateResponseMessage, error) {
|
|
||||||
dag := bt.context.DAG
|
|
||||||
// Ensure the timestamps are still in valid range for the template.
|
|
||||||
// This should really only ever happen if the local clock is changed
|
|
||||||
// after the template is generated, but it's important to avoid serving
|
|
||||||
// block templates that will be delayed on other nodes.
|
|
||||||
template := bt.template
|
|
||||||
msgBlock := template.Block
|
|
||||||
header := &msgBlock.Header
|
|
||||||
adjustedTime := dag.Now()
|
|
||||||
maxTime := adjustedTime.Add(time.Millisecond * time.Duration(dag.TimestampDeviationTolerance))
|
|
||||||
if header.Timestamp.After(maxTime) {
|
|
||||||
errorMessage := &appmessage.GetBlockTemplateResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("The template time is after the "+
|
|
||||||
"maximum allowed time for a block - template "+
|
|
||||||
"time %s, maximum time %s", adjustedTime,
|
|
||||||
maxTime)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert each transaction in the block template to a template result
|
|
||||||
// transaction. The result does not include the coinbase, so notice
|
|
||||||
// the adjustments to the various lengths and indices.
|
|
||||||
numTx := len(msgBlock.Transactions)
|
|
||||||
transactions := make([]appmessage.GetBlockTemplateTransactionMessage, 0, numTx-1)
|
|
||||||
txIndex := make(map[daghash.TxID]int64, numTx)
|
|
||||||
for i, tx := range msgBlock.Transactions {
|
|
||||||
txID := tx.TxID()
|
|
||||||
txIndex[*txID] = int64(i)
|
|
||||||
|
|
||||||
// Create an array of 1-based indices to transactions that come
|
|
||||||
// before this one in the transactions list which this one
|
|
||||||
// depends on. This is necessary since the created block must
|
|
||||||
// ensure proper ordering of the dependencies. A map is used
|
|
||||||
// before creating the final array to prevent duplicate entries
|
|
||||||
// when multiple inputs reference the same transaction.
|
|
||||||
dependsMap := make(map[int64]struct{})
|
|
||||||
for _, txIn := range tx.TxIn {
|
|
||||||
if idx, ok := txIndex[txIn.PreviousOutpoint.TxID]; ok {
|
|
||||||
dependsMap[idx] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
depends := make([]int64, 0, len(dependsMap))
|
|
||||||
for idx := range dependsMap {
|
|
||||||
depends = append(depends, idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize the transaction for later conversion to hex.
|
|
||||||
txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
|
||||||
if err := tx.Serialize(txBuf); err != nil {
|
|
||||||
errorMessage := &appmessage.GetBlockTemplateResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Failed to serialize transaction: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
resultTx := appmessage.GetBlockTemplateTransactionMessage{
|
|
||||||
Data: hex.EncodeToString(txBuf.Bytes()),
|
|
||||||
ID: txID.String(),
|
|
||||||
Depends: depends,
|
|
||||||
Mass: template.TxMasses[i],
|
|
||||||
Fee: template.Fees[i],
|
|
||||||
}
|
|
||||||
transactions = append(transactions, resultTx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the block template reply. Note that following mutations are
|
|
||||||
// implied by the included or omission of fields:
|
|
||||||
// Including MinTime -> time/decrement
|
|
||||||
// Omitting CoinbaseTxn -> coinbase, generation
|
|
||||||
targetDifficulty := fmt.Sprintf("%064x", util.CompactToBig(header.Bits))
|
|
||||||
longPollID := bt.encodeLongPollID(bt.virtualParentHashes, bt.payAddress, bt.lastGenerated)
|
|
||||||
|
|
||||||
// Check whether this node is synced with the rest of of the
|
|
||||||
// network. There's almost never a good reason to mine on top
|
|
||||||
// of an unsynced DAG, and miners are generally expected not to
|
|
||||||
// mine when isSynced is false.
|
|
||||||
// This is not a straight-up error because the choice of whether
|
|
||||||
// to mine or not is the responsibility of the miner rather
|
|
||||||
// than the node's.
|
|
||||||
isSynced := bt.context.BlockTemplateGenerator.IsSynced()
|
|
||||||
isConnected := len(bt.context.ProtocolManager.Peers()) > 0
|
|
||||||
|
|
||||||
reply := appmessage.GetBlockTemplateResponseMessage{
|
|
||||||
Bits: strconv.FormatInt(int64(header.Bits), 16),
|
|
||||||
CurrentTime: header.Timestamp.UnixMilliseconds(),
|
|
||||||
ParentHashes: daghash.Strings(header.ParentHashes),
|
|
||||||
MassLimit: appmessage.MaxMassAcceptedByBlock,
|
|
||||||
Transactions: transactions,
|
|
||||||
HashMerkleRoot: header.HashMerkleRoot.String(),
|
|
||||||
AcceptedIDMerkleRoot: header.AcceptedIDMerkleRoot.String(),
|
|
||||||
UTXOCommitment: header.UTXOCommitment.String(),
|
|
||||||
Version: header.Version,
|
|
||||||
LongPollID: longPollID,
|
|
||||||
TargetDifficulty: targetDifficulty,
|
|
||||||
MinTime: bt.minTimestamp.UnixMilliseconds(),
|
|
||||||
MaxTime: maxTime.UnixMilliseconds(),
|
|
||||||
MutableFields: blockTemplateMutableFields,
|
|
||||||
NonceRange: blockTemplateNonceRange,
|
|
||||||
IsSynced: isSynced,
|
|
||||||
IsConnected: isConnected,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &reply, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// notifyLongPollers notifies any channels that have been registered to be
|
|
||||||
// notified when block templates are stale.
|
|
||||||
//
|
|
||||||
// This function MUST be called with the state locked.
|
|
||||||
func (bt *BlockTemplateState) notifyLongPollers(parentHashes []*daghash.Hash, lastGenerated mstime.Time) {
|
|
||||||
// Notify anything that is waiting for a block template update from
|
|
||||||
// hashes which are not the current parent hashes.
|
|
||||||
parentHashesStr := daghash.JoinHashesStrings(parentHashes, "")
|
|
||||||
for hashesStr, channels := range bt.notifyMap {
|
|
||||||
if hashesStr != parentHashesStr {
|
|
||||||
for _, c := range channels {
|
|
||||||
close(c)
|
|
||||||
}
|
|
||||||
delete(bt.notifyMap, hashesStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return now if the provided last generated timestamp has not been
|
|
||||||
// initialized.
|
|
||||||
if lastGenerated.IsZero() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return now if there is nothing registered for updates to the current
|
|
||||||
// best block hash.
|
|
||||||
channels, ok := bt.notifyMap[parentHashesStr]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify anything that is waiting for a block template update from a
|
|
||||||
// block template generated before the most recently generated block
|
|
||||||
// template.
|
|
||||||
lastGeneratedUnix := lastGenerated.UnixSeconds()
|
|
||||||
for lastGen, c := range channels {
|
|
||||||
if lastGen < lastGeneratedUnix {
|
|
||||||
close(c)
|
|
||||||
delete(channels, lastGen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the entry altogether if there are no more registered
|
|
||||||
// channels.
|
|
||||||
if len(channels) == 0 {
|
|
||||||
delete(bt.notifyMap, parentHashesStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyBlockAdded uses the newly-added block to notify any long poll
|
|
||||||
// clients with a new block template when their existing block template is
|
|
||||||
// stale due to the newly added block.
|
|
||||||
func (bt *BlockTemplateState) NotifyBlockAdded(block *util.Block) {
|
|
||||||
spawn("BlockTemplateState.NotifyBlockAdded", func() {
|
|
||||||
bt.Lock()
|
|
||||||
defer bt.Unlock()
|
|
||||||
|
|
||||||
bt.notifyLongPollers(block.MsgBlock().Header.ParentHashes, bt.lastTxUpdate)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyMempoolTx uses the new last updated time for the transaction memory
|
|
||||||
// pool to notify any long poll clients with a new block template when their
|
|
||||||
// existing block template is stale due to enough time passing and the contents
|
|
||||||
// of the memory pool changing.
|
|
||||||
func (bt *BlockTemplateState) NotifyMempoolTx() {
|
|
||||||
lastUpdated := bt.context.Mempool.LastUpdated()
|
|
||||||
spawn("BlockTemplateState", func() {
|
|
||||||
bt.Lock()
|
|
||||||
defer bt.Unlock()
|
|
||||||
|
|
||||||
// No need to notify anything if no block templates have been generated
|
|
||||||
// yet.
|
|
||||||
if bt.virtualParentHashes == nil || bt.lastGenerated.IsZero() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if mstime.Now().After(bt.lastGenerated.Add(time.Second *
|
|
||||||
blockTemplateRegenerateSeconds)) {
|
|
||||||
|
|
||||||
bt.notifyLongPollers(bt.virtualParentHashes, lastUpdated)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockTemplateOrLongPollChan returns a block template if the
|
|
||||||
// template identified by the provided long poll ID is stale or
|
|
||||||
// invalid. Otherwise, it returns a channel that will notify
|
|
||||||
// when there's a more current template.
|
|
||||||
func (bt *BlockTemplateState) BlockTemplateOrLongPollChan(longPollID string,
|
|
||||||
payAddress util.Address) (*appmessage.GetBlockTemplateResponseMessage, chan struct{}, error) {
|
|
||||||
|
|
||||||
bt.Lock()
|
|
||||||
defer bt.Unlock()
|
|
||||||
|
|
||||||
if err := bt.Update(payAddress); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just return the current block template if the long poll ID provided by
|
|
||||||
// the caller is invalid.
|
|
||||||
parentHashes, lastGenerated, err := bt.decodeLongPollID(longPollID)
|
|
||||||
if err != nil {
|
|
||||||
result, err := bt.Response()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the block template now if the specific block template
|
|
||||||
// identified by the long poll ID no longer matches the current block
|
|
||||||
// template as this means the provided template is stale.
|
|
||||||
areHashesEqual := daghash.AreEqual(bt.template.Block.Header.ParentHashes, parentHashes)
|
|
||||||
if !areHashesEqual ||
|
|
||||||
lastGenerated != bt.lastGenerated.UnixSeconds() {
|
|
||||||
|
|
||||||
// Include whether or not it is valid to submit work against the
|
|
||||||
// old block template depending on whether or not a solution has
|
|
||||||
// already been found and added to the block DAG.
|
|
||||||
result, err := bt.Response()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the parent hashes and last generated time for notifications
|
|
||||||
// Get a channel that will be notified when the template associated with
|
|
||||||
// the provided ID is stale and a new block template should be returned to
|
|
||||||
// the caller.
|
|
||||||
longPollChan := bt.templateUpdateChan(parentHashes, lastGenerated)
|
|
||||||
return nil, longPollChan, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// templateUpdateChan returns a channel that will be closed once the block
|
|
||||||
// template associated with the passed parent hashes and last generated time
|
|
||||||
// is stale. The function will return existing channels for duplicate
|
|
||||||
// parameters which allows multiple clients to wait for the same block template
|
|
||||||
// without requiring a different channel for each client.
|
|
||||||
//
|
|
||||||
// This function MUST be called with the state locked.
|
|
||||||
func (bt *BlockTemplateState) templateUpdateChan(parentHashes []*daghash.Hash, lastGenerated int64) chan struct{} {
|
|
||||||
parentHashesStr := daghash.JoinHashesStrings(parentHashes, "")
|
|
||||||
// Either get the current list of channels waiting for updates about
|
|
||||||
// changes to block template for the parent hashes or create a new one.
|
|
||||||
channels, ok := bt.notifyMap[parentHashesStr]
|
|
||||||
if !ok {
|
|
||||||
m := make(map[int64]chan struct{})
|
|
||||||
bt.notifyMap[parentHashesStr] = m
|
|
||||||
channels = m
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current channel associated with the time the block template
|
|
||||||
// was last generated or create a new one.
|
|
||||||
c, ok := channels[lastGenerated]
|
|
||||||
if !ok {
|
|
||||||
c = make(chan struct{})
|
|
||||||
channels[lastGenerated] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodeLongPollID encodes the passed details into an ID that can be used to
|
|
||||||
// uniquely identify a block template.
|
|
||||||
func (bt *BlockTemplateState) encodeLongPollID(parentHashes []*daghash.Hash, miningAddress util.Address, lastGenerated mstime.Time) string {
|
|
||||||
return fmt.Sprintf("%s-%s-%d", daghash.JoinHashesStrings(parentHashes, ""), miningAddress, lastGenerated.UnixSeconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
// decodeLongPollID decodes an ID that is used to uniquely identify a block
|
|
||||||
// template. This is mainly used as a mechanism to track when to update clients
|
|
||||||
// that are using long polling for block templates. The ID consists of the
|
|
||||||
// parent blocks hashes for the associated template and the time the associated
|
|
||||||
// template was generated.
|
|
||||||
func (bt *BlockTemplateState) decodeLongPollID(longPollID string) ([]*daghash.Hash, int64, error) {
|
|
||||||
fields := strings.Split(longPollID, "-")
|
|
||||||
if len(fields) != 2 {
|
|
||||||
return nil, 0, errors.New("decodeLongPollID: invalid number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
parentHashesStr := fields[0]
|
|
||||||
if len(parentHashesStr)%daghash.HashSize != 0 {
|
|
||||||
return nil, 0, errors.New("decodeLongPollID: invalid parent hashes format")
|
|
||||||
}
|
|
||||||
numberOfHashes := len(parentHashesStr) / daghash.HashSize
|
|
||||||
|
|
||||||
parentHashes := make([]*daghash.Hash, 0, numberOfHashes)
|
|
||||||
|
|
||||||
for i := 0; i < len(parentHashesStr); i += daghash.HashSize {
|
|
||||||
hash, err := daghash.NewHashFromStr(parentHashesStr[i : i+daghash.HashSize])
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, errors.Errorf("decodeLongPollID: NewHashFromStr: %s", err)
|
|
||||||
}
|
|
||||||
parentHashes = append(parentHashes, hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
lastGenerated, err := strconv.ParseInt(fields[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, errors.Errorf("decodeLongPollID: Cannot parse timestamp %s: %s", fields[1], err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return parentHashes, lastGenerated, nil
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package rpccontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CollectChainBlocks creates a slice of chain blocks from the given hashes
|
|
||||||
func (ctx *Context) CollectChainBlocks(hashes []*daghash.Hash) ([]*appmessage.ChainBlock, error) {
|
|
||||||
chainBlocks := make([]*appmessage.ChainBlock, 0, len(hashes))
|
|
||||||
for _, hash := range hashes {
|
|
||||||
acceptanceData, err := ctx.AcceptanceIndex.TxsAcceptanceData(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Errorf("could not retrieve acceptance data for block %s", hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
acceptedBlocks := make([]*appmessage.AcceptedBlock, 0, len(acceptanceData))
|
|
||||||
for _, blockAcceptanceData := range acceptanceData {
|
|
||||||
acceptedTxIds := make([]string, 0, len(blockAcceptanceData.TxAcceptanceData))
|
|
||||||
for _, txAcceptanceData := range blockAcceptanceData.TxAcceptanceData {
|
|
||||||
if txAcceptanceData.IsAccepted {
|
|
||||||
acceptedTxIds = append(acceptedTxIds, txAcceptanceData.Tx.ID().String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acceptedBlock := &appmessage.AcceptedBlock{
|
|
||||||
Hash: blockAcceptanceData.BlockHash.String(),
|
|
||||||
AcceptedTxIDs: acceptedTxIds,
|
|
||||||
}
|
|
||||||
acceptedBlocks = append(acceptedBlocks, acceptedBlock)
|
|
||||||
}
|
|
||||||
|
|
||||||
chainBlock := &appmessage.ChainBlock{
|
|
||||||
Hash: hash.String(),
|
|
||||||
AcceptedBlocks: acceptedBlocks,
|
|
||||||
}
|
|
||||||
chainBlocks = append(chainBlocks, chainBlock)
|
|
||||||
}
|
|
||||||
return chainBlocks, nil
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package rpccontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol"
|
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag/indexers"
|
|
||||||
"github.com/kaspanet/kaspad/domain/mempool"
|
|
||||||
"github.com/kaspanet/kaspad/domain/mining"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Context represents the RPC context
|
|
||||||
type Context struct {
|
|
||||||
Config *config.Config
|
|
||||||
NetAdapter *netadapter.NetAdapter
|
|
||||||
DAG *blockdag.BlockDAG
|
|
||||||
ProtocolManager *protocol.Manager
|
|
||||||
ConnectionManager *connmanager.ConnectionManager
|
|
||||||
BlockTemplateGenerator *mining.BlkTmplGenerator
|
|
||||||
Mempool *mempool.TxPool
|
|
||||||
AddressManager *addressmanager.AddressManager
|
|
||||||
AcceptanceIndex *indexers.AcceptanceIndex
|
|
||||||
|
|
||||||
BlockTemplateState *BlockTemplateState
|
|
||||||
NotificationManager *NotificationManager
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewContext creates a new RPC context
|
|
||||||
func NewContext(
|
|
||||||
cfg *config.Config,
|
|
||||||
netAdapter *netadapter.NetAdapter,
|
|
||||||
dag *blockdag.BlockDAG,
|
|
||||||
protocolManager *protocol.Manager,
|
|
||||||
connectionManager *connmanager.ConnectionManager,
|
|
||||||
blockTemplateGenerator *mining.BlkTmplGenerator,
|
|
||||||
mempool *mempool.TxPool,
|
|
||||||
addressManager *addressmanager.AddressManager,
|
|
||||||
acceptanceIndex *indexers.AcceptanceIndex) *Context {
|
|
||||||
context := &Context{
|
|
||||||
Config: cfg,
|
|
||||||
NetAdapter: netAdapter,
|
|
||||||
DAG: dag,
|
|
||||||
ProtocolManager: protocolManager,
|
|
||||||
ConnectionManager: connectionManager,
|
|
||||||
BlockTemplateGenerator: blockTemplateGenerator,
|
|
||||||
Mempool: mempool,
|
|
||||||
AddressManager: addressManager,
|
|
||||||
AcceptanceIndex: acceptanceIndex,
|
|
||||||
}
|
|
||||||
context.BlockTemplateState = NewBlockTemplateState(context)
|
|
||||||
context.NotificationManager = NewNotificationManager()
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
package rpccontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NotificationManager manages notifications for the RPC
|
|
||||||
type NotificationManager struct {
|
|
||||||
sync.RWMutex
|
|
||||||
listeners map[*router.Router]*NotificationListener
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnBlockAddedListener is a listener function for when a block is added to the DAG
|
|
||||||
type OnBlockAddedListener func(notification *appmessage.BlockAddedNotificationMessage) error
|
|
||||||
|
|
||||||
// OnChainChangedListener is a listener function for when the DAG's selected parent chain changes
|
|
||||||
type OnChainChangedListener func(notification *appmessage.ChainChangedNotificationMessage) error
|
|
||||||
|
|
||||||
// OnFinalityConflictListener is a listener function for when there's a finality conflict in the DAG
|
|
||||||
type OnFinalityConflictListener func(notification *appmessage.FinalityConflictNotificationMessage) error
|
|
||||||
|
|
||||||
// OnFinalityConflictResolvedListener is a listener function for when a finality conflict in the DAG has been resolved
|
|
||||||
type OnFinalityConflictResolvedListener func(notification *appmessage.FinalityConflictResolvedNotificationMessage) error
|
|
||||||
|
|
||||||
// NotificationListener represents a registered RPC notification listener
|
|
||||||
type NotificationListener struct {
|
|
||||||
onBlockAddedListener OnBlockAddedListener
|
|
||||||
onBlockAddedNotificationChan chan *appmessage.BlockAddedNotificationMessage
|
|
||||||
onChainChangedListener OnChainChangedListener
|
|
||||||
onChainChangedNotificationChan chan *appmessage.ChainChangedNotificationMessage
|
|
||||||
onFinalityConflictListener OnFinalityConflictListener
|
|
||||||
onFinalityConflictNotificationChan chan *appmessage.FinalityConflictNotificationMessage
|
|
||||||
onFinalityConflictResolvedListener OnFinalityConflictResolvedListener
|
|
||||||
onFinalityConflictResolvedNotificationChan chan *appmessage.FinalityConflictResolvedNotificationMessage
|
|
||||||
|
|
||||||
closeChan chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNotificationManager creates a new NotificationManager
|
|
||||||
func NewNotificationManager() *NotificationManager {
|
|
||||||
return &NotificationManager{
|
|
||||||
listeners: make(map[*router.Router]*NotificationListener),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddListener registers a listener with the given router
|
|
||||||
func (nm *NotificationManager) AddListener(router *router.Router) *NotificationListener {
|
|
||||||
nm.Lock()
|
|
||||||
defer nm.Unlock()
|
|
||||||
|
|
||||||
listener := newNotificationListener()
|
|
||||||
nm.listeners[router] = listener
|
|
||||||
return listener
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveListener unregisters the given router
|
|
||||||
func (nm *NotificationManager) RemoveListener(router *router.Router) {
|
|
||||||
nm.Lock()
|
|
||||||
defer nm.Unlock()
|
|
||||||
|
|
||||||
listener, ok := nm.listeners[router]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
listener.close()
|
|
||||||
|
|
||||||
delete(nm.listeners, router)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listener retrieves the listener registered with the given router
|
|
||||||
func (nm *NotificationManager) Listener(router *router.Router) (*NotificationListener, error) {
|
|
||||||
nm.RLock()
|
|
||||||
defer nm.RUnlock()
|
|
||||||
|
|
||||||
listener, ok := nm.listeners[router]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Errorf("listener not found")
|
|
||||||
}
|
|
||||||
return listener, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyBlockAdded notifies the notification manager that a block has been added to the DAG
|
|
||||||
func (nm *NotificationManager) NotifyBlockAdded(notification *appmessage.BlockAddedNotificationMessage) {
|
|
||||||
nm.RLock()
|
|
||||||
defer nm.RUnlock()
|
|
||||||
|
|
||||||
for _, listener := range nm.listeners {
|
|
||||||
if listener.onBlockAddedListener != nil {
|
|
||||||
select {
|
|
||||||
case listener.onBlockAddedNotificationChan <- notification:
|
|
||||||
case <-listener.closeChan:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyChainChanged notifies the notification manager that the DAG's selected parent chain has changed
|
|
||||||
func (nm *NotificationManager) NotifyChainChanged(message *appmessage.ChainChangedNotificationMessage) {
|
|
||||||
nm.RLock()
|
|
||||||
defer nm.RUnlock()
|
|
||||||
|
|
||||||
for _, listener := range nm.listeners {
|
|
||||||
if listener.onChainChangedListener != nil {
|
|
||||||
select {
|
|
||||||
case listener.onChainChangedNotificationChan <- message:
|
|
||||||
case <-listener.closeChan:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyFinalityConflict notifies the notification manager that there's a finality conflict in the DAG
|
|
||||||
func (nm *NotificationManager) NotifyFinalityConflict(message *appmessage.FinalityConflictNotificationMessage) {
|
|
||||||
nm.RLock()
|
|
||||||
defer nm.RUnlock()
|
|
||||||
|
|
||||||
for _, listener := range nm.listeners {
|
|
||||||
if listener.onFinalityConflictListener != nil {
|
|
||||||
select {
|
|
||||||
case listener.onFinalityConflictNotificationChan <- message:
|
|
||||||
case <-listener.closeChan:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyFinalityConflictResolved notifies the notification manager that a finality conflict in the DAG has been resolved
|
|
||||||
func (nm *NotificationManager) NotifyFinalityConflictResolved(message *appmessage.FinalityConflictResolvedNotificationMessage) {
|
|
||||||
nm.RLock()
|
|
||||||
defer nm.RUnlock()
|
|
||||||
|
|
||||||
for _, listener := range nm.listeners {
|
|
||||||
if listener.onFinalityConflictResolvedListener != nil {
|
|
||||||
select {
|
|
||||||
case listener.onFinalityConflictResolvedNotificationChan <- message:
|
|
||||||
case <-listener.closeChan:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newNotificationListener() *NotificationListener {
|
|
||||||
return &NotificationListener{
|
|
||||||
onBlockAddedNotificationChan: make(chan *appmessage.BlockAddedNotificationMessage),
|
|
||||||
onChainChangedNotificationChan: make(chan *appmessage.ChainChangedNotificationMessage),
|
|
||||||
onFinalityConflictNotificationChan: make(chan *appmessage.FinalityConflictNotificationMessage),
|
|
||||||
onFinalityConflictResolvedNotificationChan: make(chan *appmessage.FinalityConflictResolvedNotificationMessage),
|
|
||||||
closeChan: make(chan struct{}, 1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnBlockAddedListener sets the onBlockAddedListener handler for this listener
|
|
||||||
func (nl *NotificationListener) SetOnBlockAddedListener(onBlockAddedListener OnBlockAddedListener) {
|
|
||||||
nl.onBlockAddedListener = onBlockAddedListener
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnChainChangedListener sets the onChainChangedListener handler for this listener
|
|
||||||
func (nl *NotificationListener) SetOnChainChangedListener(onChainChangedListener OnChainChangedListener) {
|
|
||||||
nl.onChainChangedListener = onChainChangedListener
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnFinalityConflictListener sets the onFinalityConflictListener handler for this listener
|
|
||||||
func (nl *NotificationListener) SetOnFinalityConflictListener(onFinalityConflictListener OnFinalityConflictListener) {
|
|
||||||
nl.onFinalityConflictListener = onFinalityConflictListener
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnFinalityConflictResolvedListener sets the onFinalityConflictResolvedListener handler for this listener
|
|
||||||
func (nl *NotificationListener) SetOnFinalityConflictResolvedListener(onFinalityConflictResolvedListener OnFinalityConflictResolvedListener) {
|
|
||||||
nl.onFinalityConflictResolvedListener = onFinalityConflictResolvedListener
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessNextNotification waits until a notification arrives and processes it
|
|
||||||
func (nl *NotificationListener) ProcessNextNotification() error {
|
|
||||||
select {
|
|
||||||
case block := <-nl.onBlockAddedNotificationChan:
|
|
||||||
return nl.onBlockAddedListener(block)
|
|
||||||
case notification := <-nl.onChainChangedNotificationChan:
|
|
||||||
return nl.onChainChangedListener(notification)
|
|
||||||
case notification := <-nl.onFinalityConflictNotificationChan:
|
|
||||||
return nl.onFinalityConflictListener(notification)
|
|
||||||
case notification := <-nl.onFinalityConflictResolvedNotificationChan:
|
|
||||||
return nl.onFinalityConflictResolvedListener(notification)
|
|
||||||
case <-nl.closeChan:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nl *NotificationListener) close() {
|
|
||||||
nl.closeChan <- struct{}{}
|
|
||||||
}
|
|
||||||
@@ -1,246 +0,0 @@
|
|||||||
package rpccontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
|
||||||
"github.com/kaspanet/kaspad/domain/txscript"
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
"github.com/kaspanet/kaspad/util/pointers"
|
|
||||||
"math/big"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BuildBlockVerboseData builds a BlockVerboseData from the given block.
|
|
||||||
// This method must be called with the DAG lock held for reads
|
|
||||||
func (ctx *Context) BuildBlockVerboseData(block *util.Block, includeTransactionVerboseData bool) (*appmessage.BlockVerboseData, error) {
|
|
||||||
hash := block.Hash()
|
|
||||||
params := ctx.DAG.Params
|
|
||||||
blockHeader := block.MsgBlock().Header
|
|
||||||
|
|
||||||
blockBlueScore, err := ctx.DAG.BlueScoreByBlockHash(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the hashes for the next blocks unless there are none.
|
|
||||||
childHashes, err := ctx.DAG.ChildHashesByHash(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
blockConfirmations, err := ctx.DAG.BlockConfirmationsByHashNoLock(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedParentHash, err := ctx.DAG.SelectedParentHash(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
selectedParentHashStr := ""
|
|
||||||
if selectedParentHash != nil {
|
|
||||||
selectedParentHashStr = selectedParentHash.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
isChainBlock, err := ctx.DAG.IsInSelectedParentChain(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
acceptedBlockHashes, err := ctx.DAG.BluesByBlockHash(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := &appmessage.BlockVerboseData{
|
|
||||||
Hash: hash.String(),
|
|
||||||
Version: blockHeader.Version,
|
|
||||||
VersionHex: fmt.Sprintf("%08x", blockHeader.Version),
|
|
||||||
HashMerkleRoot: blockHeader.HashMerkleRoot.String(),
|
|
||||||
AcceptedIDMerkleRoot: blockHeader.AcceptedIDMerkleRoot.String(),
|
|
||||||
UTXOCommitment: blockHeader.UTXOCommitment.String(),
|
|
||||||
ParentHashes: daghash.Strings(blockHeader.ParentHashes),
|
|
||||||
SelectedParentHash: selectedParentHashStr,
|
|
||||||
Nonce: blockHeader.Nonce,
|
|
||||||
Time: blockHeader.Timestamp.UnixMilliseconds(),
|
|
||||||
Confirmations: blockConfirmations,
|
|
||||||
BlueScore: blockBlueScore,
|
|
||||||
IsChainBlock: isChainBlock,
|
|
||||||
Size: int32(block.MsgBlock().SerializeSize()),
|
|
||||||
Bits: strconv.FormatInt(int64(blockHeader.Bits), 16),
|
|
||||||
Difficulty: ctx.GetDifficultyRatio(blockHeader.Bits, params),
|
|
||||||
ChildHashes: daghash.Strings(childHashes),
|
|
||||||
AcceptedBlockHashes: daghash.Strings(acceptedBlockHashes),
|
|
||||||
}
|
|
||||||
|
|
||||||
transactions := block.Transactions()
|
|
||||||
txIDs := make([]string, len(transactions))
|
|
||||||
for i, tx := range transactions {
|
|
||||||
txIDs[i] = tx.ID().String()
|
|
||||||
}
|
|
||||||
result.TxIDs = txIDs
|
|
||||||
|
|
||||||
if includeTransactionVerboseData {
|
|
||||||
transactions := block.Transactions()
|
|
||||||
transactionVerboseData := make([]*appmessage.TransactionVerboseData, len(transactions))
|
|
||||||
for i, tx := range transactions {
|
|
||||||
data, err := ctx.buildTransactionVerboseData(tx.MsgTx(), tx.ID().String(),
|
|
||||||
&blockHeader, hash.String(), nil, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
transactionVerboseData[i] = data
|
|
||||||
}
|
|
||||||
result.TransactionVerboseData = transactionVerboseData
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDifficultyRatio returns the proof-of-work difficulty as a multiple of the
|
|
||||||
// minimum difficulty using the passed bits field from the header of a block.
|
|
||||||
func (ctx *Context) GetDifficultyRatio(bits uint32, params *dagconfig.Params) float64 {
|
|
||||||
// The minimum difficulty is the max possible proof-of-work limit bits
|
|
||||||
// converted back to a number. Note this is not the same as the proof of
|
|
||||||
// work limit directly because the block difficulty is encoded in a block
|
|
||||||
// with the compact form which loses precision.
|
|
||||||
target := util.CompactToBig(bits)
|
|
||||||
|
|
||||||
difficulty := new(big.Rat).SetFrac(params.PowMax, target)
|
|
||||||
outString := difficulty.FloatString(8)
|
|
||||||
diff, err := strconv.ParseFloat(outString, 64)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Cannot get difficulty: %s", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return diff
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *Context) buildTransactionVerboseData(mtx *appmessage.MsgTx,
|
|
||||||
txID string, blockHeader *appmessage.BlockHeader, blockHash string,
|
|
||||||
acceptingBlock *daghash.Hash, isInMempool bool) (*appmessage.TransactionVerboseData, error) {
|
|
||||||
|
|
||||||
mtxHex, err := msgTxToHex(mtx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var payloadHash string
|
|
||||||
if mtx.PayloadHash != nil {
|
|
||||||
payloadHash = mtx.PayloadHash.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
txReply := &appmessage.TransactionVerboseData{
|
|
||||||
Hex: mtxHex,
|
|
||||||
TxID: txID,
|
|
||||||
Hash: mtx.TxHash().String(),
|
|
||||||
Size: int32(mtx.SerializeSize()),
|
|
||||||
TransactionVerboseInputs: ctx.buildTransactionVerboseInputs(mtx),
|
|
||||||
TransactionVerboseOutputs: ctx.buildTransactionVerboseOutputs(mtx, nil),
|
|
||||||
Version: mtx.Version,
|
|
||||||
LockTime: mtx.LockTime,
|
|
||||||
SubnetworkID: mtx.SubnetworkID.String(),
|
|
||||||
Gas: mtx.Gas,
|
|
||||||
PayloadHash: payloadHash,
|
|
||||||
Payload: hex.EncodeToString(mtx.Payload),
|
|
||||||
}
|
|
||||||
|
|
||||||
if blockHeader != nil {
|
|
||||||
txReply.Time = uint64(blockHeader.Timestamp.UnixMilliseconds())
|
|
||||||
txReply.BlockTime = uint64(blockHeader.Timestamp.UnixMilliseconds())
|
|
||||||
txReply.BlockHash = blockHash
|
|
||||||
}
|
|
||||||
|
|
||||||
txReply.IsInMempool = isInMempool
|
|
||||||
if acceptingBlock != nil {
|
|
||||||
txReply.AcceptedBy = acceptingBlock.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return txReply, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// msgTxToHex serializes a transaction using the latest protocol version and
|
|
||||||
// returns a hex-encoded string of the result.
|
|
||||||
func msgTxToHex(msgTx *appmessage.MsgTx) (string, error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err := msgTx.KaspaEncode(&buf, 0)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return hex.EncodeToString(buf.Bytes()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *Context) buildTransactionVerboseInputs(mtx *appmessage.MsgTx) []*appmessage.TransactionVerboseInput {
|
|
||||||
inputs := make([]*appmessage.TransactionVerboseInput, len(mtx.TxIn))
|
|
||||||
for i, txIn := range mtx.TxIn {
|
|
||||||
// The disassembled string will contain [error] inline
|
|
||||||
// if the script doesn't fully parse, so ignore the
|
|
||||||
// error here.
|
|
||||||
disbuf, _ := txscript.DisasmString(txIn.SignatureScript)
|
|
||||||
|
|
||||||
input := &appmessage.TransactionVerboseInput{}
|
|
||||||
input.TxID = txIn.PreviousOutpoint.TxID.String()
|
|
||||||
input.OutputIndex = txIn.PreviousOutpoint.Index
|
|
||||||
input.Sequence = txIn.Sequence
|
|
||||||
input.ScriptSig = &appmessage.ScriptSig{
|
|
||||||
Asm: disbuf,
|
|
||||||
Hex: hex.EncodeToString(txIn.SignatureScript),
|
|
||||||
}
|
|
||||||
inputs[i] = input
|
|
||||||
}
|
|
||||||
|
|
||||||
return inputs
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTransactionVerboseOutputs returns a slice of JSON objects for the outputs of the passed
|
|
||||||
// transaction.
|
|
||||||
func (ctx *Context) buildTransactionVerboseOutputs(mtx *appmessage.MsgTx, filterAddrMap map[string]struct{}) []*appmessage.TransactionVerboseOutput {
|
|
||||||
outputs := make([]*appmessage.TransactionVerboseOutput, len(mtx.TxOut))
|
|
||||||
for i, v := range mtx.TxOut {
|
|
||||||
// The disassembled string will contain [error] inline if the
|
|
||||||
// script doesn't fully parse, so ignore the error here.
|
|
||||||
disbuf, _ := txscript.DisasmString(v.ScriptPubKey)
|
|
||||||
|
|
||||||
// Ignore the error here since an error means the script
|
|
||||||
// couldn't parse and there is no additional information about
|
|
||||||
// it anyways.
|
|
||||||
scriptClass, addr, _ := txscript.ExtractScriptPubKeyAddress(
|
|
||||||
v.ScriptPubKey, ctx.DAG.Params)
|
|
||||||
|
|
||||||
// Encode the addresses while checking if the address passes the
|
|
||||||
// filter when needed.
|
|
||||||
passesFilter := len(filterAddrMap) == 0
|
|
||||||
var encodedAddr string
|
|
||||||
if addr != nil {
|
|
||||||
encodedAddr = *pointers.String(addr.EncodeAddress())
|
|
||||||
|
|
||||||
// If the filter doesn't already pass, make it pass if
|
|
||||||
// the address exists in the filter.
|
|
||||||
if _, exists := filterAddrMap[encodedAddr]; exists {
|
|
||||||
passesFilter = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !passesFilter {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
output := &appmessage.TransactionVerboseOutput{}
|
|
||||||
output.Index = uint32(i)
|
|
||||||
output.Value = v.Value
|
|
||||||
output.ScriptPubKey = &appmessage.ScriptPubKeyResult{
|
|
||||||
Address: encodedAddr,
|
|
||||||
Asm: disbuf,
|
|
||||||
Hex: hex.EncodeToString(v.ScriptPubKey),
|
|
||||||
Type: scriptClass.String(),
|
|
||||||
}
|
|
||||||
outputs[i] = output
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputs
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleAddPeer handles the respectively named RPC command
|
|
||||||
func HandleAddPeer(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
AddPeerRequest := request.(*appmessage.AddPeerRequestMessage)
|
|
||||||
address, err := network.NormalizeAddress(AddPeerRequest.Address, context.DAG.Params.DefaultPort)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.AddPeerResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse address: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
context.ConnectionManager.AddConnectionRequest(address, AddPeerRequest.IsPermanent)
|
|
||||||
|
|
||||||
response := appmessage.NewAddPeerResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBlock handles the respectively named RPC command
|
|
||||||
func HandleGetBlock(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
getBlockRequest := request.(*appmessage.GetBlockRequestMessage)
|
|
||||||
|
|
||||||
// Load the raw block bytes from the database.
|
|
||||||
hash, err := daghash.NewHashFromStr(getBlockRequest.Hash)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Hash could not be parsed: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
context.DAG.RLock()
|
|
||||||
defer context.DAG.RUnlock()
|
|
||||||
|
|
||||||
if context.DAG.IsKnownInvalid(hash) {
|
|
||||||
errorMessage := &appmessage.GetBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block %s is known to be invalid", hash)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
if context.DAG.IsKnownOrphan(hash) {
|
|
||||||
errorMessage := &appmessage.GetBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block %s is an orphan", hash)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
block, err := context.DAG.BlockByHash(hash)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block %s not found", hash)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
blockBytes, err := block.Bytes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle partial blocks
|
|
||||||
if getBlockRequest.SubnetworkID != "" {
|
|
||||||
requestSubnetworkID, err := subnetworkid.NewFromStr(getBlockRequest.SubnetworkID)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("SubnetworkID could not be parsed: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
nodeSubnetworkID := context.Config.SubnetworkID
|
|
||||||
|
|
||||||
if requestSubnetworkID != nil {
|
|
||||||
if nodeSubnetworkID != nil {
|
|
||||||
if !nodeSubnetworkID.IsEqual(requestSubnetworkID) {
|
|
||||||
errorMessage := &appmessage.GetBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("subnetwork %s does not match this partial node",
|
|
||||||
getBlockRequest.SubnetworkID)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
// nothing to do - partial node stores partial blocks
|
|
||||||
} else {
|
|
||||||
// Deserialize the block.
|
|
||||||
msgBlock := block.MsgBlock()
|
|
||||||
msgBlock.ConvertToPartial(requestSubnetworkID)
|
|
||||||
var b bytes.Buffer
|
|
||||||
err := msgBlock.Serialize(bufio.NewWriter(&b))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blockBytes = b.Bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetBlockResponseMessage()
|
|
||||||
|
|
||||||
if getBlockRequest.IncludeBlockHex {
|
|
||||||
response.BlockHex = hex.EncodeToString(blockBytes)
|
|
||||||
}
|
|
||||||
if getBlockRequest.IncludeBlockVerboseData {
|
|
||||||
blockVerboseData, err := context.BuildBlockVerboseData(block, getBlockRequest.IncludeTransactionVerboseData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.BlockVerboseData = blockVerboseData
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBlockCount handles the respectively named RPC command
|
|
||||||
func HandleGetBlockCount(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
response := appmessage.NewGetBlockCountResponseMessage(context.DAG.BlockCount())
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util/daghash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBlockDAGInfo handles the respectively named RPC command
|
|
||||||
func HandleGetBlockDAGInfo(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
dag := context.DAG
|
|
||||||
params := dag.Params
|
|
||||||
|
|
||||||
response := appmessage.NewGetBlockDAGInfoResponseMessage()
|
|
||||||
response.NetworkName = params.Name
|
|
||||||
response.BlockCount = dag.BlockCount()
|
|
||||||
response.TipHashes = daghash.Strings(dag.TipHashes())
|
|
||||||
response.VirtualParentHashes = daghash.Strings(dag.VirtualParentHashes())
|
|
||||||
response.Difficulty = context.GetDifficultyRatio(dag.CurrentBits(), params)
|
|
||||||
response.PastMedianTime = dag.CalcPastMedianTime().UnixMilliseconds()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBlockTemplate handles the respectively named RPC command
|
|
||||||
func HandleGetBlockTemplate(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
getBlockTemplateRequest := request.(*appmessage.GetBlockTemplateRequestMessage)
|
|
||||||
|
|
||||||
payAddress, err := util.DecodeAddress(getBlockTemplateRequest.PayAddress, context.DAG.Params.Prefix)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetBlockTemplateResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not decode address: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// When a long poll ID was provided, this is a long poll request by the
|
|
||||||
// client to be notified when block template referenced by the ID should
|
|
||||||
// be replaced with a new one.
|
|
||||||
if getBlockTemplateRequest.LongPollID != "" {
|
|
||||||
return handleGetBlockTemplateLongPoll(context, getBlockTemplateRequest.LongPollID, payAddress)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protect concurrent access when updating block templates.
|
|
||||||
context.BlockTemplateState.Lock()
|
|
||||||
defer context.BlockTemplateState.Unlock()
|
|
||||||
|
|
||||||
// Get and return a block template. A new block template will be
|
|
||||||
// generated when the current best block has changed or the transactions
|
|
||||||
// in the memory pool have been updated and it has been at least five
|
|
||||||
// seconds since the last template was generated. Otherwise, the
|
|
||||||
// timestamp for the existing block template is updated (and possibly
|
|
||||||
// the difficulty on testnet per the consesus rules).
|
|
||||||
err = context.BlockTemplateState.Update(payAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return context.BlockTemplateState.Response()
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleGetBlockTemplateLongPoll is a helper for handleGetBlockTemplateRequest
|
|
||||||
// which deals with handling long polling for block templates. When a caller
|
|
||||||
// sends a request with a long poll ID that was previously returned, a response
|
|
||||||
// is not sent until the caller should stop working on the previous block
|
|
||||||
// template in favor of the new one. In particular, this is the case when the
|
|
||||||
// old block template is no longer valid due to a solution already being found
|
|
||||||
// and added to the block DAG, or new transactions have shown up and some time
|
|
||||||
// has passed without finding a solution.
|
|
||||||
func handleGetBlockTemplateLongPoll(context *rpccontext.Context, longPollID string,
|
|
||||||
payAddress util.Address) (*appmessage.GetBlockTemplateResponseMessage, error) {
|
|
||||||
state := context.BlockTemplateState
|
|
||||||
|
|
||||||
result, longPollChan, err := state.BlockTemplateOrLongPollChan(longPollID, payAddress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if result != nil {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until signal received to send the reply.
|
|
||||||
<-longPollChan
|
|
||||||
|
|
||||||
// Get the lastest block template
|
|
||||||
state.Lock()
|
|
||||||
defer state.Unlock()
|
|
||||||
|
|
||||||
if err := state.Update(payAddress); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include whether or not it is valid to submit work against the old
|
|
||||||
// block template depending on whether or not a solution has already
|
|
||||||
// been found and added to the block DAG.
|
|
||||||
result, err = state.Response()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// maxBlocksInGetBlocksResponse is the max amount of blocks that are
|
|
||||||
// allowed in a GetBlocksResult.
|
|
||||||
maxBlocksInGetBlocksResponse = 1000
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBlocks handles the respectively named RPC command
|
|
||||||
func HandleGetBlocks(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
getBlocksRequest := request.(*appmessage.GetBlocksRequestMessage)
|
|
||||||
|
|
||||||
var lowHash *daghash.Hash
|
|
||||||
if getBlocksRequest.LowHash != "" {
|
|
||||||
lowHash = &daghash.Hash{}
|
|
||||||
err := daghash.Decode(lowHash, getBlocksRequest.LowHash)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetBlocksResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse lowHash: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.DAG.RLock()
|
|
||||||
defer context.DAG.RUnlock()
|
|
||||||
|
|
||||||
// If lowHash is not in the DAG, there's nothing to do; return an error.
|
|
||||||
if lowHash != nil && !context.DAG.IsKnownBlock(lowHash) {
|
|
||||||
errorMessage := &appmessage.GetBlocksResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block %s not found in DAG", lowHash)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the block hashes.
|
|
||||||
blockHashes, err := context.DAG.BlockHashesFrom(lowHash, maxBlocksInGetBlocksResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the hashes to strings
|
|
||||||
hashes := make([]string, len(blockHashes))
|
|
||||||
for i, blockHash := range blockHashes {
|
|
||||||
hashes[i] = blockHash.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include more data if requested
|
|
||||||
var blockHexes []string
|
|
||||||
var blockVerboseData []*appmessage.BlockVerboseData
|
|
||||||
if getBlocksRequest.IncludeBlockHexes || getBlocksRequest.IncludeBlockVerboseData {
|
|
||||||
blockBytesSlice, err := hashesToBlockBytes(context, blockHashes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if getBlocksRequest.IncludeBlockHexes {
|
|
||||||
blockHexes = blockBytesToStrings(blockBytesSlice)
|
|
||||||
}
|
|
||||||
if getBlocksRequest.IncludeBlockVerboseData {
|
|
||||||
data, err := blockBytesToBlockVerboseResults(context, blockBytesSlice, getBlocksRequest.IncludeBlockVerboseData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blockVerboseData = data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetBlocksResponseMessage(hashes, blockHexes, blockVerboseData)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func hashesToBlockBytes(context *rpccontext.Context, hashes []*daghash.Hash) ([][]byte, error) {
|
|
||||||
blocks := make([][]byte, len(hashes))
|
|
||||||
for i, hash := range hashes {
|
|
||||||
block, err := context.DAG.BlockByHash(hash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blockBytes, err := block.Bytes()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blocks[i] = blockBytes
|
|
||||||
}
|
|
||||||
return blocks, nil
|
|
||||||
}
|
|
||||||
func blockBytesToStrings(blockBytesSlice [][]byte) []string {
|
|
||||||
rawBlocks := make([]string, len(blockBytesSlice))
|
|
||||||
for i, blockBytes := range blockBytesSlice {
|
|
||||||
rawBlocks[i] = hex.EncodeToString(blockBytes)
|
|
||||||
}
|
|
||||||
return rawBlocks
|
|
||||||
}
|
|
||||||
|
|
||||||
func blockBytesToBlockVerboseResults(context *rpccontext.Context, blockBytesSlice [][]byte,
|
|
||||||
includeTransactionVerboseData bool) ([]*appmessage.BlockVerboseData, error) {
|
|
||||||
|
|
||||||
verboseBlocks := make([]*appmessage.BlockVerboseData, len(blockBytesSlice))
|
|
||||||
for i, blockBytes := range blockBytesSlice {
|
|
||||||
block, err := util.NewBlockFromBytes(blockBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
getBlockVerboseResult, err := context.BuildBlockVerboseData(block, includeTransactionVerboseData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
verboseBlocks[i] = getBlockVerboseResult
|
|
||||||
}
|
|
||||||
return verboseBlocks, nil
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util/daghash"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// maxBlocksInGetChainFromBlockResponse is the max amount of blocks that
|
|
||||||
// are allowed in a GetChainFromBlockResponse.
|
|
||||||
maxBlocksInGetChainFromBlockResponse = 1000
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetChainFromBlock handles the respectively named RPC command
|
|
||||||
func HandleGetChainFromBlock(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
getChainFromBlockRequest := request.(*appmessage.GetChainFromBlockRequestMessage)
|
|
||||||
|
|
||||||
if context.AcceptanceIndex == nil {
|
|
||||||
errorMessage := &appmessage.GetChainFromBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("The acceptance index must be " +
|
|
||||||
"enabled to get the selected parent chain " +
|
|
||||||
"(specify --acceptanceindex)")
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var startHash *daghash.Hash
|
|
||||||
if getChainFromBlockRequest.StartHash != "" {
|
|
||||||
startHash = &daghash.Hash{}
|
|
||||||
err := daghash.Decode(startHash, getChainFromBlockRequest.StartHash)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetChainFromBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse startHash: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.DAG.RLock()
|
|
||||||
defer context.DAG.RUnlock()
|
|
||||||
|
|
||||||
// If startHash is not in the selected parent chain, there's nothing
|
|
||||||
// to do; return an error.
|
|
||||||
if startHash != nil && !context.DAG.IsInDAG(startHash) {
|
|
||||||
errorMessage := &appmessage.GetChainFromBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block %s not found in the DAG", startHash)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the selected parent chain.
|
|
||||||
removedChainHashes, addedChainHashes, err := context.DAG.SelectedParentChain(startHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit the amount of blocks in the response
|
|
||||||
if len(addedChainHashes) > maxBlocksInGetChainFromBlockResponse {
|
|
||||||
addedChainHashes = addedChainHashes[:maxBlocksInGetChainFromBlockResponse]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect addedChainBlocks.
|
|
||||||
addedChainBlocks, err := context.CollectChainBlocks(addedChainHashes)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetChainFromBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not collect chain blocks: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect removedHashes.
|
|
||||||
removedHashes := make([]string, len(removedChainHashes))
|
|
||||||
for i, hash := range removedChainHashes {
|
|
||||||
removedHashes[i] = hash.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user specified to include the blocks, collect them as well.
|
|
||||||
var blockVerboseData []*appmessage.BlockVerboseData
|
|
||||||
if getChainFromBlockRequest.IncludeBlockVerboseData {
|
|
||||||
data, err := hashesToBlockVerboseData(context, addedChainHashes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blockVerboseData = data
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetChainFromBlockResponseMessage(removedHashes, addedChainBlocks, blockVerboseData)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// hashesToBlockVerboseData takes block hashes and returns their
|
|
||||||
// correspondent block verbose.
|
|
||||||
func hashesToBlockVerboseData(context *rpccontext.Context, hashes []*daghash.Hash) ([]*appmessage.BlockVerboseData, error) {
|
|
||||||
getBlockVerboseResults := make([]*appmessage.BlockVerboseData, 0, len(hashes))
|
|
||||||
for _, blockHash := range hashes {
|
|
||||||
block, err := context.DAG.BlockByHash(blockHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Errorf("could not retrieve block %s.", blockHash)
|
|
||||||
}
|
|
||||||
getBlockVerboseResult, err := context.BuildBlockVerboseData(block, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "could not build getBlockVerboseResult for block %s", blockHash)
|
|
||||||
}
|
|
||||||
getBlockVerboseResults = append(getBlockVerboseResults, getBlockVerboseResult)
|
|
||||||
}
|
|
||||||
return getBlockVerboseResults, nil
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetConnectedPeerInfo handles the respectively named RPC command
|
|
||||||
func HandleGetConnectedPeerInfo(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
peers := context.ProtocolManager.Peers()
|
|
||||||
ibdPeer := context.ProtocolManager.IBDPeer()
|
|
||||||
infos := make([]*appmessage.GetConnectedPeerInfoMessage, 0, len(peers))
|
|
||||||
for _, peer := range peers {
|
|
||||||
info := &appmessage.GetConnectedPeerInfoMessage{
|
|
||||||
ID: peer.ID().String(),
|
|
||||||
Address: peer.Address(),
|
|
||||||
LastPingDuration: peer.LastPingDuration().Milliseconds(),
|
|
||||||
SelectedTipHash: peer.SelectedTipHash().String(),
|
|
||||||
IsSyncNode: peer == ibdPeer,
|
|
||||||
IsOutbound: peer.IsOutbound(),
|
|
||||||
TimeOffset: peer.TimeOffset().Milliseconds(),
|
|
||||||
UserAgent: peer.UserAgent(),
|
|
||||||
AdvertisedProtocolVersion: peer.AdvertisedProtocolVersion(),
|
|
||||||
TimeConnected: peer.TimeConnected().Milliseconds(),
|
|
||||||
}
|
|
||||||
infos = append(infos, info)
|
|
||||||
}
|
|
||||||
response := appmessage.NewGetConnectedPeerInfoResponseMessage(infos)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetCurrentNetwork handles the respectively named RPC command
|
|
||||||
func HandleGetCurrentNetwork(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
response := appmessage.NewGetCurrentNetworkResponseMessage(context.DAG.Params.Net.String())
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util/daghash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetMempoolEntry handles the respectively named RPC command
|
|
||||||
func HandleGetMempoolEntry(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
getMempoolEntryRequest := request.(*appmessage.GetMempoolEntryRequestMessage)
|
|
||||||
txID, err := daghash.NewTxIDFromStr(getMempoolEntryRequest.TxID)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetMempoolEntryResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse txId: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok := context.Mempool.FetchTxDesc(txID)
|
|
||||||
if !ok {
|
|
||||||
errorMessage := &appmessage.GetMempoolEntryResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("transaction is not in the pool")
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetMempoolEntryResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetPeerAddresses handles the respectively named RPC command
|
|
||||||
func HandleGetPeerAddresses(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
peersState, err := context.AddressManager.PeersStateForSerialization()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
addresses := make([]*appmessage.GetPeerAddressesKnownAddressMessage, len(peersState.Addresses))
|
|
||||||
for i, address := range peersState.Addresses {
|
|
||||||
addresses[i] = &appmessage.GetPeerAddressesKnownAddressMessage{Addr: string(address.Address)}
|
|
||||||
}
|
|
||||||
response := appmessage.NewGetPeerAddressesResponseMessage(addresses)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetSelectedTipHash handles the respectively named RPC command
|
|
||||||
func HandleGetSelectedTipHash(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
response := appmessage.NewGetSelectedTipHashResponseMessage(context.DAG.SelectedTipHash().String())
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util/subnetworkid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetSubnetwork handles the respectively named RPC command
|
|
||||||
func HandleGetSubnetwork(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
getSubnetworkRequest := request.(*appmessage.GetSubnetworkRequestMessage)
|
|
||||||
|
|
||||||
subnetworkID, err := subnetworkid.NewFromStr(getSubnetworkRequest.SubnetworkID)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetSubnetworkResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse subnetworkID: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var gasLimit uint64
|
|
||||||
if !subnetworkID.IsBuiltInOrNative() {
|
|
||||||
limit, err := context.DAG.GasLimit(subnetworkID)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.GetSubnetworkResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Subnetwork %s not found.", subnetworkID)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
gasLimit = limit
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetSubnetworkResponseMessage(gasLimit)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log, _ = logger.Get(logger.SubsystemTags.RPCS)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleNotifyBlockAdded handles the respectively named RPC command
|
|
||||||
func HandleNotifyBlockAdded(context *rpccontext.Context, router *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
listener, err := context.NotificationManager.Listener(router)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
listener.SetOnBlockAddedListener(func(notification *appmessage.BlockAddedNotificationMessage) error {
|
|
||||||
return router.OutgoingRoute().Enqueue(notification)
|
|
||||||
})
|
|
||||||
|
|
||||||
response := appmessage.NewNotifyBlockAddedResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleNotifyChainChanged handles the respectively named RPC command
|
|
||||||
func HandleNotifyChainChanged(context *rpccontext.Context, router *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
if context.AcceptanceIndex == nil {
|
|
||||||
errorMessage := appmessage.NewNotifyChainChangedResponseMessage()
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Acceptance index is not available")
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
listener, err := context.NotificationManager.Listener(router)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
listener.SetOnChainChangedListener(func(message *appmessage.ChainChangedNotificationMessage) error {
|
|
||||||
return router.OutgoingRoute().Enqueue(message)
|
|
||||||
})
|
|
||||||
|
|
||||||
response := appmessage.NewNotifyChainChangedResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleNotifyFinalityConflicts handles the respectively named RPC command
|
|
||||||
func HandleNotifyFinalityConflicts(context *rpccontext.Context, router *router.Router, _ appmessage.Message) (appmessage.Message, error) {
|
|
||||||
listener, err := context.NotificationManager.Listener(router)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
listener.SetOnFinalityConflictListener(func(notification *appmessage.FinalityConflictNotificationMessage) error {
|
|
||||||
return router.OutgoingRoute().Enqueue(notification)
|
|
||||||
})
|
|
||||||
listener.SetOnFinalityConflictResolvedListener(func(notification *appmessage.FinalityConflictResolvedNotificationMessage) error {
|
|
||||||
return router.OutgoingRoute().Enqueue(notification)
|
|
||||||
})
|
|
||||||
|
|
||||||
response := appmessage.NewNotifyFinalityConflictsResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
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/kaspanet/kaspad/util/daghash"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleResolveFinalityConflict handles the respectively named RPC command
|
|
||||||
func HandleResolveFinalityConflict(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
ResolveFinalityConflictRequest := request.(*appmessage.ResolveFinalityConflictRequestMessage)
|
|
||||||
|
|
||||||
finalityBlockHash, err := daghash.NewHashFromStr(ResolveFinalityConflictRequest.FinalityBlockHash)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.ResolveFinalityConflictResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not parse finalityBlockHash: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err = context.DAG.ResolveFinalityConflict(finalityBlockHash)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.ResolveFinalityConflictResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Could not resolve finality conflict: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewResolveFinalityConflictResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleSubmitBlock handles the respectively named RPC command
|
|
||||||
func HandleSubmitBlock(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
submitBlockRequest := request.(*appmessage.SubmitBlockRequestMessage)
|
|
||||||
|
|
||||||
// Deserialize the submitted block.
|
|
||||||
serializedBlock, err := hex.DecodeString(submitBlockRequest.BlockHex)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.SubmitBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block hex could not be parsed: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
block, err := util.NewBlockFromBytes(serializedBlock)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.SubmitBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block decode failed: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err = context.ProtocolManager.AddBlock(block, blockdag.BFDisallowDelay|blockdag.BFDisallowOrphans)
|
|
||||||
if err != nil {
|
|
||||||
errorMessage := &appmessage.SubmitBlockResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Block rejected. Reason: %s", err)
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Accepted block %s via submitBlock", block.Hash())
|
|
||||||
|
|
||||||
response := appmessage.NewSubmitBlockResponseMessage()
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user