Add AcceptedTransactionIDs to ChainChanged notification and VirtualSelectedParentChain RPC (#2036)

* Add acceptedTransactionIds to GetVirtualSelectedParentChainFromBlockResponseMessage and VirtualSelectedParentChainChangedNotificationMessage

* Modify appmessage structs to include new fields

* Implement the functionality for acceptedTransactionID notifications

* Add missing field for IncludeAcceptedTransactionIds

* Notify of block added before notifying that chain changed

* Use consensushashing instead of Transaction.ID

* Don't notify of empty virtual changes

* Don't generate virtualChainChanged notification if there's nobody subscribed

* Fix test to not expect empty notifications

* Don't generate acceptedTransactionIDs if they were not requested by anyone

Co-authored-by: Ori Newman <orinewman1@gmail.com>
This commit is contained in:
Svarog 2022-05-05 12:35:02 +03:00 committed by GitHub
parent 1660cf0cf1
commit 52fbeedf20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1076 additions and 788 deletions

View File

@ -4,7 +4,8 @@ package appmessage
// its respective RPC message
type GetVirtualSelectedParentChainFromBlockRequestMessage struct {
baseMessage
StartHash string
StartHash string
IncludeAcceptedTransactionIDs bool
}
// Command returns the protocol command string for the message
@ -13,18 +14,29 @@ func (msg *GetVirtualSelectedParentChainFromBlockRequestMessage) Command() Messa
}
// NewGetVirtualSelectedParentChainFromBlockRequestMessage returns a instance of the message
func NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash string) *GetVirtualSelectedParentChainFromBlockRequestMessage {
func NewGetVirtualSelectedParentChainFromBlockRequestMessage(
startHash string, includeAcceptedTransactionIDs bool) *GetVirtualSelectedParentChainFromBlockRequestMessage {
return &GetVirtualSelectedParentChainFromBlockRequestMessage{
StartHash: startHash,
StartHash: startHash,
IncludeAcceptedTransactionIDs: includeAcceptedTransactionIDs,
}
}
// AcceptedTransactionIDs is a part of the GetVirtualSelectedParentChainFromBlockResponseMessage and
// VirtualSelectedParentChainChangedNotificationMessage appmessages
type AcceptedTransactionIDs struct {
AcceptingBlockHash string
AcceptedTransactionIDs []string
}
// GetVirtualSelectedParentChainFromBlockResponseMessage is an appmessage corresponding to
// its respective RPC message
type GetVirtualSelectedParentChainFromBlockResponseMessage struct {
baseMessage
RemovedChainBlockHashes []string
AddedChainBlockHashes []string
AcceptedTransactionIDs []*AcceptedTransactionIDs
Error *RPCError
}
@ -36,10 +48,11 @@ func (msg *GetVirtualSelectedParentChainFromBlockResponseMessage) Command() Mess
// NewGetVirtualSelectedParentChainFromBlockResponseMessage returns a instance of the message
func NewGetVirtualSelectedParentChainFromBlockResponseMessage(removedChainBlockHashes,
addedChainBlockHashes []string) *GetVirtualSelectedParentChainFromBlockResponseMessage {
addedChainBlockHashes []string, acceptedTransactionIDs []*AcceptedTransactionIDs) *GetVirtualSelectedParentChainFromBlockResponseMessage {
return &GetVirtualSelectedParentChainFromBlockResponseMessage{
RemovedChainBlockHashes: removedChainBlockHashes,
AddedChainBlockHashes: addedChainBlockHashes,
AcceptedTransactionIDs: acceptedTransactionIDs,
}
}

View File

@ -4,6 +4,7 @@ package appmessage
// its respective RPC message
type NotifyVirtualSelectedParentChainChangedRequestMessage struct {
baseMessage
IncludeAcceptedTransactionIDs bool
}
// Command returns the protocol command string for the message
@ -11,9 +12,13 @@ func (msg *NotifyVirtualSelectedParentChainChangedRequestMessage) Command() Mess
return CmdNotifyVirtualSelectedParentChainChangedRequestMessage
}
// NewNotifyVirtualSelectedParentChainChangedRequestMessage returns a instance of the message
func NewNotifyVirtualSelectedParentChainChangedRequestMessage() *NotifyVirtualSelectedParentChainChangedRequestMessage {
return &NotifyVirtualSelectedParentChainChangedRequestMessage{}
// NewNotifyVirtualSelectedParentChainChangedRequestMessage returns an instance of the message
func NewNotifyVirtualSelectedParentChainChangedRequestMessage(
includeAcceptedTransactionIDs bool) *NotifyVirtualSelectedParentChainChangedRequestMessage {
return &NotifyVirtualSelectedParentChainChangedRequestMessage{
IncludeAcceptedTransactionIDs: includeAcceptedTransactionIDs,
}
}
// NotifyVirtualSelectedParentChainChangedResponseMessage is an appmessage corresponding to
@ -39,6 +44,7 @@ type VirtualSelectedParentChainChangedNotificationMessage struct {
baseMessage
RemovedChainBlockHashes []string
AddedChainBlockHashes []string
AcceptedTransactionIDs []*AcceptedTransactionIDs
}
// Command returns the protocol command string for the message
@ -48,10 +54,11 @@ func (msg *VirtualSelectedParentChainChangedNotificationMessage) Command() Messa
// NewVirtualSelectedParentChainChangedNotificationMessage returns a instance of the message
func NewVirtualSelectedParentChainChangedNotificationMessage(removedChainBlockHashes,
addedChainBlocks []string) *VirtualSelectedParentChainChangedNotificationMessage {
addedChainBlocks []string, acceptedTransactionIDs []*AcceptedTransactionIDs) *VirtualSelectedParentChainChangedNotificationMessage {
return &VirtualSelectedParentChainChangedNotificationMessage{
RemovedChainBlockHashes: removedChainBlockHashes,
AddedChainBlockHashes: addedChainBlocks,
AcceptedTransactionIDs: acceptedTransactionIDs,
}
}

View File

@ -52,18 +52,25 @@ func (m *Manager) NotifyBlockAddedToDAG(block *externalapi.DomainBlock, virtualC
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyBlockAddedToDAG")
defer onEnd()
err := m.NotifyVirtualChange(virtualChangeSet)
if err != nil {
return err
}
rpcBlock := appmessage.DomainBlockToRPCBlock(block)
err = m.context.PopulateBlockWithVerboseData(rpcBlock, block.Header, block, false)
err := m.context.PopulateBlockWithVerboseData(rpcBlock, block.Header, block, true)
if err != nil {
return err
}
blockAddedNotification := appmessage.NewBlockAddedNotificationMessage(rpcBlock)
return m.context.NotificationManager.NotifyBlockAdded(blockAddedNotification)
err = m.context.NotificationManager.NotifyBlockAdded(blockAddedNotification)
if err != nil {
return err
}
// When block was added during IBD - it doesn't incur any Virtual change,
// thus no notification is needed.
if len(virtualChangeSet.VirtualSelectedParentChainChanges.Added) == 0 &&
len(virtualChangeSet.VirtualSelectedParentChainChanges.Removed) == 0 {
return nil
}
return m.NotifyVirtualChange(virtualChangeSet)
}
// NotifyVirtualChange notifies the manager that the virtual block has been changed.
@ -195,10 +202,25 @@ func (m *Manager) notifyVirtualSelectedParentChainChanged(virtualChangeSet *exte
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualSelectedParentChainChanged")
defer onEnd()
notification, err := m.context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
virtualChangeSet.VirtualSelectedParentChainChanges)
if err != nil {
return err
listenersThatPropagateSelectedParentChanged :=
m.context.NotificationManager.AllListenersThatPropagateVirtualSelectedParentChainChanged()
if len(listenersThatPropagateSelectedParentChanged) > 0 {
// Generating acceptedTransactionIDs is a heavy operation, so we check if it's needed by any listener.
includeAcceptedTransactionIDs := false
for _, listener := range listenersThatPropagateSelectedParentChanged {
if listener.IncludeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications() {
includeAcceptedTransactionIDs = true
break
}
}
notification, err := m.context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
virtualChangeSet.VirtualSelectedParentChainChanges, includeAcceptedTransactionIDs)
if err != nil {
return err
}
return m.context.NotificationManager.NotifyVirtualSelectedParentChainChanged(notification)
}
return m.context.NotificationManager.NotifyVirtualSelectedParentChainChanged(notification)
return nil
}

View File

@ -3,12 +3,14 @@ package rpccontext
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
)
// ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage converts
// VirtualSelectedParentChainChanges to VirtualSelectedParentChainChangedNotificationMessage
func (ctx *Context) ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
selectedParentChainChanges *externalapi.SelectedChainPath) (*appmessage.VirtualSelectedParentChainChangedNotificationMessage, error) {
selectedParentChainChanges *externalapi.SelectedChainPath, includeAcceptedTransactionIDs bool) (
*appmessage.VirtualSelectedParentChainChangedNotificationMessage, error) {
removedChainBlockHashes := make([]string, len(selectedParentChainChanges.Removed))
for i, removed := range selectedParentChainChanges.Removed {
@ -20,5 +22,43 @@ func (ctx *Context) ConvertVirtualSelectedParentChainChangesToChainChangedNotifi
addedChainBlocks[i] = added.String()
}
return appmessage.NewVirtualSelectedParentChainChangedNotificationMessage(removedChainBlockHashes, addedChainBlocks), nil
var acceptedTransactionIDs []*appmessage.AcceptedTransactionIDs
if includeAcceptedTransactionIDs {
var err error
acceptedTransactionIDs, err = ctx.getAndConvertAcceptedTransactionIDs(selectedParentChainChanges)
if err != nil {
return nil, err
}
}
return appmessage.NewVirtualSelectedParentChainChangedNotificationMessage(
removedChainBlockHashes, addedChainBlocks, acceptedTransactionIDs), nil
}
func (ctx *Context) getAndConvertAcceptedTransactionIDs(selectedParentChainChanges *externalapi.SelectedChainPath) (
[]*appmessage.AcceptedTransactionIDs, error) {
acceptedTransactionIDs := make([]*appmessage.AcceptedTransactionIDs, len(selectedParentChainChanges.Added))
for i, addedChainBlock := range selectedParentChainChanges.Added {
blockAcceptanceData, err := ctx.Domain.Consensus().GetBlockAcceptanceData(addedChainBlock)
if err != nil {
return nil, err
}
acceptedTransactionIDs[i] = &appmessage.AcceptedTransactionIDs{
AcceptingBlockHash: addedChainBlock.String(),
AcceptedTransactionIDs: nil,
}
for _, blockAcceptanceData := range blockAcceptanceData {
for _, transactionAcceptanceData := range blockAcceptanceData.TransactionAcceptanceData {
if transactionAcceptanceData.IsAccepted {
acceptedTransactionIDs[i].AcceptedTransactionIDs =
append(acceptedTransactionIDs[i].AcceptedTransactionIDs,
consensushashing.TransactionID(transactionAcceptanceData.Transaction).String())
}
}
}
}
return acceptedTransactionIDs, nil
}

View File

@ -34,7 +34,8 @@ type NotificationListener struct {
propagatePruningPointUTXOSetOverrideNotifications bool
propagateNewBlockTemplateNotifications bool
propagateUTXOsChangedNotificationAddresses map[utxoindex.ScriptPublicKeyString]*UTXOsChangedNotificationAddress
propagateUTXOsChangedNotificationAddresses map[utxoindex.ScriptPublicKeyString]*UTXOsChangedNotificationAddress
includeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications bool
}
// NewNotificationManager creates a new NotificationManager
@ -92,13 +93,27 @@ func (nm *NotificationManager) NotifyBlockAdded(notification *appmessage.BlockAd
}
// NotifyVirtualSelectedParentChainChanged notifies the notification manager that the DAG's selected parent chain has changed
func (nm *NotificationManager) NotifyVirtualSelectedParentChainChanged(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage) error {
func (nm *NotificationManager) NotifyVirtualSelectedParentChainChanged(
notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage) error {
nm.RLock()
defer nm.RUnlock()
notificationWithoutAcceptedTransactionIDs := &appmessage.VirtualSelectedParentChainChangedNotificationMessage{
RemovedChainBlockHashes: notification.RemovedChainBlockHashes,
AddedChainBlockHashes: notification.AddedChainBlockHashes,
}
for router, listener := range nm.listeners {
if listener.propagateVirtualSelectedParentChainChangedNotifications {
err := router.OutgoingRoute().Enqueue(notification)
var err error
if listener.includeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications {
err = router.OutgoingRoute().Enqueue(notification)
} else {
err = router.OutgoingRoute().Enqueue(notificationWithoutAcceptedTransactionIDs)
}
if err != nil {
return err
}
@ -107,6 +122,18 @@ func (nm *NotificationManager) NotifyVirtualSelectedParentChainChanged(notificat
return nil
}
// AllListenersThatPropagateVirtualSelectedParentChainChanged returns true if there's any listener that is
// subscribed to VirtualSelectedParentChainChanged notifications.
func (nm *NotificationManager) AllListenersThatPropagateVirtualSelectedParentChainChanged() []*NotificationListener {
var listenersThatPropagate []*NotificationListener
for _, listener := range nm.listeners {
if listener.propagateVirtualSelectedParentChainChangedNotifications {
listenersThatPropagate = append(listenersThatPropagate, listener)
}
}
return listenersThatPropagate
}
// NotifyFinalityConflict notifies the notification manager that there's a finality conflict in the DAG
func (nm *NotificationManager) NotifyFinalityConflict(notification *appmessage.FinalityConflictNotificationMessage) error {
nm.RLock()
@ -251,6 +278,12 @@ func newNotificationListener() *NotificationListener {
}
}
// IncludeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications returns true if this listener
// includes accepted transaction IDs in it's virtual-selected-parent-chain-changed notifications
func (nl *NotificationListener) IncludeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications() bool {
return nl.includeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications
}
// PropagateBlockAddedNotifications instructs the listener to send block added notifications
// to the remote listener
func (nl *NotificationListener) PropagateBlockAddedNotifications() {
@ -259,8 +292,9 @@ func (nl *NotificationListener) PropagateBlockAddedNotifications() {
// PropagateVirtualSelectedParentChainChangedNotifications instructs the listener to send chain changed notifications
// to the remote listener
func (nl *NotificationListener) PropagateVirtualSelectedParentChainChangedNotifications() {
func (nl *NotificationListener) PropagateVirtualSelectedParentChainChangedNotifications(includeAcceptedTransactionIDs bool) {
nl.propagateVirtualSelectedParentChainChangedNotifications = true
nl.includeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications = includeAcceptedTransactionIDs
}
// PropagateFinalityConflictNotifications instructs the listener to send finality conflict notifications

View File

@ -26,12 +26,14 @@ func HandleGetVirtualSelectedParentChainFromBlock(context *rpccontext.Context, _
return response, nil
}
chainChangedNotification, err := context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(virtualSelectedParentChain)
chainChangedNotification, err := context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
virtualSelectedParentChain, getVirtualSelectedParentChainFromBlockRequest.IncludeAcceptedTransactionIDs)
if err != nil {
return nil, err
}
response := appmessage.NewGetVirtualSelectedParentChainFromBlockResponseMessage(
chainChangedNotification.RemovedChainBlockHashes, chainChangedNotification.AddedChainBlockHashes)
chainChangedNotification.RemovedChainBlockHashes, chainChangedNotification.AddedChainBlockHashes,
chainChangedNotification.AcceptedTransactionIDs)
return response, nil
}

View File

@ -7,12 +7,17 @@ import (
)
// HandleNotifyVirtualSelectedParentChainChanged handles the respectively named RPC command
func HandleNotifyVirtualSelectedParentChainChanged(context *rpccontext.Context, router *router.Router, _ appmessage.Message) (appmessage.Message, error) {
func HandleNotifyVirtualSelectedParentChainChanged(context *rpccontext.Context, router *router.Router,
request appmessage.Message) (appmessage.Message, error) {
notifyVirtualSelectedParentChainChangedRequest := request.(*appmessage.NotifyVirtualSelectedParentChainChangedRequestMessage)
listener, err := context.NotificationManager.Listener(router)
if err != nil {
return nil, err
}
listener.PropagateVirtualSelectedParentChainChangedNotifications()
listener.PropagateVirtualSelectedParentChainChangedNotifications(
notifyVirtualSelectedParentChainChangedRequest.IncludeAcceptedTransactionIDs)
response := appmessage.NewNotifyVirtualSelectedParentChainChangedResponseMessage()
return response, nil

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.17.2
// protoc v3.12.3
// source: messages.proto
package protowire

View File

@ -1,8 +1,4 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.17.2
// source: messages.proto
package protowire

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.17.2
// protoc v3.12.3
// source: p2p.proto
package protowire

View File

@ -301,6 +301,7 @@ message SubmitTransactionResponseMessage{
//
// See: VirtualSelectedParentChainChangedNotificationMessage
message NotifyVirtualSelectedParentChainChangedRequestMessage{
bool includeAcceptedTransactionIds = 1;
}
message NotifyVirtualSelectedParentChainChangedResponseMessage{
@ -317,6 +318,9 @@ message VirtualSelectedParentChainChangedNotificationMessage{
// The chain blocks that were added, in low-to-high order
repeated string addedChainBlockHashes = 3;
// Will be filled only if `includeAcceptedTransactionIds = true` in the notify request.
repeated AcceptedTransactionIds acceptedTransactionIds = 2;
}
// GetBlockRequestMessage requests information about a specific block
@ -349,6 +353,12 @@ message GetSubnetworkResponseMessage{
// parent chain from some startHash to this kaspad's current virtual
message GetVirtualSelectedParentChainFromBlockRequestMessage{
string startHash = 1;
bool includeAcceptedTransactionIds = 2;
}
message AcceptedTransactionIds{
string acceptingBlockHash = 1;
repeated string acceptedTransactionIds = 2;
}
message GetVirtualSelectedParentChainFromBlockResponseMessage{
@ -358,6 +368,10 @@ message GetVirtualSelectedParentChainFromBlockResponseMessage{
// The chain blocks that were added, in low-to-high order
repeated string addedChainBlockHashes = 3;
// The transactions accepted by each block in addedChainBlockHashes.
// Will be filled only if `includeAcceptedTransactionIds = true` in the request.
repeated AcceptedTransactionIds acceptedTransactionIds = 2;
RPCError error = 1000;
}

View File

@ -43,8 +43,13 @@ func (x *KaspadMessage_GetVirtualSelectedParentChainFromBlockResponse) fromAppMe
x.GetVirtualSelectedParentChainFromBlockResponse = &GetVirtualSelectedParentChainFromBlockResponseMessage{
RemovedChainBlockHashes: message.RemovedChainBlockHashes,
AddedChainBlockHashes: message.AddedChainBlockHashes,
AcceptedTransactionIds: make([]*AcceptedTransactionIds, len(message.AcceptedTransactionIDs)),
Error: err,
}
for i, acceptedTransactionIDs := range message.AcceptedTransactionIDs {
x.GetVirtualSelectedParentChainFromBlockResponse.AcceptedTransactionIds[i] = &AcceptedTransactionIds{}
x.GetVirtualSelectedParentChainFromBlockResponse.AcceptedTransactionIds[i].fromAppMessage(acceptedTransactionIDs)
}
return nil
}
@ -62,9 +67,28 @@ func (x *GetVirtualSelectedParentChainFromBlockResponseMessage) toAppMessage() (
return nil, errors.New("GetVirtualSelectedParentChainFromBlockResponseMessage contains both an error and a response")
}
return &appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage{
message := &appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage{
RemovedChainBlockHashes: x.RemovedChainBlockHashes,
AddedChainBlockHashes: x.AddedChainBlockHashes,
AcceptedTransactionIDs: make([]*appmessage.AcceptedTransactionIDs, len(x.AcceptedTransactionIds)),
Error: rpcErr,
}, nil
}
for i, acceptedTransactionIds := range x.AcceptedTransactionIds {
message.AcceptedTransactionIDs[i] = acceptedTransactionIds.toAppMessage()
}
return message, nil
}
func (x *AcceptedTransactionIds) fromAppMessage(acceptedTransactionIDs *appmessage.AcceptedTransactionIDs) {
x.AcceptingBlockHash = acceptedTransactionIDs.AcceptingBlockHash
x.AcceptedTransactionIds = acceptedTransactionIDs.AcceptedTransactionIDs
}
func (x *AcceptedTransactionIds) toAppMessage() *appmessage.AcceptedTransactionIDs {
return &appmessage.AcceptedTransactionIDs{
AcceptingBlockHash: x.AcceptingBlockHash,
AcceptedTransactionIDs: x.AcceptedTransactionIds,
}
}

View File

@ -9,11 +9,15 @@ func (x *KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest) toAppMess
if x == nil {
return nil, errors.Wrapf(errorNil, "KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest is nil")
}
return &appmessage.NotifyVirtualSelectedParentChainChangedRequestMessage{}, nil
return &appmessage.NotifyVirtualSelectedParentChainChangedRequestMessage{
IncludeAcceptedTransactionIDs: x.NotifyVirtualSelectedParentChainChangedRequest.IncludeAcceptedTransactionIds,
}, nil
}
func (x *KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest) fromAppMessage(_ *appmessage.NotifyVirtualSelectedParentChainChangedRequestMessage) error {
x.NotifyVirtualSelectedParentChainChangedRequest = &NotifyVirtualSelectedParentChainChangedRequestMessage{}
func (x *KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest) fromAppMessage(appmessage *appmessage.NotifyVirtualSelectedParentChainChangedRequestMessage) error {
x.NotifyVirtualSelectedParentChainChangedRequest = &NotifyVirtualSelectedParentChainChangedRequestMessage{
IncludeAcceptedTransactionIds: appmessage.IncludeAcceptedTransactionIDs,
}
return nil
}
@ -60,6 +64,12 @@ func (x *KaspadMessage_VirtualSelectedParentChainChangedNotification) fromAppMes
x.VirtualSelectedParentChainChangedNotification = &VirtualSelectedParentChainChangedNotificationMessage{
RemovedChainBlockHashes: message.RemovedChainBlockHashes,
AddedChainBlockHashes: message.AddedChainBlockHashes,
AcceptedTransactionIds: make([]*AcceptedTransactionIds, len(message.AcceptedTransactionIDs)),
}
for i, acceptedTransactionIDs := range message.AcceptedTransactionIDs {
x.VirtualSelectedParentChainChangedNotification.AcceptedTransactionIds[i] = &AcceptedTransactionIds{}
x.VirtualSelectedParentChainChangedNotification.AcceptedTransactionIds[i].fromAppMessage(acceptedTransactionIDs)
}
return nil
}
@ -68,8 +78,14 @@ func (x *VirtualSelectedParentChainChangedNotificationMessage) toAppMessage() (a
if x == nil {
return nil, errors.Wrapf(errorNil, "VirtualSelectedParentChainChangedNotificationMessage is nil")
}
return &appmessage.VirtualSelectedParentChainChangedNotificationMessage{
message := &appmessage.VirtualSelectedParentChainChangedNotificationMessage{
RemovedChainBlockHashes: x.RemovedChainBlockHashes,
AddedChainBlockHashes: x.AddedChainBlockHashes,
}, nil
AcceptedTransactionIDs: make([]*appmessage.AcceptedTransactionIDs, len(x.AcceptedTransactionIds)),
}
for i, acceptedTransactionIds := range x.AcceptedTransactionIds {
message.AcceptedTransactionIDs[i] = acceptedTransactionIds.toAppMessage()
}
return message, nil
}

View File

@ -3,8 +3,10 @@ package rpcclient
import "github.com/kaspanet/kaspad/app/appmessage"
// GetVirtualSelectedParentChainFromBlock sends an RPC request respective to the function's name and returns the RPC server's response
func (c *RPCClient) GetVirtualSelectedParentChainFromBlock(startHash string) (*appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage, error) {
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash))
func (c *RPCClient) GetVirtualSelectedParentChainFromBlock(startHash string, includeAcceptedTransactionIDs bool) (
*appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage, error) {
err := c.rpcRouter.outgoingRoute().Enqueue(
appmessage.NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash, includeAcceptedTransactionIDs))
if err != nil {
return nil, err
}

View File

@ -8,8 +8,11 @@ import (
// RegisterForVirtualSelectedParentChainChangedNotifications sends an RPC request respective to the function's name and returns the RPC server's response.
// Additionally, it starts listening for the appropriate notification using the given handler function
func (c *RPCClient) RegisterForVirtualSelectedParentChainChangedNotifications(onChainChanged func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage)) error {
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewNotifyVirtualSelectedParentChainChangedRequestMessage())
func (c *RPCClient) RegisterForVirtualSelectedParentChainChangedNotifications(includeAcceptedTransactionIDs bool,
onChainChanged func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage)) error {
err := c.rpcRouter.outgoingRoute().Enqueue(
appmessage.NewNotifyVirtualSelectedParentChainChangedRequestMessage(includeAcceptedTransactionIDs))
if err != nil {
return err
}

View File

@ -1,9 +1,10 @@
package integration
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"testing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
)
@ -15,7 +16,7 @@ func TestVirtualSelectedParentChain(t *testing.T) {
// Register to virtual selected parent chain changes
onVirtualSelectedParentChainChangedChan := make(chan *appmessage.VirtualSelectedParentChainChangedNotificationMessage)
err := kaspad1.rpcClient.RegisterForVirtualSelectedParentChainChangedNotifications(
err := kaspad1.rpcClient.RegisterForVirtualSelectedParentChainChangedNotifications(true,
func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage) {
onVirtualSelectedParentChainChangedChan <- notification
})
@ -64,36 +65,10 @@ func TestVirtualSelectedParentChain(t *testing.T) {
chain2TipHashString := chain2TipHash.String()
// For the first `blockAmountToMine - 1` blocks we don't expect
// the chain to change at all
for i := 0; i < blockAmountToMine-1; i++ {
notification := <-onVirtualSelectedParentChainChangedChan
if len(notification.RemovedChainBlockHashes) > 0 {
t.Fatalf("RemovedChainBlockHashes is unexpectedly not empty")
}
if len(notification.AddedChainBlockHashes) > 0 {
t.Fatalf("AddedChainBlockHashes is unexpectedly not empty")
}
}
// the chain to change at all, thus there will be no notifications
// Either the next block could cause a reorg or the one
// after it
potentialReorgNotification1 := <-onVirtualSelectedParentChainChangedChan
potentialReorgNotification2 := <-onVirtualSelectedParentChainChangedChan
var reorgNotification *appmessage.VirtualSelectedParentChainChangedNotificationMessage
var nonReorgNotification *appmessage.VirtualSelectedParentChainChangedNotificationMessage
if len(potentialReorgNotification1.RemovedChainBlockHashes) > 0 {
reorgNotification = potentialReorgNotification1
nonReorgNotification = potentialReorgNotification2
} else {
reorgNotification = potentialReorgNotification2
nonReorgNotification = potentialReorgNotification1
}
// Make sure that the non-reorg notification has nothing
// in `removed`
if len(nonReorgNotification.RemovedChainBlockHashes) > 0 {
t.Fatalf("nonReorgNotification.RemovedChainBlockHashes is unexpectedly not empty")
}
// Either the next block or the one after it will cause a reorg
reorgNotification := <-onVirtualSelectedParentChainChangedChan
// Make sure that the reorg notification contains exactly
// `blockAmountToMine` blocks in its `removed`
@ -104,7 +79,8 @@ func TestVirtualSelectedParentChain(t *testing.T) {
// Get the virtual selected parent chain from the tip of
// the first chain
virtualSelectedParentChainFromChain1Tip, err := kaspad1.rpcClient.GetVirtualSelectedParentChainFromBlock(chain1TipHashString)
virtualSelectedParentChainFromChain1Tip, err := kaspad1.rpcClient.GetVirtualSelectedParentChainFromBlock(
chain1TipHashString, true)
if err != nil {
t.Fatalf("GetVirtualSelectedParentChainFromBlock failed: %s", err)
}