mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-07-09 14:22:33 +00:00
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:
parent
1660cf0cf1
commit
52fbeedf20
@ -5,6 +5,7 @@ package appmessage
|
|||||||
type GetVirtualSelectedParentChainFromBlockRequestMessage struct {
|
type GetVirtualSelectedParentChainFromBlockRequestMessage struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
StartHash string
|
StartHash string
|
||||||
|
IncludeAcceptedTransactionIDs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
// 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
|
// NewGetVirtualSelectedParentChainFromBlockRequestMessage returns a instance of the message
|
||||||
func NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash string) *GetVirtualSelectedParentChainFromBlockRequestMessage {
|
func NewGetVirtualSelectedParentChainFromBlockRequestMessage(
|
||||||
|
startHash string, includeAcceptedTransactionIDs bool) *GetVirtualSelectedParentChainFromBlockRequestMessage {
|
||||||
|
|
||||||
return &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
|
// GetVirtualSelectedParentChainFromBlockResponseMessage is an appmessage corresponding to
|
||||||
// its respective RPC message
|
// its respective RPC message
|
||||||
type GetVirtualSelectedParentChainFromBlockResponseMessage struct {
|
type GetVirtualSelectedParentChainFromBlockResponseMessage struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
RemovedChainBlockHashes []string
|
RemovedChainBlockHashes []string
|
||||||
AddedChainBlockHashes []string
|
AddedChainBlockHashes []string
|
||||||
|
AcceptedTransactionIDs []*AcceptedTransactionIDs
|
||||||
|
|
||||||
Error *RPCError
|
Error *RPCError
|
||||||
}
|
}
|
||||||
@ -36,10 +48,11 @@ func (msg *GetVirtualSelectedParentChainFromBlockResponseMessage) Command() Mess
|
|||||||
|
|
||||||
// NewGetVirtualSelectedParentChainFromBlockResponseMessage returns a instance of the message
|
// NewGetVirtualSelectedParentChainFromBlockResponseMessage returns a instance of the message
|
||||||
func NewGetVirtualSelectedParentChainFromBlockResponseMessage(removedChainBlockHashes,
|
func NewGetVirtualSelectedParentChainFromBlockResponseMessage(removedChainBlockHashes,
|
||||||
addedChainBlockHashes []string) *GetVirtualSelectedParentChainFromBlockResponseMessage {
|
addedChainBlockHashes []string, acceptedTransactionIDs []*AcceptedTransactionIDs) *GetVirtualSelectedParentChainFromBlockResponseMessage {
|
||||||
|
|
||||||
return &GetVirtualSelectedParentChainFromBlockResponseMessage{
|
return &GetVirtualSelectedParentChainFromBlockResponseMessage{
|
||||||
RemovedChainBlockHashes: removedChainBlockHashes,
|
RemovedChainBlockHashes: removedChainBlockHashes,
|
||||||
AddedChainBlockHashes: addedChainBlockHashes,
|
AddedChainBlockHashes: addedChainBlockHashes,
|
||||||
|
AcceptedTransactionIDs: acceptedTransactionIDs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ package appmessage
|
|||||||
// its respective RPC message
|
// its respective RPC message
|
||||||
type NotifyVirtualSelectedParentChainChangedRequestMessage struct {
|
type NotifyVirtualSelectedParentChainChangedRequestMessage struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
|
IncludeAcceptedTransactionIDs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
// Command returns the protocol command string for the message
|
||||||
@ -11,9 +12,13 @@ func (msg *NotifyVirtualSelectedParentChainChangedRequestMessage) Command() Mess
|
|||||||
return CmdNotifyVirtualSelectedParentChainChangedRequestMessage
|
return CmdNotifyVirtualSelectedParentChainChangedRequestMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNotifyVirtualSelectedParentChainChangedRequestMessage returns a instance of the message
|
// NewNotifyVirtualSelectedParentChainChangedRequestMessage returns an instance of the message
|
||||||
func NewNotifyVirtualSelectedParentChainChangedRequestMessage() *NotifyVirtualSelectedParentChainChangedRequestMessage {
|
func NewNotifyVirtualSelectedParentChainChangedRequestMessage(
|
||||||
return &NotifyVirtualSelectedParentChainChangedRequestMessage{}
|
includeAcceptedTransactionIDs bool) *NotifyVirtualSelectedParentChainChangedRequestMessage {
|
||||||
|
|
||||||
|
return &NotifyVirtualSelectedParentChainChangedRequestMessage{
|
||||||
|
IncludeAcceptedTransactionIDs: includeAcceptedTransactionIDs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyVirtualSelectedParentChainChangedResponseMessage is an appmessage corresponding to
|
// NotifyVirtualSelectedParentChainChangedResponseMessage is an appmessage corresponding to
|
||||||
@ -39,6 +44,7 @@ type VirtualSelectedParentChainChangedNotificationMessage struct {
|
|||||||
baseMessage
|
baseMessage
|
||||||
RemovedChainBlockHashes []string
|
RemovedChainBlockHashes []string
|
||||||
AddedChainBlockHashes []string
|
AddedChainBlockHashes []string
|
||||||
|
AcceptedTransactionIDs []*AcceptedTransactionIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
// 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
|
// NewVirtualSelectedParentChainChangedNotificationMessage returns a instance of the message
|
||||||
func NewVirtualSelectedParentChainChangedNotificationMessage(removedChainBlockHashes,
|
func NewVirtualSelectedParentChainChangedNotificationMessage(removedChainBlockHashes,
|
||||||
addedChainBlocks []string) *VirtualSelectedParentChainChangedNotificationMessage {
|
addedChainBlocks []string, acceptedTransactionIDs []*AcceptedTransactionIDs) *VirtualSelectedParentChainChangedNotificationMessage {
|
||||||
|
|
||||||
return &VirtualSelectedParentChainChangedNotificationMessage{
|
return &VirtualSelectedParentChainChangedNotificationMessage{
|
||||||
RemovedChainBlockHashes: removedChainBlockHashes,
|
RemovedChainBlockHashes: removedChainBlockHashes,
|
||||||
AddedChainBlockHashes: addedChainBlocks,
|
AddedChainBlockHashes: addedChainBlocks,
|
||||||
|
AcceptedTransactionIDs: acceptedTransactionIDs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,18 +52,25 @@ func (m *Manager) NotifyBlockAddedToDAG(block *externalapi.DomainBlock, virtualC
|
|||||||
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyBlockAddedToDAG")
|
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyBlockAddedToDAG")
|
||||||
defer onEnd()
|
defer onEnd()
|
||||||
|
|
||||||
err := m.NotifyVirtualChange(virtualChangeSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcBlock := appmessage.DomainBlockToRPCBlock(block)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
blockAddedNotification := appmessage.NewBlockAddedNotificationMessage(rpcBlock)
|
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.
|
// 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")
|
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualSelectedParentChainChanged")
|
||||||
defer onEnd()
|
defer onEnd()
|
||||||
|
|
||||||
|
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(
|
notification, err := m.context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
|
||||||
virtualChangeSet.VirtualSelectedParentChainChanges)
|
virtualChangeSet.VirtualSelectedParentChainChanges, includeAcceptedTransactionIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return m.context.NotificationManager.NotifyVirtualSelectedParentChainChanged(notification)
|
return m.context.NotificationManager.NotifyVirtualSelectedParentChainChanged(notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -3,12 +3,14 @@ package rpccontext
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage converts
|
// ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage converts
|
||||||
// VirtualSelectedParentChainChanges to VirtualSelectedParentChainChangedNotificationMessage
|
// VirtualSelectedParentChainChanges to VirtualSelectedParentChainChangedNotificationMessage
|
||||||
func (ctx *Context) ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
|
func (ctx *Context) ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
|
||||||
selectedParentChainChanges *externalapi.SelectedChainPath) (*appmessage.VirtualSelectedParentChainChangedNotificationMessage, error) {
|
selectedParentChainChanges *externalapi.SelectedChainPath, includeAcceptedTransactionIDs bool) (
|
||||||
|
*appmessage.VirtualSelectedParentChainChangedNotificationMessage, error) {
|
||||||
|
|
||||||
removedChainBlockHashes := make([]string, len(selectedParentChainChanges.Removed))
|
removedChainBlockHashes := make([]string, len(selectedParentChainChanges.Removed))
|
||||||
for i, removed := range selectedParentChainChanges.Removed {
|
for i, removed := range selectedParentChainChanges.Removed {
|
||||||
@ -20,5 +22,43 @@ func (ctx *Context) ConvertVirtualSelectedParentChainChangesToChainChangedNotifi
|
|||||||
addedChainBlocks[i] = added.String()
|
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
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ type NotificationListener struct {
|
|||||||
propagateNewBlockTemplateNotifications bool
|
propagateNewBlockTemplateNotifications bool
|
||||||
|
|
||||||
propagateUTXOsChangedNotificationAddresses map[utxoindex.ScriptPublicKeyString]*UTXOsChangedNotificationAddress
|
propagateUTXOsChangedNotificationAddresses map[utxoindex.ScriptPublicKeyString]*UTXOsChangedNotificationAddress
|
||||||
|
includeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNotificationManager creates a new NotificationManager
|
// 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
|
// 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()
|
nm.RLock()
|
||||||
defer nm.RUnlock()
|
defer nm.RUnlock()
|
||||||
|
|
||||||
|
notificationWithoutAcceptedTransactionIDs := &appmessage.VirtualSelectedParentChainChangedNotificationMessage{
|
||||||
|
RemovedChainBlockHashes: notification.RemovedChainBlockHashes,
|
||||||
|
AddedChainBlockHashes: notification.AddedChainBlockHashes,
|
||||||
|
}
|
||||||
|
|
||||||
for router, listener := range nm.listeners {
|
for router, listener := range nm.listeners {
|
||||||
if listener.propagateVirtualSelectedParentChainChangedNotifications {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -107,6 +122,18 @@ func (nm *NotificationManager) NotifyVirtualSelectedParentChainChanged(notificat
|
|||||||
return nil
|
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
|
// NotifyFinalityConflict notifies the notification manager that there's a finality conflict in the DAG
|
||||||
func (nm *NotificationManager) NotifyFinalityConflict(notification *appmessage.FinalityConflictNotificationMessage) error {
|
func (nm *NotificationManager) NotifyFinalityConflict(notification *appmessage.FinalityConflictNotificationMessage) error {
|
||||||
nm.RLock()
|
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
|
// PropagateBlockAddedNotifications instructs the listener to send block added notifications
|
||||||
// to the remote listener
|
// to the remote listener
|
||||||
func (nl *NotificationListener) PropagateBlockAddedNotifications() {
|
func (nl *NotificationListener) PropagateBlockAddedNotifications() {
|
||||||
@ -259,8 +292,9 @@ func (nl *NotificationListener) PropagateBlockAddedNotifications() {
|
|||||||
|
|
||||||
// PropagateVirtualSelectedParentChainChangedNotifications instructs the listener to send chain changed notifications
|
// PropagateVirtualSelectedParentChainChangedNotifications instructs the listener to send chain changed notifications
|
||||||
// to the remote listener
|
// to the remote listener
|
||||||
func (nl *NotificationListener) PropagateVirtualSelectedParentChainChangedNotifications() {
|
func (nl *NotificationListener) PropagateVirtualSelectedParentChainChangedNotifications(includeAcceptedTransactionIDs bool) {
|
||||||
nl.propagateVirtualSelectedParentChainChangedNotifications = true
|
nl.propagateVirtualSelectedParentChainChangedNotifications = true
|
||||||
|
nl.includeAcceptedTransactionIDsInVirtualSelectedParentChainChangedNotifications = includeAcceptedTransactionIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
// PropagateFinalityConflictNotifications instructs the listener to send finality conflict notifications
|
// PropagateFinalityConflictNotifications instructs the listener to send finality conflict notifications
|
||||||
|
@ -26,12 +26,14 @@ func HandleGetVirtualSelectedParentChainFromBlock(context *rpccontext.Context, _
|
|||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
chainChangedNotification, err := context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(virtualSelectedParentChain)
|
chainChangedNotification, err := context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
|
||||||
|
virtualSelectedParentChain, getVirtualSelectedParentChainFromBlockRequest.IncludeAcceptedTransactionIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
response := appmessage.NewGetVirtualSelectedParentChainFromBlockResponseMessage(
|
response := appmessage.NewGetVirtualSelectedParentChainFromBlockResponseMessage(
|
||||||
chainChangedNotification.RemovedChainBlockHashes, chainChangedNotification.AddedChainBlockHashes)
|
chainChangedNotification.RemovedChainBlockHashes, chainChangedNotification.AddedChainBlockHashes,
|
||||||
|
chainChangedNotification.AcceptedTransactionIDs)
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// HandleNotifyVirtualSelectedParentChainChanged handles the respectively named RPC command
|
// 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)
|
listener, err := context.NotificationManager.Listener(router)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
listener.PropagateVirtualSelectedParentChainChangedNotifications()
|
listener.PropagateVirtualSelectedParentChainChangedNotifications(
|
||||||
|
notifyVirtualSelectedParentChainChangedRequest.IncludeAcceptedTransactionIDs)
|
||||||
|
|
||||||
response := appmessage.NewNotifyVirtualSelectedParentChainChangedResponseMessage()
|
response := appmessage.NewNotifyVirtualSelectedParentChainChangedResponseMessage()
|
||||||
return response, nil
|
return response, nil
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.26.0
|
||||||
// protoc v3.17.2
|
// protoc v3.12.3
|
||||||
// source: messages.proto
|
// source: messages.proto
|
||||||
|
|
||||||
package protowire
|
package protowire
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// 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
|
package protowire
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.26.0
|
||||||
// protoc v3.17.2
|
// protoc v3.12.3
|
||||||
// source: p2p.proto
|
// source: p2p.proto
|
||||||
|
|
||||||
package protowire
|
package protowire
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -301,6 +301,7 @@ message SubmitTransactionResponseMessage{
|
|||||||
//
|
//
|
||||||
// See: VirtualSelectedParentChainChangedNotificationMessage
|
// See: VirtualSelectedParentChainChangedNotificationMessage
|
||||||
message NotifyVirtualSelectedParentChainChangedRequestMessage{
|
message NotifyVirtualSelectedParentChainChangedRequestMessage{
|
||||||
|
bool includeAcceptedTransactionIds = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NotifyVirtualSelectedParentChainChangedResponseMessage{
|
message NotifyVirtualSelectedParentChainChangedResponseMessage{
|
||||||
@ -317,6 +318,9 @@ message VirtualSelectedParentChainChangedNotificationMessage{
|
|||||||
|
|
||||||
// The chain blocks that were added, in low-to-high order
|
// The chain blocks that were added, in low-to-high order
|
||||||
repeated string addedChainBlockHashes = 3;
|
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
|
// GetBlockRequestMessage requests information about a specific block
|
||||||
@ -349,6 +353,12 @@ message GetSubnetworkResponseMessage{
|
|||||||
// parent chain from some startHash to this kaspad's current virtual
|
// parent chain from some startHash to this kaspad's current virtual
|
||||||
message GetVirtualSelectedParentChainFromBlockRequestMessage{
|
message GetVirtualSelectedParentChainFromBlockRequestMessage{
|
||||||
string startHash = 1;
|
string startHash = 1;
|
||||||
|
bool includeAcceptedTransactionIds = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AcceptedTransactionIds{
|
||||||
|
string acceptingBlockHash = 1;
|
||||||
|
repeated string acceptedTransactionIds = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetVirtualSelectedParentChainFromBlockResponseMessage{
|
message GetVirtualSelectedParentChainFromBlockResponseMessage{
|
||||||
@ -358,6 +368,10 @@ message GetVirtualSelectedParentChainFromBlockResponseMessage{
|
|||||||
// The chain blocks that were added, in low-to-high order
|
// The chain blocks that were added, in low-to-high order
|
||||||
repeated string addedChainBlockHashes = 3;
|
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;
|
RPCError error = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +43,13 @@ func (x *KaspadMessage_GetVirtualSelectedParentChainFromBlockResponse) fromAppMe
|
|||||||
x.GetVirtualSelectedParentChainFromBlockResponse = &GetVirtualSelectedParentChainFromBlockResponseMessage{
|
x.GetVirtualSelectedParentChainFromBlockResponse = &GetVirtualSelectedParentChainFromBlockResponseMessage{
|
||||||
RemovedChainBlockHashes: message.RemovedChainBlockHashes,
|
RemovedChainBlockHashes: message.RemovedChainBlockHashes,
|
||||||
AddedChainBlockHashes: message.AddedChainBlockHashes,
|
AddedChainBlockHashes: message.AddedChainBlockHashes,
|
||||||
|
AcceptedTransactionIds: make([]*AcceptedTransactionIds, len(message.AcceptedTransactionIDs)),
|
||||||
Error: err,
|
Error: err,
|
||||||
}
|
}
|
||||||
|
for i, acceptedTransactionIDs := range message.AcceptedTransactionIDs {
|
||||||
|
x.GetVirtualSelectedParentChainFromBlockResponse.AcceptedTransactionIds[i] = &AcceptedTransactionIds{}
|
||||||
|
x.GetVirtualSelectedParentChainFromBlockResponse.AcceptedTransactionIds[i].fromAppMessage(acceptedTransactionIDs)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,9 +67,28 @@ func (x *GetVirtualSelectedParentChainFromBlockResponseMessage) toAppMessage() (
|
|||||||
return nil, errors.New("GetVirtualSelectedParentChainFromBlockResponseMessage contains both an error and a response")
|
return nil, errors.New("GetVirtualSelectedParentChainFromBlockResponseMessage contains both an error and a response")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage{
|
message := &appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage{
|
||||||
RemovedChainBlockHashes: x.RemovedChainBlockHashes,
|
RemovedChainBlockHashes: x.RemovedChainBlockHashes,
|
||||||
AddedChainBlockHashes: x.AddedChainBlockHashes,
|
AddedChainBlockHashes: x.AddedChainBlockHashes,
|
||||||
|
AcceptedTransactionIDs: make([]*appmessage.AcceptedTransactionIDs, len(x.AcceptedTransactionIds)),
|
||||||
Error: rpcErr,
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,15 @@ func (x *KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest) toAppMess
|
|||||||
if x == nil {
|
if x == nil {
|
||||||
return nil, errors.Wrapf(errorNil, "KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest is 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 {
|
func (x *KaspadMessage_NotifyVirtualSelectedParentChainChangedRequest) fromAppMessage(appmessage *appmessage.NotifyVirtualSelectedParentChainChangedRequestMessage) error {
|
||||||
x.NotifyVirtualSelectedParentChainChangedRequest = &NotifyVirtualSelectedParentChainChangedRequestMessage{}
|
x.NotifyVirtualSelectedParentChainChangedRequest = &NotifyVirtualSelectedParentChainChangedRequestMessage{
|
||||||
|
IncludeAcceptedTransactionIds: appmessage.IncludeAcceptedTransactionIDs,
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +64,12 @@ func (x *KaspadMessage_VirtualSelectedParentChainChangedNotification) fromAppMes
|
|||||||
x.VirtualSelectedParentChainChangedNotification = &VirtualSelectedParentChainChangedNotificationMessage{
|
x.VirtualSelectedParentChainChangedNotification = &VirtualSelectedParentChainChangedNotificationMessage{
|
||||||
RemovedChainBlockHashes: message.RemovedChainBlockHashes,
|
RemovedChainBlockHashes: message.RemovedChainBlockHashes,
|
||||||
AddedChainBlockHashes: message.AddedChainBlockHashes,
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@ -68,8 +78,14 @@ func (x *VirtualSelectedParentChainChangedNotificationMessage) toAppMessage() (a
|
|||||||
if x == nil {
|
if x == nil {
|
||||||
return nil, errors.Wrapf(errorNil, "VirtualSelectedParentChainChangedNotificationMessage is nil")
|
return nil, errors.Wrapf(errorNil, "VirtualSelectedParentChainChangedNotificationMessage is nil")
|
||||||
}
|
}
|
||||||
return &appmessage.VirtualSelectedParentChainChangedNotificationMessage{
|
message := &appmessage.VirtualSelectedParentChainChangedNotificationMessage{
|
||||||
RemovedChainBlockHashes: x.RemovedChainBlockHashes,
|
RemovedChainBlockHashes: x.RemovedChainBlockHashes,
|
||||||
AddedChainBlockHashes: x.AddedChainBlockHashes,
|
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
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ package rpcclient
|
|||||||
import "github.com/kaspanet/kaspad/app/appmessage"
|
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
|
// 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) {
|
func (c *RPCClient) GetVirtualSelectedParentChainFromBlock(startHash string, includeAcceptedTransactionIDs bool) (
|
||||||
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash))
|
*appmessage.GetVirtualSelectedParentChainFromBlockResponseMessage, error) {
|
||||||
|
err := c.rpcRouter.outgoingRoute().Enqueue(
|
||||||
|
appmessage.NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash, includeAcceptedTransactionIDs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,11 @@ import (
|
|||||||
|
|
||||||
// RegisterForVirtualSelectedParentChainChangedNotifications sends an RPC request respective to the function's name and returns the RPC server's response.
|
// 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
|
// Additionally, it starts listening for the appropriate notification using the given handler function
|
||||||
func (c *RPCClient) RegisterForVirtualSelectedParentChainChangedNotifications(onChainChanged func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage)) error {
|
func (c *RPCClient) RegisterForVirtualSelectedParentChainChangedNotifications(includeAcceptedTransactionIDs bool,
|
||||||
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewNotifyVirtualSelectedParentChainChangedRequestMessage())
|
onChainChanged func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage)) error {
|
||||||
|
|
||||||
|
err := c.rpcRouter.outgoingRoute().Enqueue(
|
||||||
|
appmessage.NewNotifyVirtualSelectedParentChainChangedRequestMessage(includeAcceptedTransactionIDs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
)
|
)
|
||||||
@ -15,7 +16,7 @@ func TestVirtualSelectedParentChain(t *testing.T) {
|
|||||||
|
|
||||||
// Register to virtual selected parent chain changes
|
// Register to virtual selected parent chain changes
|
||||||
onVirtualSelectedParentChainChangedChan := make(chan *appmessage.VirtualSelectedParentChainChangedNotificationMessage)
|
onVirtualSelectedParentChainChangedChan := make(chan *appmessage.VirtualSelectedParentChainChangedNotificationMessage)
|
||||||
err := kaspad1.rpcClient.RegisterForVirtualSelectedParentChainChangedNotifications(
|
err := kaspad1.rpcClient.RegisterForVirtualSelectedParentChainChangedNotifications(true,
|
||||||
func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage) {
|
func(notification *appmessage.VirtualSelectedParentChainChangedNotificationMessage) {
|
||||||
onVirtualSelectedParentChainChangedChan <- notification
|
onVirtualSelectedParentChainChangedChan <- notification
|
||||||
})
|
})
|
||||||
@ -64,36 +65,10 @@ func TestVirtualSelectedParentChain(t *testing.T) {
|
|||||||
chain2TipHashString := chain2TipHash.String()
|
chain2TipHashString := chain2TipHash.String()
|
||||||
|
|
||||||
// For the first `blockAmountToMine - 1` blocks we don't expect
|
// For the first `blockAmountToMine - 1` blocks we don't expect
|
||||||
// the chain to change at all
|
// the chain to change at all, thus there will be no notifications
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Either the next block could cause a reorg or the one
|
// Either the next block or the one after it will cause a reorg
|
||||||
// after it
|
reorgNotification := <-onVirtualSelectedParentChainChangedChan
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that the reorg notification contains exactly
|
// Make sure that the reorg notification contains exactly
|
||||||
// `blockAmountToMine` blocks in its `removed`
|
// `blockAmountToMine` blocks in its `removed`
|
||||||
@ -104,7 +79,8 @@ func TestVirtualSelectedParentChain(t *testing.T) {
|
|||||||
|
|
||||||
// Get the virtual selected parent chain from the tip of
|
// Get the virtual selected parent chain from the tip of
|
||||||
// the first chain
|
// the first chain
|
||||||
virtualSelectedParentChainFromChain1Tip, err := kaspad1.rpcClient.GetVirtualSelectedParentChainFromBlock(chain1TipHashString)
|
virtualSelectedParentChainFromChain1Tip, err := kaspad1.rpcClient.GetVirtualSelectedParentChainFromBlock(
|
||||||
|
chain1TipHashString, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("GetVirtualSelectedParentChainFromBlock failed: %s", err)
|
t.Fatalf("GetVirtualSelectedParentChainFromBlock failed: %s", err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user