diff --git a/app/appmessage/message.go b/app/appmessage/message.go index fe6afb4fb..c5a69c2f9 100644 --- a/app/appmessage/message.go +++ b/app/appmessage/message.go @@ -139,6 +139,9 @@ const ( CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage CmdEstimateNetworkHashesPerSecondRequestMessage CmdEstimateNetworkHashesPerSecondResponseMessage + CmdNotifyVirtualDaaScoreChangedRequestMessage + CmdNotifyVirtualDaaScoreChangedResponseMessage + CmdVirtualDaaScoreChangedNotificationMessage ) // ProtocolMessageCommandToString maps all MessageCommands to their string representation @@ -252,6 +255,9 @@ var RPCMessageCommandToString = map[MessageCommand]string{ CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage: "StopNotifyingPruningPointUTXOSetOverrideResponse", CmdEstimateNetworkHashesPerSecondRequestMessage: "EstimateNetworkHashesPerSecondRequest", CmdEstimateNetworkHashesPerSecondResponseMessage: "EstimateNetworkHashesPerSecondResponse", + CmdNotifyVirtualDaaScoreChangedRequestMessage: "NotifyVirtualDaaScoreChangedRequest", + CmdNotifyVirtualDaaScoreChangedResponseMessage: "NotifyVirtualDaaScoreChangedResponse", + CmdVirtualDaaScoreChangedNotificationMessage: "VirtualDaaScoreChangedNotification", } // Message is an interface that describes a kaspa message. A type that diff --git a/app/appmessage/rpc_notify_virtual_daa_score_changed.go b/app/appmessage/rpc_notify_virtual_daa_score_changed.go new file mode 100644 index 000000000..583155262 --- /dev/null +++ b/app/appmessage/rpc_notify_virtual_daa_score_changed.go @@ -0,0 +1,55 @@ +package appmessage + +// NotifyVirtualDaaScoreChangedRequestMessage is an appmessage corresponding to +// its respective RPC message +type NotifyVirtualDaaScoreChangedRequestMessage struct { + baseMessage +} + +// Command returns the protocol command string for the message +func (msg *NotifyVirtualDaaScoreChangedRequestMessage) Command() MessageCommand { + return CmdNotifyVirtualDaaScoreChangedRequestMessage +} + +// NewNotifyVirtualDaaScoreChangedRequestMessage returns a instance of the message +func NewNotifyVirtualDaaScoreChangedRequestMessage() *NotifyVirtualDaaScoreChangedRequestMessage { + return &NotifyVirtualDaaScoreChangedRequestMessage{} +} + +// NotifyVirtualDaaScoreChangedResponseMessage is an appmessage corresponding to +// its respective RPC message +type NotifyVirtualDaaScoreChangedResponseMessage struct { + baseMessage + Error *RPCError +} + +// Command returns the protocol command string for the message +func (msg *NotifyVirtualDaaScoreChangedResponseMessage) Command() MessageCommand { + return CmdNotifyVirtualDaaScoreChangedResponseMessage +} + +// NewNotifyVirtualDaaScoreChangedResponseMessage returns a instance of the message +func NewNotifyVirtualDaaScoreChangedResponseMessage() *NotifyVirtualDaaScoreChangedResponseMessage { + return &NotifyVirtualDaaScoreChangedResponseMessage{} +} + +// VirtualDaaScoreChangedNotificationMessage is an appmessage corresponding to +// its respective RPC message +type VirtualDaaScoreChangedNotificationMessage struct { + baseMessage + VirtualDaaScore uint64 +} + +// Command returns the protocol command string for the message +func (msg *VirtualDaaScoreChangedNotificationMessage) Command() MessageCommand { + return CmdVirtualDaaScoreChangedNotificationMessage +} + +// NewVirtualDaaScoreChangedNotificationMessage returns a instance of the message +func NewVirtualDaaScoreChangedNotificationMessage( + virtualDaaScore uint64) *VirtualDaaScoreChangedNotificationMessage { + + return &VirtualDaaScoreChangedNotificationMessage{ + VirtualDaaScore: virtualDaaScore, + } +} diff --git a/app/rpc/manager.go b/app/rpc/manager.go index ffd5c0823..51f5ff08f 100644 --- a/app/rpc/manager.go +++ b/app/rpc/manager.go @@ -64,6 +64,11 @@ func (m *Manager) NotifyBlockAddedToDAG(block *externalapi.DomainBlock, blockIns return err } + err = m.notifyVirtualDaaScoreChanged() + if err != nil { + return err + } + err = m.notifyVirtualSelectedParentChainChanged(blockInsertionResult) if err != nil { return err @@ -153,6 +158,19 @@ func (m *Manager) notifyVirtualSelectedParentBlueScoreChanged() error { return m.context.NotificationManager.NotifyVirtualSelectedParentBlueScoreChanged(notification) } +func (m *Manager) notifyVirtualDaaScoreChanged() error { + onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualDaaScoreChanged") + defer onEnd() + + virtualInfo, err := m.context.Domain.Consensus().GetVirtualInfo() + if err != nil { + return err + } + + notification := appmessage.NewVirtualDaaScoreChangedNotificationMessage(virtualInfo.DAAScore) + return m.context.NotificationManager.NotifyVirtualDaaScoreChanged(notification) +} + func (m *Manager) notifyVirtualSelectedParentChainChanged(blockInsertionResult *externalapi.BlockInsertionResult) error { onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualSelectedParentChainChanged") defer onEnd() diff --git a/app/rpc/rpc.go b/app/rpc/rpc.go index ddf3957a0..e3fd1a7d4 100644 --- a/app/rpc/rpc.go +++ b/app/rpc/rpc.go @@ -45,6 +45,7 @@ var handlers = map[appmessage.MessageCommand]handler{ appmessage.CmdNotifyPruningPointUTXOSetOverrideRequestMessage: rpchandlers.HandleNotifyPruningPointUTXOSetOverrideRequest, appmessage.CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage: rpchandlers.HandleStopNotifyingPruningPointUTXOSetOverrideRequest, appmessage.CmdEstimateNetworkHashesPerSecondRequestMessage: rpchandlers.HandleEstimateNetworkHashesPerSecond, + appmessage.CmdNotifyVirtualDaaScoreChangedRequestMessage: rpchandlers.HandleNotifyVirtualDaaScoreChanged, } func (m *Manager) routerInitializer(router *router.Router, netConnection *netadapter.NetConnection) { diff --git a/app/rpc/rpccontext/notificationmanager.go b/app/rpc/rpccontext/notificationmanager.go index 58b1f2b6b..c75e79195 100644 --- a/app/rpc/rpccontext/notificationmanager.go +++ b/app/rpc/rpccontext/notificationmanager.go @@ -30,6 +30,7 @@ type NotificationListener struct { propagateFinalityConflictResolvedNotifications bool propagateUTXOsChangedNotifications bool propagateVirtualSelectedParentBlueScoreChangedNotifications bool + propagateVirtualDaaScoreChangedNotifications bool propagatePruningPointUTXOSetOverrideNotifications bool propagateUTXOsChangedNotificationAddresses map[utxoindex.ScriptPublicKeyString]*UTXOsChangedNotificationAddress @@ -181,6 +182,25 @@ func (nm *NotificationManager) NotifyVirtualSelectedParentBlueScoreChanged( return nil } +// NotifyVirtualDaaScoreChanged notifies the notification manager that the DAG's +// virtual DAA score has changed +func (nm *NotificationManager) NotifyVirtualDaaScoreChanged( + notification *appmessage.VirtualDaaScoreChangedNotificationMessage) error { + + nm.RLock() + defer nm.RUnlock() + + for router, listener := range nm.listeners { + if listener.propagateVirtualDaaScoreChangedNotifications { + err := router.OutgoingRoute().Enqueue(notification) + if err != nil { + return err + } + } + } + return nil +} + // NotifyPruningPointUTXOSetOverride notifies the notification manager that the UTXO index // reset due to pruning point change via IBD. func (nm *NotificationManager) NotifyPruningPointUTXOSetOverride() error { @@ -308,6 +328,12 @@ func (nl *NotificationListener) PropagateVirtualSelectedParentBlueScoreChangedNo nl.propagateVirtualSelectedParentBlueScoreChangedNotifications = true } +// PropagateVirtualDaaScoreChangedNotifications instructs the listener to send +// virtual DAA score notifications to the remote listener +func (nl *NotificationListener) PropagateVirtualDaaScoreChangedNotifications() { + nl.propagateVirtualDaaScoreChangedNotifications = true +} + // PropagatePruningPointUTXOSetOverrideNotifications instructs the listener to send pruning point UTXO set override notifications // to the remote listener. func (nl *NotificationListener) PropagatePruningPointUTXOSetOverrideNotifications() { diff --git a/app/rpc/rpchandlers/notify_virtual_daa_score_changed.go b/app/rpc/rpchandlers/notify_virtual_daa_score_changed.go new file mode 100644 index 000000000..d7d6d8329 --- /dev/null +++ b/app/rpc/rpchandlers/notify_virtual_daa_score_changed.go @@ -0,0 +1,19 @@ +package rpchandlers + +import ( + "github.com/kaspanet/kaspad/app/appmessage" + "github.com/kaspanet/kaspad/app/rpc/rpccontext" + "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" +) + +// HandleNotifyVirtualDaaScoreChanged handles the respectively named RPC command +func HandleNotifyVirtualDaaScoreChanged(context *rpccontext.Context, router *router.Router, _ appmessage.Message) (appmessage.Message, error) { + listener, err := context.NotificationManager.Listener(router) + if err != nil { + return nil, err + } + listener.PropagateVirtualDaaScoreChangedNotifications() + + response := appmessage.NewNotifyVirtualDaaScoreChangedResponseMessage() + return response, nil +} diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto b/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto index 421a65180..85b0f96a3 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/messages.proto @@ -114,6 +114,9 @@ message KaspadMessage { StopNotifyingPruningPointUTXOSetOverrideResponseMessage stopNotifyingPruningPointUTXOSetOverrideResponse = 1071; EstimateNetworkHashesPerSecondRequestMessage estimateNetworkHashesPerSecondRequest = 1072; EstimateNetworkHashesPerSecondResponseMessage estimateNetworkHashesPerSecondResponse = 1073; + NotifyVirtualDaaScoreChangedRequestMessage notifyVirtualDaaScoreChangedRequest = 1072; + NotifyVirtualDaaScoreChangedResponseMessage notifyVirtualDaaScoreChangedResponse = 1073; + VirtualDaaScoreChangedNotificationMessage virtualDaaScoreChangedNotification = 1074; } } diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go index 102e61cfd..09653ed68 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/messages_grpc.pb.go @@ -11,7 +11,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 // P2PClient is the client API for P2P service. // @@ -29,7 +30,7 @@ func NewP2PClient(cc grpc.ClientConnInterface) P2PClient { } func (c *p2PClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (P2P_MessageStreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_P2P_serviceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...) + stream, err := c.cc.NewStream(ctx, &P2P_ServiceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...) if err != nil { return nil, err } @@ -71,13 +72,20 @@ type P2PServer interface { type UnimplementedP2PServer struct { } -func (*UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error { +func (UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error { return status.Errorf(codes.Unimplemented, "method MessageStream not implemented") } -func (*UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {} +func (UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {} -func RegisterP2PServer(s *grpc.Server, srv P2PServer) { - s.RegisterService(&_P2P_serviceDesc, srv) +// UnsafeP2PServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to P2PServer will +// result in compilation errors. +type UnsafeP2PServer interface { + mustEmbedUnimplementedP2PServer() +} + +func RegisterP2PServer(s grpc.ServiceRegistrar, srv P2PServer) { + s.RegisterService(&P2P_ServiceDesc, srv) } func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error { @@ -106,7 +114,10 @@ func (x *p2PMessageStreamServer) Recv() (*KaspadMessage, error) { return m, nil } -var _P2P_serviceDesc = grpc.ServiceDesc{ +// P2P_ServiceDesc is the grpc.ServiceDesc for P2P service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var P2P_ServiceDesc = grpc.ServiceDesc{ ServiceName: "protowire.P2P", HandlerType: (*P2PServer)(nil), Methods: []grpc.MethodDesc{}, @@ -137,7 +148,7 @@ func NewRPCClient(cc grpc.ClientConnInterface) RPCClient { } func (c *rPCClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (RPC_MessageStreamClient, error) { - stream, err := c.cc.NewStream(ctx, &_RPC_serviceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...) + stream, err := c.cc.NewStream(ctx, &RPC_ServiceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...) if err != nil { return nil, err } @@ -179,13 +190,20 @@ type RPCServer interface { type UnimplementedRPCServer struct { } -func (*UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error { +func (UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error { return status.Errorf(codes.Unimplemented, "method MessageStream not implemented") } -func (*UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {} +func (UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {} -func RegisterRPCServer(s *grpc.Server, srv RPCServer) { - s.RegisterService(&_RPC_serviceDesc, srv) +// UnsafeRPCServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RPCServer will +// result in compilation errors. +type UnsafeRPCServer interface { + mustEmbedUnimplementedRPCServer() +} + +func RegisterRPCServer(s grpc.ServiceRegistrar, srv RPCServer) { + s.RegisterService(&RPC_ServiceDesc, srv) } func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error { @@ -214,7 +232,10 @@ func (x *rPCMessageStreamServer) Recv() (*KaspadMessage, error) { return m, nil } -var _RPC_serviceDesc = grpc.ServiceDesc{ +// RPC_ServiceDesc is the grpc.ServiceDesc for RPC service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var RPC_ServiceDesc = grpc.ServiceDesc{ ServiceName: "protowire.RPC", HandlerType: (*RPCServer)(nil), Methods: []grpc.MethodDesc{}, diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go index e32ec2205..449a1c050 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/p2p.pb.go @@ -1,13 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 +// protoc-gen-go v1.26.0 // protoc v3.12.3 // source: p2p.proto package protowire import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -21,10 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - type RequestAddressesMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto index d38682449..08b3a0732 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto @@ -528,6 +528,25 @@ message VirtualSelectedParentBlueScoreChangedNotificationMessage { uint64 virtualSelectedParentBlueScore = 1; } +// NotifyVirtualDaaScoreChangedRequestMessage registers this connection for +// virtualDaaScoreChanged notifications. +// +// See: VirtualDaaScoreChangedNotificationMessage +message NotifyVirtualDaaScoreChangedRequestMessage { +} + +message NotifyVirtualDaaScoreChangedResponseMessage { + RPCError error = 1000; +} + +// VirtualDaaScoreChangedNotificationMessage is sent whenever the DAA score +// of the virtual changes. +// +// See NotifyVirtualDaaScoreChangedRequestMessage +message VirtualDaaScoreChangedNotificationMessage { + uint64 virtualDaaScore = 1; +} + // NotifyPruningPointUTXOSetOverrideRequestMessage registers this connection for // pruning point UTXO set override notifications. // diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_notify_virtual_daa_score_changed.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_notify_virtual_daa_score_changed.go new file mode 100644 index 000000000..b6b59ea46 --- /dev/null +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_notify_virtual_daa_score_changed.go @@ -0,0 +1,73 @@ +package protowire + +import ( + "github.com/kaspanet/kaspad/app/appmessage" + "github.com/pkg/errors" +) + +func (x *KaspadMessage_NotifyVirtualDaaScoreChangedRequest) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "KaspadMessage_NotifyVirtualDaaScoreChangedRequest is nil") + } + return &appmessage.NotifyVirtualDaaScoreChangedRequestMessage{}, nil +} + +func (x *KaspadMessage_NotifyVirtualDaaScoreChangedRequest) fromAppMessage(_ *appmessage.NotifyVirtualDaaScoreChangedRequestMessage) error { + x.NotifyVirtualDaaScoreChangedRequest = &NotifyVirtualDaaScoreChangedRequestMessage{} + return nil +} + +func (x *KaspadMessage_NotifyVirtualDaaScoreChangedResponse) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "KaspadMessage_NotifyVirtualDaaScoreChangedResponse is nil") + } + return x.NotifyVirtualDaaScoreChangedResponse.toAppMessage() +} + +func (x *KaspadMessage_NotifyVirtualDaaScoreChangedResponse) fromAppMessage(message *appmessage.NotifyVirtualDaaScoreChangedResponseMessage) error { + var err *RPCError + if message.Error != nil { + err = &RPCError{Message: message.Error.Message} + } + x.NotifyVirtualDaaScoreChangedResponse = &NotifyVirtualDaaScoreChangedResponseMessage{ + Error: err, + } + return nil +} + +func (x *NotifyVirtualDaaScoreChangedResponseMessage) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "NotifyVirtualDaaScoreChangedResponseMessage is nil") + } + rpcErr, err := x.Error.toAppMessage() + // Error is an optional field + if err != nil && !errors.Is(err, errorNil) { + return nil, err + } + return &appmessage.NotifyVirtualDaaScoreChangedResponseMessage{ + Error: rpcErr, + }, nil +} + +func (x *KaspadMessage_VirtualDaaScoreChangedNotification) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "KaspadMessage_VirtualDaaScoreChangedNotification is nil") + } + return x.VirtualDaaScoreChangedNotification.toAppMessage() +} + +func (x *KaspadMessage_VirtualDaaScoreChangedNotification) fromAppMessage(message *appmessage.VirtualDaaScoreChangedNotificationMessage) error { + x.VirtualDaaScoreChangedNotification = &VirtualDaaScoreChangedNotificationMessage{ + VirtualDaaScore: message.VirtualDaaScore, + } + return nil +} + +func (x *VirtualDaaScoreChangedNotificationMessage) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "VirtualDaaScoreChangedNotificationMessage is nil") + } + return &appmessage.VirtualDaaScoreChangedNotificationMessage{ + VirtualDaaScore: x.VirtualDaaScore, + }, nil +} diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go b/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go index 51f312664..04da3e9a2 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/wire.go @@ -793,6 +793,27 @@ func toRPCPayload(message appmessage.Message) (isKaspadMessage_Payload, error) { return nil, err } return payload, nil + case *appmessage.NotifyVirtualDaaScoreChangedRequestMessage: + payload := new(KaspadMessage_NotifyVirtualDaaScoreChangedRequest) + err := payload.fromAppMessage(message) + if err != nil { + return nil, err + } + return payload, nil + case *appmessage.NotifyVirtualDaaScoreChangedResponseMessage: + payload := new(KaspadMessage_NotifyVirtualDaaScoreChangedResponse) + err := payload.fromAppMessage(message) + if err != nil { + return nil, err + } + return payload, nil + case *appmessage.VirtualDaaScoreChangedNotificationMessage: + payload := new(KaspadMessage_VirtualDaaScoreChangedNotification) + err := payload.fromAppMessage(message) + if err != nil { + return nil, err + } + return payload, nil default: return nil, nil } diff --git a/infrastructure/network/rpcclient/rpc_on_virtual_daa_score_changed.go b/infrastructure/network/rpcclient/rpc_on_virtual_daa_score_changed.go new file mode 100644 index 000000000..8b6d044d0 --- /dev/null +++ b/infrastructure/network/rpcclient/rpc_on_virtual_daa_score_changed.go @@ -0,0 +1,41 @@ +package rpcclient + +import ( + "github.com/kaspanet/kaspad/app/appmessage" + routerpkg "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" + "github.com/pkg/errors" +) + +// RegisterForVirtualDaaScoreChangedNotifications 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) RegisterForVirtualDaaScoreChangedNotifications( + onVirtualDaaScoreChanged func(notification *appmessage.VirtualDaaScoreChangedNotificationMessage)) error { + + err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewNotifyVirtualDaaScoreChangedRequestMessage()) + if err != nil { + return err + } + response, err := c.route(appmessage.CmdNotifyVirtualDaaScoreChangedResponseMessage).DequeueWithTimeout(c.timeout) + if err != nil { + return err + } + notifyVirtualDaaScoreChangedResponse := response.(*appmessage.NotifyVirtualDaaScoreChangedResponseMessage) + if notifyVirtualDaaScoreChangedResponse.Error != nil { + return c.convertRPCError(notifyVirtualDaaScoreChangedResponse.Error) + } + spawn("RegisterForVirtualDaaScoreChangedNotifications", func() { + for { + notification, err := c.route(appmessage.CmdVirtualDaaScoreChangedNotificationMessage).Dequeue() + if err != nil { + if errors.Is(err, routerpkg.ErrRouteClosed) { + break + } + panic(err) + } + VirtualDaaScoreChangedNotification := notification.(*appmessage.VirtualDaaScoreChangedNotificationMessage) + onVirtualDaaScoreChanged(VirtualDaaScoreChangedNotification) + } + }) + return nil +} diff --git a/testing/integration/virtual_selected_parent_blue_score_test.go b/testing/integration/virtual_selected_parent_blue_score_test.go index f3ce0969e..2d22289bd 100644 --- a/testing/integration/virtual_selected_parent_blue_score_test.go +++ b/testing/integration/virtual_selected_parent_blue_score_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestVirtualSelectedParentBlueScore(t *testing.T) { +func TestVirtualSelectedParentBlueScoreAndVirtualDAAScore(t *testing.T) { // Setup a single kaspad instance harnessParams := &harnessParams{ p2pAddress: p2pAddress1, @@ -38,15 +38,30 @@ func TestVirtualSelectedParentBlueScore(t *testing.T) { "blue score change notifications: %s", err) } + // Register to virtual DAA score changes + onVirtualDaaScoreChangedChan := make(chan *appmessage.VirtualDaaScoreChangedNotificationMessage) + err = kaspad.rpcClient.RegisterForVirtualDaaScoreChangedNotifications( + func(notification *appmessage.VirtualDaaScoreChangedNotificationMessage) { + onVirtualDaaScoreChangedChan <- notification + }) + if err != nil { + t.Fatalf("Failed to register for virtual DAA score change notifications: %s", err) + } + // Mine some blocks and make sure that the notifications - // report correct blue score values + // report correct values const blockAmountToMine = 100 for i := 0; i < blockAmountToMine; i++ { mineNextBlock(t, kaspad) - notification := <-onVirtualSelectedParentBlueScoreChangedChan - if notification.VirtualSelectedParentBlueScore != 1+uint64(i) { + blueScoreChangedNotification := <-onVirtualSelectedParentBlueScoreChangedChan + if blueScoreChangedNotification.VirtualSelectedParentBlueScore != 1+uint64(i) { t.Fatalf("Unexpected virtual selected parent blue score. Want: %d, got: %d", - 1+uint64(i), notification.VirtualSelectedParentBlueScore) + 1+uint64(i), blueScoreChangedNotification.VirtualSelectedParentBlueScore) + } + daaScoreChangedNotification := <-onVirtualDaaScoreChangedChan + if daaScoreChangedNotification.VirtualDaaScore > 1+uint64(i) { + t.Fatalf("Unexpected virtual DAA score. Want: %d, got: %d", + 1+uint64(i), daaScoreChangedNotification.VirtualDaaScore) } }