From 84c404306ade7dfb4bb8774a762a738b25fc69a4 Mon Sep 17 00:00:00 2001 From: Dylan Murray Date: Mon, 24 Nov 2025 22:58:10 -0500 Subject: [PATCH 1/2] Add invalid subtree handling --- errors/error.pb.go | 2 +- model/model.pb.go | 2 +- services/alert/alert_api/alert_api.pb.go | 2 +- services/alert/alert_api/alert_api_grpc.pb.go | 2 +- services/asset/asset_api/asset_api.pb.go | 2 +- .../blockassembly_api/blockassembly_api.pb.go | 2 +- .../blockassembly_api_grpc.pb.go | 2 +- .../blockchain_api/blockchain_api.pb.go | 2 +- .../blockchain_api/blockchain_api_grpc.pb.go | 2 +- .../blockvalidation_api.pb.go | 2 +- .../blockvalidation_api_grpc.pb.go | 2 +- services/blockvalidation/get_blocks.go | 2 +- services/legacy/peer_api/peer_api.pb.go | 2 +- services/legacy/peer_api/peer_api_grpc.pb.go | 2 +- services/p2p/Client.go | 27 ++ services/p2p/Interface.go | 4 + services/p2p/Server.go | 18 +- services/p2p/Server_test.go | 8 +- .../p2p/catchup_metrics_integration_test.go | 6 +- services/p2p/handle_catchup_metrics.go | 43 --- services/p2p/handler.go | 69 ++++ services/p2p/p2p_api/p2p_api.pb.go | 307 ++++++++++++------ services/p2p/p2p_api/p2p_api.proto | 13 + services/p2p/p2p_api/p2p_api_grpc.pb.go | 40 ++- .../propagation_api/propagation_api.pb.go | 2 +- .../propagation_api_grpc.pb.go | 2 +- services/rpc/handlers_additional_test.go | 5 + .../subtreevalidation/SubtreeValidation.go | 8 +- .../subtreevalidation/p2p_client_interface.go | 3 + services/subtreevalidation/subtreeHandler.go | 6 + .../subtreevalidation_api.pb.go | 2 +- .../subtreevalidation_api_grpc.pb.go | 2 +- .../validator_api/validator_api.pb.go | 2 +- .../validator_api/validator_api_grpc.pb.go | 2 +- stores/utxo/status.pb.go | 2 +- util/kafka/kafka_message/kafka_messages.pb.go | 2 +- 36 files changed, 424 insertions(+), 177 deletions(-) create mode 100644 services/p2p/handler.go diff --git a/errors/error.pb.go b/errors/error.pb.go index 763c050cb6..b7455bab83 100644 --- a/errors/error.pb.go +++ b/errors/error.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: errors/error.proto package errors diff --git a/model/model.pb.go b/model/model.pb.go index d7bf435847..a0a06905ef 100644 --- a/model/model.pb.go +++ b/model/model.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: model/model.proto package model diff --git a/services/alert/alert_api/alert_api.pb.go b/services/alert/alert_api/alert_api.pb.go index a4ac1cfd89..4ef6807102 100644 --- a/services/alert/alert_api/alert_api.pb.go +++ b/services/alert/alert_api/alert_api.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/alert/alert_api/alert_api.proto package alert_api diff --git a/services/alert/alert_api/alert_api_grpc.pb.go b/services/alert/alert_api/alert_api_grpc.pb.go index 084002e6d4..8885e882ad 100644 --- a/services/alert/alert_api/alert_api_grpc.pb.go +++ b/services/alert/alert_api/alert_api_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/alert/alert_api/alert_api.proto package alert_api diff --git a/services/asset/asset_api/asset_api.pb.go b/services/asset/asset_api/asset_api.pb.go index 1f17a9d11f..a6d44be7c5 100644 --- a/services/asset/asset_api/asset_api.pb.go +++ b/services/asset/asset_api/asset_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/asset/asset_api/asset_api.proto package asset_api diff --git a/services/blockassembly/blockassembly_api/blockassembly_api.pb.go b/services/blockassembly/blockassembly_api/blockassembly_api.pb.go index e6a0faf778..d9675e2eab 100644 --- a/services/blockassembly/blockassembly_api/blockassembly_api.pb.go +++ b/services/blockassembly/blockassembly_api/blockassembly_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/blockassembly/blockassembly_api/blockassembly_api.proto package blockassembly_api diff --git a/services/blockassembly/blockassembly_api/blockassembly_api_grpc.pb.go b/services/blockassembly/blockassembly_api/blockassembly_api_grpc.pb.go index 66dc7ddce7..e117bd35f5 100644 --- a/services/blockassembly/blockassembly_api/blockassembly_api_grpc.pb.go +++ b/services/blockassembly/blockassembly_api/blockassembly_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/blockassembly/blockassembly_api/blockassembly_api.proto package blockassembly_api diff --git a/services/blockchain/blockchain_api/blockchain_api.pb.go b/services/blockchain/blockchain_api/blockchain_api.pb.go index 32f79510eb..9e35fc1663 100644 --- a/services/blockchain/blockchain_api/blockchain_api.pb.go +++ b/services/blockchain/blockchain_api/blockchain_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/blockchain/blockchain_api/blockchain_api.proto // Package blockchain_api defines the gRPC service interface for blockchain operations. diff --git a/services/blockchain/blockchain_api/blockchain_api_grpc.pb.go b/services/blockchain/blockchain_api/blockchain_api_grpc.pb.go index eb6f593cbb..d8a451aed7 100644 --- a/services/blockchain/blockchain_api/blockchain_api_grpc.pb.go +++ b/services/blockchain/blockchain_api/blockchain_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/blockchain/blockchain_api/blockchain_api.proto // Package blockchain_api defines the gRPC service interface for blockchain operations. diff --git a/services/blockvalidation/blockvalidation_api/blockvalidation_api.pb.go b/services/blockvalidation/blockvalidation_api/blockvalidation_api.pb.go index ba5a6cafaa..4d3a31de81 100644 --- a/services/blockvalidation/blockvalidation_api/blockvalidation_api.pb.go +++ b/services/blockvalidation/blockvalidation_api/blockvalidation_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/blockvalidation/blockvalidation_api/blockvalidation_api.proto package blockvalidation_api diff --git a/services/blockvalidation/blockvalidation_api/blockvalidation_api_grpc.pb.go b/services/blockvalidation/blockvalidation_api/blockvalidation_api_grpc.pb.go index 307c6c6a6a..0b6c9c0e5b 100644 --- a/services/blockvalidation/blockvalidation_api/blockvalidation_api_grpc.pb.go +++ b/services/blockvalidation/blockvalidation_api/blockvalidation_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/blockvalidation/blockvalidation_api/blockvalidation_api.proto package blockvalidation_api diff --git a/services/blockvalidation/get_blocks.go b/services/blockvalidation/get_blocks.go index d76a46426b..d310270df5 100644 --- a/services/blockvalidation/get_blocks.go +++ b/services/blockvalidation/get_blocks.go @@ -425,7 +425,7 @@ func (u *Server) fetchAndStoreSubtree(ctx context.Context, block *model.Block, s // Only report success after the entire block is validated // This prevents inflating reputation for peers providing invalid chains // if u.p2pClient != nil { - // if err := u.p2pClient.ReportValidSubtree(ctx, peerID, subtreeHash.String()); err != nil { + // if err := u.p2pClient.ReportValidSubtreeHandler(ctx, peerID, subtreeHash.String()); err != nil { // u.logger.Warnf("[fetchAndStoreSubtree][%s] failed to report valid subtree: %v", subtreeHash.String(), err) // } // } diff --git a/services/legacy/peer_api/peer_api.pb.go b/services/legacy/peer_api/peer_api.pb.go index b988cdf9b5..4f34bcdcef 100644 --- a/services/legacy/peer_api/peer_api.pb.go +++ b/services/legacy/peer_api/peer_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/legacy/peer_api/peer_api.proto package peer_api diff --git a/services/legacy/peer_api/peer_api_grpc.pb.go b/services/legacy/peer_api/peer_api_grpc.pb.go index 0a75e37c06..d2461c46f0 100644 --- a/services/legacy/peer_api/peer_api_grpc.pb.go +++ b/services/legacy/peer_api/peer_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/legacy/peer_api/peer_api.proto package peer_api diff --git a/services/p2p/Client.go b/services/p2p/Client.go index b5aff27dd1..de550ea2fa 100644 --- a/services/p2p/Client.go +++ b/services/p2p/Client.go @@ -526,6 +526,33 @@ func (c *Client) ReportValidSubtree(ctx context.Context, peerID string, subtreeH return nil } +// ReportInvalidSubtree reports that a subtree was unsuccessfully fetched and validated from a peer. +// Parameters: +// - ctx: Context for the operation +// - peerID: Peer ID that provided the subtree +// - subtreeHash: Hash of the validated subtree +// +// Returns: +// - error: Any error encountered during the operation +func (c *Client) ReportInvalidSubtree(ctx context.Context, peerID string, subtreeHash string, reason string) error { + req := &p2p_api.ReportInvalidSubtreeRequest{ + PeerId: peerID, + SubtreeHash: subtreeHash, + Reason: reason, + } + + resp, err := c.client.ReportInvalidSubtree(ctx, req) + if err != nil { + return err + } + + if resp != nil && !resp.Success { + return errors.NewServiceError("failed to report valid subtree: %s", resp.Message) + } + + return nil +} + // ReportValidBlock reports that a block was successfully received and validated from a peer. // Parameters: // - ctx: Context for the operation diff --git a/services/p2p/Interface.go b/services/p2p/Interface.go index 1234079b2a..ead8430910 100644 --- a/services/p2p/Interface.go +++ b/services/p2p/Interface.go @@ -186,6 +186,10 @@ type ClientI interface { // This increases the peer's reputation score for providing valid data. ReportValidSubtree(ctx context.Context, peerID string, subtreeHash string) error + // ReportInvalidSubtree reports that a subtree was unsuccessfully fetched and validated from a peer. + // This decreases the peer's reputation score for providing valid data. + ReportInvalidSubtree(ctx context.Context, peerID string, subtreeHash string, reason string) error + // ReportValidBlock reports that a block was successfully received and validated from a peer. // This increases the peer's reputation score for providing valid blocks. ReportValidBlock(ctx context.Context, peerID string, blockHash string) error diff --git a/services/p2p/Server.go b/services/p2p/Server.go index 62d5174a50..bc4e28f12c 100644 --- a/services/p2p/Server.go +++ b/services/p2p/Server.go @@ -690,8 +690,8 @@ func (s *Server) invalidSubtreeHandler(ctx context.Context) func(msg *kafka.Kafk s.logger.Infof("[invalidSubtreeHandler] Received invalid subtree notification via Kafka: hash=%s, peerUrl=%s, reason=%s", m.SubtreeHash, m.PeerUrl, m.Reason) - // Use the existing ReportInvalidSubtree method to handle the invalid subtree - err = s.ReportInvalidSubtree(ctx, m.SubtreeHash, m.PeerUrl, m.Reason) + // Use the existing reportInvalidSubtree method to handle the invalid subtree + err = s.reportInvalidSubtree(ctx, m.SubtreeHash, m.PeerUrl, m.Reason) if err != nil { // Don't return error here, as we want to continue processing messages s.logger.Errorf("[invalidSubtreeHandler] Failed to report invalid subtree from Kafka: %v", err) @@ -1807,8 +1807,8 @@ func (s *Server) ReportInvalidBlock(ctx context.Context, blockHash string, reaso return nil } -// ReportInvalidSubtree handles invalid subtree reports with explicit peer URL -func (s *Server) ReportInvalidSubtree(ctx context.Context, subtreeHash string, peerURL string, reason string) error { +// reportInvalidSubtree handles invalid subtree reports with explicit peer URL +func (s *Server) reportInvalidSubtree(ctx context.Context, subtreeHash string, peerURL string, reason string) error { var peerID string // First try to get peer ID from the subtreePeerMap (for subtrees received via P2P) @@ -1817,22 +1817,22 @@ func (s *Server) ReportInvalidSubtree(ctx context.Context, subtreeHash string, p // If not found in map and we have a peer URL, look up the peer ID from the URL peerID = s.getPeerIDFromDataHubURL(peerURL) if peerID == "" { - s.logger.Warnf("[ReportInvalidSubtree] could not find peer ID for URL %s, subtree %s, reason: %s", + s.logger.Warnf("[reportInvalidSubtree] could not find peer ID for URL %s, subtree %s, reason: %s", peerURL, subtreeHash, reason) return nil // Don't return error, just log and continue } - s.logger.Debugf("[ReportInvalidSubtree] found peer %s from URL %s for subtree %s", + s.logger.Debugf("[reportInvalidSubtree] found peer %s from URL %s for subtree %s", peerID, peerURL, subtreeHash) } if peerID == "" { - s.logger.Warnf("[ReportInvalidSubtree] could not determine peer for subtree %s, reason: %s", + s.logger.Warnf("[reportInvalidSubtree] could not determine peer for subtree %s, reason: %s", subtreeHash, reason) return nil } // Add ban score to the peer - s.logger.Infof("[ReportInvalidSubtree] adding ban score to peer %s for invalid subtree %s: %s", + s.logger.Infof("[reportInvalidSubtree] adding ban score to peer %s for invalid subtree %s: %s", peerID, subtreeHash, reason) // Record as malicious interaction for reputation tracking @@ -1847,7 +1847,7 @@ func (s *Server) ReportInvalidSubtree(ctx context.Context, subtreeHash string, p // Call the AddBanScore method _, err = s.AddBanScore(ctx, req) if err != nil { - s.logger.Errorf("[ReportInvalidSubtree] error adding ban score to peer %s: %v", peerID, err) + s.logger.Errorf("[reportInvalidSubtree] error adding ban score to peer %s: %v", peerID, err) return errors.NewServiceError("error adding ban score to peer %s", peerID, err) } diff --git a/services/p2p/Server_test.go b/services/p2p/Server_test.go index 105e5f4fcf..fd8d623a92 100644 --- a/services/p2p/Server_test.go +++ b/services/p2p/Server_test.go @@ -3391,16 +3391,16 @@ func TestReportInvalidSubtreeCoverage(t *testing.T) { server := createTestServer(t) // Test with empty hash and required parameters - err := server.ReportInvalidSubtree(ctx, "", "http://test-peer:8080", "test reason") + err := server.reportInvalidSubtree(ctx, "", "http://test-peer:8080", "test reason") if err != nil { - t.Logf("ReportInvalidSubtree with empty hash failed as expected: %v", err) + t.Logf("reportInvalidSubtree with empty hash failed as expected: %v", err) } // Test with valid hash format and all required parameters testHash := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - err = server.ReportInvalidSubtree(ctx, testHash, "http://peer:8080", "invalid subtree") + err = server.reportInvalidSubtree(ctx, testHash, "http://peer:8080", "invalid subtree") if err != nil { - t.Logf("ReportInvalidSubtree may fail in test environment: %v", err) + t.Logf("reportInvalidSubtree may fail in test environment: %v", err) } // The function should execute the main logic path regardless of result diff --git a/services/p2p/catchup_metrics_integration_test.go b/services/p2p/catchup_metrics_integration_test.go index 5ccd33da16..b54b08b07e 100644 --- a/services/p2p/catchup_metrics_integration_test.go +++ b/services/p2p/catchup_metrics_integration_test.go @@ -531,7 +531,7 @@ func TestReportValidSubtree_GRPCEndpoint(t *testing.T) { PeerId: testPeerID.String(), SubtreeHash: "test_subtree_hash_123", } - resp, err := p2pServer.ReportValidSubtree(ctx, req) + resp, err := p2pServer.ReportValidSubtreeHandler(ctx, req) require.NoError(t, err) assert.True(t, resp.Success) assert.Equal(t, "subtree validation recorded", resp.Message) @@ -559,7 +559,7 @@ func TestReportValidSubtree_MissingHash(t *testing.T) { PeerId: "", SubtreeHash: "test_hash", } - resp1, err1 := p2pServer.ReportValidSubtree(ctx, req1) + resp1, err1 := p2pServer.ReportValidSubtreeHandler(ctx, req1) assert.Error(t, err1) assert.False(t, resp1.Success) assert.Contains(t, resp1.Message, "peer ID is required") @@ -569,7 +569,7 @@ func TestReportValidSubtree_MissingHash(t *testing.T) { PeerId: "12D3KooWBPqTBhshqRZMKZtqb5sfgckM9JYkWDR7eW5kSPEKwKCW", SubtreeHash: "", } - resp2, err2 := p2pServer.ReportValidSubtree(ctx, req2) + resp2, err2 := p2pServer.ReportValidSubtreeHandler(ctx, req2) assert.Error(t, err2) assert.False(t, resp2.Success) assert.Contains(t, resp2.Message, "subtree hash is required") diff --git a/services/p2p/handle_catchup_metrics.go b/services/p2p/handle_catchup_metrics.go index 1d65d97592..20cc27c00d 100644 --- a/services/p2p/handle_catchup_metrics.go +++ b/services/p2p/handle_catchup_metrics.go @@ -143,49 +143,6 @@ func (s *Server) GetPeersForCatchup(_ context.Context, _ *p2p_api.GetPeersForCat return &p2p_api.GetPeersForCatchupResponse{Peers: protoPeers}, nil } -// ReportValidSubtree is a gRPC handler for reporting valid subtree reception -func (s *Server) ReportValidSubtree(_ context.Context, req *p2p_api.ReportValidSubtreeRequest) (*p2p_api.ReportValidSubtreeResponse, error) { - if s.peerRegistry == nil { - return &p2p_api.ReportValidSubtreeResponse{ - Success: false, - Message: "peer registry not initialized", - }, errors.WrapGRPC(errors.NewServiceError("peer registry not initialized")) - } - - if req.PeerId == "" { - return &p2p_api.ReportValidSubtreeResponse{ - Success: false, - Message: "peer ID is required", - }, errors.WrapGRPC(errors.NewInvalidArgumentError("peer ID is required")) - } - - if req.SubtreeHash == "" { - return &p2p_api.ReportValidSubtreeResponse{ - Success: false, - Message: "subtree hash is required", - }, errors.WrapGRPC(errors.NewInvalidArgumentError("subtree hash is required")) - } - - // Decode peer ID - peerID, err := peer.Decode(req.PeerId) - if err != nil { - return &p2p_api.ReportValidSubtreeResponse{ - Success: false, - Message: "invalid peer ID", - }, errors.WrapGRPC(errors.NewProcessingError("invalid peer ID: %v", err)) - } - - // Record successful subtree reception directly with peer ID - // Use a nominal duration since we don't have timing info at this level - s.peerRegistry.RecordSubtreeReceived(peerID, 0) - s.logger.Debugf("[ReportValidSubtree] Recorded successful subtree %s from peer %s", req.SubtreeHash, req.PeerId) - - return &p2p_api.ReportValidSubtreeResponse{ - Success: true, - Message: "subtree validation recorded", - }, nil -} - // ReportValidBlock is a gRPC handler for reporting valid block reception func (s *Server) ReportValidBlock(_ context.Context, req *p2p_api.ReportValidBlockRequest) (*p2p_api.ReportValidBlockResponse, error) { if s.peerRegistry == nil { diff --git a/services/p2p/handler.go b/services/p2p/handler.go new file mode 100644 index 0000000000..aa4093f073 --- /dev/null +++ b/services/p2p/handler.go @@ -0,0 +1,69 @@ +package p2p + +import ( + "context" + "fmt" + + "github.com/bsv-blockchain/teranode/errors" + "github.com/bsv-blockchain/teranode/services/p2p/p2p_api" + "github.com/libp2p/go-libp2p/core/peer" +) + +// ReportValidSubtreeHandler is a gRPC handler for reporting valid subtree reception +func (s *Server) ReportValidSubtreeHandler(_ context.Context, req *p2p_api.ReportValidSubtreeRequest) (*p2p_api.ReportValidSubtreeResponse, error) { + if s.peerRegistry == nil { + return &p2p_api.ReportValidSubtreeResponse{ + Success: false, + Message: "peer registry not initialized", + }, errors.WrapGRPC(errors.NewServiceError("peer registry not initialized")) + } + + if req.PeerId == "" { + return &p2p_api.ReportValidSubtreeResponse{ + Success: false, + Message: "peer ID is required", + }, errors.WrapGRPC(errors.NewInvalidArgumentError("peer ID is required")) + } + + if req.SubtreeHash == "" { + return &p2p_api.ReportValidSubtreeResponse{ + Success: false, + Message: "subtree hash is required", + }, errors.WrapGRPC(errors.NewInvalidArgumentError("subtree hash is required")) + } + + // Decode peer ID + peerID, err := peer.Decode(req.PeerId) + if err != nil { + return &p2p_api.ReportValidSubtreeResponse{ + Success: false, + Message: "invalid peer ID", + }, errors.WrapGRPC(errors.NewProcessingError("invalid peer ID: %v", err)) + } + + // Record successful subtree reception directly with peer ID + // Use a nominal duration since we don't have timing info at this level + s.peerRegistry.RecordSubtreeReceived(peerID, 0) + s.logger.Debugf("[ReportValidSubtreeHandler] Recorded successful subtree %s from peer %s", req.SubtreeHash, req.PeerId) + + return &p2p_api.ReportValidSubtreeResponse{ + Success: true, + Message: "subtree validation recorded", + }, nil +} + +// ReportInvalidSubtreeHandler is a gRPC handler for reporting invalid subtree reception +func (s *Server) ReportInvalidSubtreeHandler(ctx context.Context, req *p2p_api.ReportInvalidSubtreeRequest) (*p2p_api.ReportValidSubtreeResponse, error) { + err := s.reportInvalidSubtree(ctx, req.SubtreeHash, req.PeerId, req.Reason) + if err != nil { + return &p2p_api.ReportValidSubtreeResponse{ + Success: false, + Message: fmt.Sprintf("failed to report invalid subtree: %v", err), + }, errors.WrapGRPC(err) + } + + return &p2p_api.ReportValidSubtreeResponse{ + Success: true, + Message: "invalid subtree reported", + }, nil +} diff --git a/services/p2p/p2p_api/p2p_api.pb.go b/services/p2p/p2p_api/p2p_api.pb.go index ef141b16ab..1dd5f850d8 100644 --- a/services/p2p/p2p_api/p2p_api.pb.go +++ b/services/p2p/p2p_api/p2p_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/p2p/p2p_api/p2p_api.proto package p2p_api @@ -1900,6 +1900,119 @@ func (x *ReportValidSubtreeResponse) GetMessage() string { return "" } +// Report invalid subtree reception +type ReportInvalidSubtreeRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + PeerId string `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` // Peer ID that provided the subtree + SubtreeHash string `protobuf:"bytes,2,opt,name=subtree_hash,json=subtreeHash,proto3" json:"subtree_hash,omitempty"` + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` // Reason why the subtree is considered invalid + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReportInvalidSubtreeRequest) Reset() { + *x = ReportInvalidSubtreeRequest{} + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReportInvalidSubtreeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportInvalidSubtreeRequest) ProtoMessage() {} + +func (x *ReportInvalidSubtreeRequest) ProtoReflect() protoreflect.Message { + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[35] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReportInvalidSubtreeRequest.ProtoReflect.Descriptor instead. +func (*ReportInvalidSubtreeRequest) Descriptor() ([]byte, []int) { + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{35} +} + +func (x *ReportInvalidSubtreeRequest) GetPeerId() string { + if x != nil { + return x.PeerId + } + return "" +} + +func (x *ReportInvalidSubtreeRequest) GetSubtreeHash() string { + if x != nil { + return x.SubtreeHash + } + return "" +} + +func (x *ReportInvalidSubtreeRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type ReportInvalidSubtreeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReportInvalidSubtreeResponse) Reset() { + *x = ReportInvalidSubtreeResponse{} + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReportInvalidSubtreeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportInvalidSubtreeResponse) ProtoMessage() {} + +func (x *ReportInvalidSubtreeResponse) ProtoReflect() protoreflect.Message { + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[36] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReportInvalidSubtreeResponse.ProtoReflect.Descriptor instead. +func (*ReportInvalidSubtreeResponse) Descriptor() ([]byte, []int) { + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{36} +} + +func (x *ReportInvalidSubtreeResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *ReportInvalidSubtreeResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + // Report valid block reception type ReportValidBlockRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1911,7 +2024,7 @@ type ReportValidBlockRequest struct { func (x *ReportValidBlockRequest) Reset() { *x = ReportValidBlockRequest{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[35] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1923,7 +2036,7 @@ func (x *ReportValidBlockRequest) String() string { func (*ReportValidBlockRequest) ProtoMessage() {} func (x *ReportValidBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[35] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1936,7 +2049,7 @@ func (x *ReportValidBlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportValidBlockRequest.ProtoReflect.Descriptor instead. func (*ReportValidBlockRequest) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{35} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{37} } func (x *ReportValidBlockRequest) GetPeerId() string { @@ -1963,7 +2076,7 @@ type ReportValidBlockResponse struct { func (x *ReportValidBlockResponse) Reset() { *x = ReportValidBlockResponse{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[36] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1975,7 +2088,7 @@ func (x *ReportValidBlockResponse) String() string { func (*ReportValidBlockResponse) ProtoMessage() {} func (x *ReportValidBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[36] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1988,7 +2101,7 @@ func (x *ReportValidBlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportValidBlockResponse.ProtoReflect.Descriptor instead. func (*ReportValidBlockResponse) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{36} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{38} } func (x *ReportValidBlockResponse) GetSuccess() bool { @@ -2015,7 +2128,7 @@ type IsPeerMaliciousRequest struct { func (x *IsPeerMaliciousRequest) Reset() { *x = IsPeerMaliciousRequest{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[37] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2027,7 +2140,7 @@ func (x *IsPeerMaliciousRequest) String() string { func (*IsPeerMaliciousRequest) ProtoMessage() {} func (x *IsPeerMaliciousRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[37] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2040,7 +2153,7 @@ func (x *IsPeerMaliciousRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use IsPeerMaliciousRequest.ProtoReflect.Descriptor instead. func (*IsPeerMaliciousRequest) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{37} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{39} } func (x *IsPeerMaliciousRequest) GetPeerId() string { @@ -2060,7 +2173,7 @@ type IsPeerMaliciousResponse struct { func (x *IsPeerMaliciousResponse) Reset() { *x = IsPeerMaliciousResponse{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[38] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2072,7 +2185,7 @@ func (x *IsPeerMaliciousResponse) String() string { func (*IsPeerMaliciousResponse) ProtoMessage() {} func (x *IsPeerMaliciousResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[38] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2085,7 +2198,7 @@ func (x *IsPeerMaliciousResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use IsPeerMaliciousResponse.ProtoReflect.Descriptor instead. func (*IsPeerMaliciousResponse) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{38} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{40} } func (x *IsPeerMaliciousResponse) GetIsMalicious() bool { @@ -2111,7 +2224,7 @@ type IsPeerUnhealthyRequest struct { func (x *IsPeerUnhealthyRequest) Reset() { *x = IsPeerUnhealthyRequest{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[39] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2123,7 +2236,7 @@ func (x *IsPeerUnhealthyRequest) String() string { func (*IsPeerUnhealthyRequest) ProtoMessage() {} func (x *IsPeerUnhealthyRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[39] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2136,7 +2249,7 @@ func (x *IsPeerUnhealthyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use IsPeerUnhealthyRequest.ProtoReflect.Descriptor instead. func (*IsPeerUnhealthyRequest) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{39} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{41} } func (x *IsPeerUnhealthyRequest) GetPeerId() string { @@ -2157,7 +2270,7 @@ type IsPeerUnhealthyResponse struct { func (x *IsPeerUnhealthyResponse) Reset() { *x = IsPeerUnhealthyResponse{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[40] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2169,7 +2282,7 @@ func (x *IsPeerUnhealthyResponse) String() string { func (*IsPeerUnhealthyResponse) ProtoMessage() {} func (x *IsPeerUnhealthyResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[40] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2182,7 +2295,7 @@ func (x *IsPeerUnhealthyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use IsPeerUnhealthyResponse.ProtoReflect.Descriptor instead. func (*IsPeerUnhealthyResponse) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{40} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{42} } func (x *IsPeerUnhealthyResponse) GetIsUnhealthy() bool { @@ -2240,7 +2353,7 @@ type PeerRegistryInfo struct { func (x *PeerRegistryInfo) Reset() { *x = PeerRegistryInfo{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[41] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2252,7 +2365,7 @@ func (x *PeerRegistryInfo) String() string { func (*PeerRegistryInfo) ProtoMessage() {} func (x *PeerRegistryInfo) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[41] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2265,7 +2378,7 @@ func (x *PeerRegistryInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerRegistryInfo.ProtoReflect.Descriptor instead. func (*PeerRegistryInfo) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{41} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{43} } func (x *PeerRegistryInfo) GetId() string { @@ -2445,7 +2558,7 @@ type GetPeerRegistryResponse struct { func (x *GetPeerRegistryResponse) Reset() { *x = GetPeerRegistryResponse{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[42] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2457,7 +2570,7 @@ func (x *GetPeerRegistryResponse) String() string { func (*GetPeerRegistryResponse) ProtoMessage() {} func (x *GetPeerRegistryResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[42] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2470,7 +2583,7 @@ func (x *GetPeerRegistryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPeerRegistryResponse.ProtoReflect.Descriptor instead. func (*GetPeerRegistryResponse) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{42} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{44} } func (x *GetPeerRegistryResponse) GetPeers() []*PeerRegistryInfo { @@ -2491,7 +2604,7 @@ type RecordBytesDownloadedRequest struct { func (x *RecordBytesDownloadedRequest) Reset() { *x = RecordBytesDownloadedRequest{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[43] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2503,7 +2616,7 @@ func (x *RecordBytesDownloadedRequest) String() string { func (*RecordBytesDownloadedRequest) ProtoMessage() {} func (x *RecordBytesDownloadedRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[43] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2516,7 +2629,7 @@ func (x *RecordBytesDownloadedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RecordBytesDownloadedRequest.ProtoReflect.Descriptor instead. func (*RecordBytesDownloadedRequest) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{43} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{45} } func (x *RecordBytesDownloadedRequest) GetPeerId() string { @@ -2542,7 +2655,7 @@ type RecordBytesDownloadedResponse struct { func (x *RecordBytesDownloadedResponse) Reset() { *x = RecordBytesDownloadedResponse{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[44] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2554,7 +2667,7 @@ func (x *RecordBytesDownloadedResponse) String() string { func (*RecordBytesDownloadedResponse) ProtoMessage() {} func (x *RecordBytesDownloadedResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[44] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2567,7 +2680,7 @@ func (x *RecordBytesDownloadedResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RecordBytesDownloadedResponse.ProtoReflect.Descriptor instead. func (*RecordBytesDownloadedResponse) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{44} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{46} } func (x *RecordBytesDownloadedResponse) GetOk() bool { @@ -2586,7 +2699,7 @@ type GetPeerRequest struct { func (x *GetPeerRequest) Reset() { *x = GetPeerRequest{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[45] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2598,7 +2711,7 @@ func (x *GetPeerRequest) String() string { func (*GetPeerRequest) ProtoMessage() {} func (x *GetPeerRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[45] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2611,7 +2724,7 @@ func (x *GetPeerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPeerRequest.ProtoReflect.Descriptor instead. func (*GetPeerRequest) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{45} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{47} } func (x *GetPeerRequest) GetPeerId() string { @@ -2631,7 +2744,7 @@ type GetPeerResponse struct { func (x *GetPeerResponse) Reset() { *x = GetPeerResponse{} - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[46] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2643,7 +2756,7 @@ func (x *GetPeerResponse) String() string { func (*GetPeerResponse) ProtoMessage() {} func (x *GetPeerResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[46] + mi := &file_services_p2p_p2p_api_p2p_api_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2656,7 +2769,7 @@ func (x *GetPeerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPeerResponse.ProtoReflect.Descriptor instead. func (*GetPeerResponse) Descriptor() ([]byte, []int) { - return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{46} + return file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP(), []int{48} } func (x *GetPeerResponse) GetPeer() *PeerRegistryInfo { @@ -2800,6 +2913,13 @@ const file_services_p2p_p2p_api_p2p_api_proto_rawDesc = "" + "\fsubtree_hash\x18\x02 \x01(\tR\vsubtreeHash\"P\n" + "\x1aReportValidSubtreeResponse\x12\x18\n" + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage\"q\n" + + "\x1bReportInvalidSubtreeRequest\x12\x17\n" + + "\apeer_id\x18\x01 \x01(\tR\x06peerId\x12!\n" + + "\fsubtree_hash\x18\x02 \x01(\tR\vsubtreeHash\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\"R\n" + + "\x1cReportInvalidSubtreeResponse\x12\x18\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess\x12\x18\n" + "\amessage\x18\x02 \x01(\tR\amessage\"Q\n" + "\x17ReportValidBlockRequest\x12\x17\n" + "\apeer_id\x18\x01 \x01(\tR\x06peerId\x12\x1d\n" + @@ -2859,7 +2979,7 @@ const file_services_p2p_p2p_api_p2p_api_proto_rawDesc = "" + "\apeer_id\x18\x01 \x01(\tR\x06peerId\"V\n" + "\x0fGetPeerResponse\x12-\n" + "\x04peer\x18\x01 \x01(\v2\x19.p2p_api.PeerRegistryInfoR\x04peer\x12\x14\n" + - "\x05found\x18\x02 \x01(\bR\x05found2\xa1\x10\n" + + "\x05found\x18\x02 \x01(\bR\x05found2\x88\x11\n" + "\vPeerService\x12?\n" + "\bGetPeers\x12\x16.google.protobuf.Empty\x1a\x19.p2p_api.GetPeersResponse\"\x00\x12>\n" + "\aBanPeer\x12\x17.p2p_api.BanPeerRequest\x1a\x18.p2p_api.BanPeerResponse\"\x00\x12D\n" + @@ -2879,7 +2999,8 @@ const file_services_p2p_p2p_api_p2p_api_proto_rawDesc = "" + "\x12UpdateCatchupError\x12\".p2p_api.UpdateCatchupErrorRequest\x1a#.p2p_api.UpdateCatchupErrorResponse\"\x00\x12V\n" + "\x0fResetReputation\x12\x1f.p2p_api.ResetReputationRequest\x1a .p2p_api.ResetReputationResponse\"\x00\x12_\n" + "\x12GetPeersForCatchup\x12\".p2p_api.GetPeersForCatchupRequest\x1a#.p2p_api.GetPeersForCatchupResponse\"\x00\x12_\n" + - "\x12ReportValidSubtree\x12\".p2p_api.ReportValidSubtreeRequest\x1a#.p2p_api.ReportValidSubtreeResponse\"\x00\x12Y\n" + + "\x12ReportValidSubtree\x12\".p2p_api.ReportValidSubtreeRequest\x1a#.p2p_api.ReportValidSubtreeResponse\"\x00\x12e\n" + + "\x14ReportInvalidSubtree\x12$.p2p_api.ReportInvalidSubtreeRequest\x1a%.p2p_api.ReportInvalidSubtreeResponse\"\x00\x12Y\n" + "\x10ReportValidBlock\x12 .p2p_api.ReportValidBlockRequest\x1a!.p2p_api.ReportValidBlockResponse\"\x00\x12V\n" + "\x0fIsPeerMalicious\x12\x1f.p2p_api.IsPeerMaliciousRequest\x1a .p2p_api.IsPeerMaliciousResponse\"\x00\x12V\n" + "\x0fIsPeerUnhealthy\x12\x1f.p2p_api.IsPeerUnhealthyRequest\x1a .p2p_api.IsPeerUnhealthyResponse\"\x00\x12M\n" + @@ -2900,7 +3021,7 @@ func file_services_p2p_p2p_api_p2p_api_proto_rawDescGZIP() []byte { return file_services_p2p_p2p_api_p2p_api_proto_rawDescData } -var file_services_p2p_p2p_api_p2p_api_proto_msgTypes = make([]protoimpl.MessageInfo, 47) +var file_services_p2p_p2p_api_p2p_api_proto_msgTypes = make([]protoimpl.MessageInfo, 49) var file_services_p2p_p2p_api_p2p_api_proto_goTypes = []any{ (*Peer)(nil), // 0: p2p_api.Peer (*GetPeersResponse)(nil), // 1: p2p_api.GetPeersResponse @@ -2937,31 +3058,33 @@ var file_services_p2p_p2p_api_p2p_api_proto_goTypes = []any{ (*GetPeersForCatchupResponse)(nil), // 32: p2p_api.GetPeersForCatchupResponse (*ReportValidSubtreeRequest)(nil), // 33: p2p_api.ReportValidSubtreeRequest (*ReportValidSubtreeResponse)(nil), // 34: p2p_api.ReportValidSubtreeResponse - (*ReportValidBlockRequest)(nil), // 35: p2p_api.ReportValidBlockRequest - (*ReportValidBlockResponse)(nil), // 36: p2p_api.ReportValidBlockResponse - (*IsPeerMaliciousRequest)(nil), // 37: p2p_api.IsPeerMaliciousRequest - (*IsPeerMaliciousResponse)(nil), // 38: p2p_api.IsPeerMaliciousResponse - (*IsPeerUnhealthyRequest)(nil), // 39: p2p_api.IsPeerUnhealthyRequest - (*IsPeerUnhealthyResponse)(nil), // 40: p2p_api.IsPeerUnhealthyResponse - (*PeerRegistryInfo)(nil), // 41: p2p_api.PeerRegistryInfo - (*GetPeerRegistryResponse)(nil), // 42: p2p_api.GetPeerRegistryResponse - (*RecordBytesDownloadedRequest)(nil), // 43: p2p_api.RecordBytesDownloadedRequest - (*RecordBytesDownloadedResponse)(nil), // 44: p2p_api.RecordBytesDownloadedResponse - (*GetPeerRequest)(nil), // 45: p2p_api.GetPeerRequest - (*GetPeerResponse)(nil), // 46: p2p_api.GetPeerResponse - (*emptypb.Empty)(nil), // 47: google.protobuf.Empty + (*ReportInvalidSubtreeRequest)(nil), // 35: p2p_api.ReportInvalidSubtreeRequest + (*ReportInvalidSubtreeResponse)(nil), // 36: p2p_api.ReportInvalidSubtreeResponse + (*ReportValidBlockRequest)(nil), // 37: p2p_api.ReportValidBlockRequest + (*ReportValidBlockResponse)(nil), // 38: p2p_api.ReportValidBlockResponse + (*IsPeerMaliciousRequest)(nil), // 39: p2p_api.IsPeerMaliciousRequest + (*IsPeerMaliciousResponse)(nil), // 40: p2p_api.IsPeerMaliciousResponse + (*IsPeerUnhealthyRequest)(nil), // 41: p2p_api.IsPeerUnhealthyRequest + (*IsPeerUnhealthyResponse)(nil), // 42: p2p_api.IsPeerUnhealthyResponse + (*PeerRegistryInfo)(nil), // 43: p2p_api.PeerRegistryInfo + (*GetPeerRegistryResponse)(nil), // 44: p2p_api.GetPeerRegistryResponse + (*RecordBytesDownloadedRequest)(nil), // 45: p2p_api.RecordBytesDownloadedRequest + (*RecordBytesDownloadedResponse)(nil), // 46: p2p_api.RecordBytesDownloadedResponse + (*GetPeerRequest)(nil), // 47: p2p_api.GetPeerRequest + (*GetPeerResponse)(nil), // 48: p2p_api.GetPeerResponse + (*emptypb.Empty)(nil), // 49: google.protobuf.Empty } var file_services_p2p_p2p_api_p2p_api_proto_depIdxs = []int32{ 0, // 0: p2p_api.GetPeersResponse.peers:type_name -> p2p_api.Peer 31, // 1: p2p_api.GetPeersForCatchupResponse.peers:type_name -> p2p_api.PeerInfoForCatchup - 41, // 2: p2p_api.GetPeerRegistryResponse.peers:type_name -> p2p_api.PeerRegistryInfo - 41, // 3: p2p_api.GetPeerResponse.peer:type_name -> p2p_api.PeerRegistryInfo - 47, // 4: p2p_api.PeerService.GetPeers:input_type -> google.protobuf.Empty + 43, // 2: p2p_api.GetPeerRegistryResponse.peers:type_name -> p2p_api.PeerRegistryInfo + 43, // 3: p2p_api.GetPeerResponse.peer:type_name -> p2p_api.PeerRegistryInfo + 49, // 4: p2p_api.PeerService.GetPeers:input_type -> google.protobuf.Empty 2, // 5: p2p_api.PeerService.BanPeer:input_type -> p2p_api.BanPeerRequest 4, // 6: p2p_api.PeerService.UnbanPeer:input_type -> p2p_api.UnbanPeerRequest 6, // 7: p2p_api.PeerService.IsBanned:input_type -> p2p_api.IsBannedRequest - 47, // 8: p2p_api.PeerService.ListBanned:input_type -> google.protobuf.Empty - 47, // 9: p2p_api.PeerService.ClearBanned:input_type -> google.protobuf.Empty + 49, // 8: p2p_api.PeerService.ListBanned:input_type -> google.protobuf.Empty + 49, // 9: p2p_api.PeerService.ClearBanned:input_type -> google.protobuf.Empty 10, // 10: p2p_api.PeerService.AddBanScore:input_type -> p2p_api.AddBanScoreRequest 12, // 11: p2p_api.PeerService.ConnectPeer:input_type -> p2p_api.ConnectPeerRequest 14, // 12: p2p_api.PeerService.DisconnectPeer:input_type -> p2p_api.DisconnectPeerRequest @@ -2974,38 +3097,40 @@ var file_services_p2p_p2p_api_p2p_api_proto_depIdxs = []int32{ 28, // 19: p2p_api.PeerService.ResetReputation:input_type -> p2p_api.ResetReputationRequest 30, // 20: p2p_api.PeerService.GetPeersForCatchup:input_type -> p2p_api.GetPeersForCatchupRequest 33, // 21: p2p_api.PeerService.ReportValidSubtree:input_type -> p2p_api.ReportValidSubtreeRequest - 35, // 22: p2p_api.PeerService.ReportValidBlock:input_type -> p2p_api.ReportValidBlockRequest - 37, // 23: p2p_api.PeerService.IsPeerMalicious:input_type -> p2p_api.IsPeerMaliciousRequest - 39, // 24: p2p_api.PeerService.IsPeerUnhealthy:input_type -> p2p_api.IsPeerUnhealthyRequest - 47, // 25: p2p_api.PeerService.GetPeerRegistry:input_type -> google.protobuf.Empty - 43, // 26: p2p_api.PeerService.RecordBytesDownloaded:input_type -> p2p_api.RecordBytesDownloadedRequest - 45, // 27: p2p_api.PeerService.GetPeer:input_type -> p2p_api.GetPeerRequest - 1, // 28: p2p_api.PeerService.GetPeers:output_type -> p2p_api.GetPeersResponse - 3, // 29: p2p_api.PeerService.BanPeer:output_type -> p2p_api.BanPeerResponse - 5, // 30: p2p_api.PeerService.UnbanPeer:output_type -> p2p_api.UnbanPeerResponse - 7, // 31: p2p_api.PeerService.IsBanned:output_type -> p2p_api.IsBannedResponse - 8, // 32: p2p_api.PeerService.ListBanned:output_type -> p2p_api.ListBannedResponse - 9, // 33: p2p_api.PeerService.ClearBanned:output_type -> p2p_api.ClearBannedResponse - 11, // 34: p2p_api.PeerService.AddBanScore:output_type -> p2p_api.AddBanScoreResponse - 13, // 35: p2p_api.PeerService.ConnectPeer:output_type -> p2p_api.ConnectPeerResponse - 15, // 36: p2p_api.PeerService.DisconnectPeer:output_type -> p2p_api.DisconnectPeerResponse - 17, // 37: p2p_api.PeerService.RecordCatchupAttempt:output_type -> p2p_api.RecordCatchupAttemptResponse - 19, // 38: p2p_api.PeerService.RecordCatchupSuccess:output_type -> p2p_api.RecordCatchupSuccessResponse - 21, // 39: p2p_api.PeerService.RecordCatchupFailure:output_type -> p2p_api.RecordCatchupFailureResponse - 23, // 40: p2p_api.PeerService.RecordCatchupMalicious:output_type -> p2p_api.RecordCatchupMaliciousResponse - 25, // 41: p2p_api.PeerService.UpdateCatchupReputation:output_type -> p2p_api.UpdateCatchupReputationResponse - 27, // 42: p2p_api.PeerService.UpdateCatchupError:output_type -> p2p_api.UpdateCatchupErrorResponse - 29, // 43: p2p_api.PeerService.ResetReputation:output_type -> p2p_api.ResetReputationResponse - 32, // 44: p2p_api.PeerService.GetPeersForCatchup:output_type -> p2p_api.GetPeersForCatchupResponse - 34, // 45: p2p_api.PeerService.ReportValidSubtree:output_type -> p2p_api.ReportValidSubtreeResponse - 36, // 46: p2p_api.PeerService.ReportValidBlock:output_type -> p2p_api.ReportValidBlockResponse - 38, // 47: p2p_api.PeerService.IsPeerMalicious:output_type -> p2p_api.IsPeerMaliciousResponse - 40, // 48: p2p_api.PeerService.IsPeerUnhealthy:output_type -> p2p_api.IsPeerUnhealthyResponse - 42, // 49: p2p_api.PeerService.GetPeerRegistry:output_type -> p2p_api.GetPeerRegistryResponse - 44, // 50: p2p_api.PeerService.RecordBytesDownloaded:output_type -> p2p_api.RecordBytesDownloadedResponse - 46, // 51: p2p_api.PeerService.GetPeer:output_type -> p2p_api.GetPeerResponse - 28, // [28:52] is the sub-list for method output_type - 4, // [4:28] is the sub-list for method input_type + 35, // 22: p2p_api.PeerService.reportInvalidSubtree:input_type -> p2p_api.ReportInvalidSubtreeRequest + 37, // 23: p2p_api.PeerService.ReportValidBlock:input_type -> p2p_api.ReportValidBlockRequest + 39, // 24: p2p_api.PeerService.IsPeerMalicious:input_type -> p2p_api.IsPeerMaliciousRequest + 41, // 25: p2p_api.PeerService.IsPeerUnhealthy:input_type -> p2p_api.IsPeerUnhealthyRequest + 49, // 26: p2p_api.PeerService.GetPeerRegistry:input_type -> google.protobuf.Empty + 45, // 27: p2p_api.PeerService.RecordBytesDownloaded:input_type -> p2p_api.RecordBytesDownloadedRequest + 47, // 28: p2p_api.PeerService.GetPeer:input_type -> p2p_api.GetPeerRequest + 1, // 29: p2p_api.PeerService.GetPeers:output_type -> p2p_api.GetPeersResponse + 3, // 30: p2p_api.PeerService.BanPeer:output_type -> p2p_api.BanPeerResponse + 5, // 31: p2p_api.PeerService.UnbanPeer:output_type -> p2p_api.UnbanPeerResponse + 7, // 32: p2p_api.PeerService.IsBanned:output_type -> p2p_api.IsBannedResponse + 8, // 33: p2p_api.PeerService.ListBanned:output_type -> p2p_api.ListBannedResponse + 9, // 34: p2p_api.PeerService.ClearBanned:output_type -> p2p_api.ClearBannedResponse + 11, // 35: p2p_api.PeerService.AddBanScore:output_type -> p2p_api.AddBanScoreResponse + 13, // 36: p2p_api.PeerService.ConnectPeer:output_type -> p2p_api.ConnectPeerResponse + 15, // 37: p2p_api.PeerService.DisconnectPeer:output_type -> p2p_api.DisconnectPeerResponse + 17, // 38: p2p_api.PeerService.RecordCatchupAttempt:output_type -> p2p_api.RecordCatchupAttemptResponse + 19, // 39: p2p_api.PeerService.RecordCatchupSuccess:output_type -> p2p_api.RecordCatchupSuccessResponse + 21, // 40: p2p_api.PeerService.RecordCatchupFailure:output_type -> p2p_api.RecordCatchupFailureResponse + 23, // 41: p2p_api.PeerService.RecordCatchupMalicious:output_type -> p2p_api.RecordCatchupMaliciousResponse + 25, // 42: p2p_api.PeerService.UpdateCatchupReputation:output_type -> p2p_api.UpdateCatchupReputationResponse + 27, // 43: p2p_api.PeerService.UpdateCatchupError:output_type -> p2p_api.UpdateCatchupErrorResponse + 29, // 44: p2p_api.PeerService.ResetReputation:output_type -> p2p_api.ResetReputationResponse + 32, // 45: p2p_api.PeerService.GetPeersForCatchup:output_type -> p2p_api.GetPeersForCatchupResponse + 34, // 46: p2p_api.PeerService.ReportValidSubtree:output_type -> p2p_api.ReportValidSubtreeResponse + 36, // 47: p2p_api.PeerService.reportInvalidSubtree:output_type -> p2p_api.ReportInvalidSubtreeResponse + 38, // 48: p2p_api.PeerService.ReportValidBlock:output_type -> p2p_api.ReportValidBlockResponse + 40, // 49: p2p_api.PeerService.IsPeerMalicious:output_type -> p2p_api.IsPeerMaliciousResponse + 42, // 50: p2p_api.PeerService.IsPeerUnhealthy:output_type -> p2p_api.IsPeerUnhealthyResponse + 44, // 51: p2p_api.PeerService.GetPeerRegistry:output_type -> p2p_api.GetPeerRegistryResponse + 46, // 52: p2p_api.PeerService.RecordBytesDownloaded:output_type -> p2p_api.RecordBytesDownloadedResponse + 48, // 53: p2p_api.PeerService.GetPeer:output_type -> p2p_api.GetPeerResponse + 29, // [29:54] is the sub-list for method output_type + 4, // [4:29] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name @@ -3022,7 +3147,7 @@ func file_services_p2p_p2p_api_p2p_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_services_p2p_p2p_api_p2p_api_proto_rawDesc), len(file_services_p2p_p2p_api_p2p_api_proto_rawDesc)), NumEnums: 0, - NumMessages: 47, + NumMessages: 49, NumExtensions: 0, NumServices: 1, }, diff --git a/services/p2p/p2p_api/p2p_api.proto b/services/p2p/p2p_api/p2p_api.proto index d3aaf3a31e..c5b7158e16 100644 --- a/services/p2p/p2p_api/p2p_api.proto +++ b/services/p2p/p2p_api/p2p_api.proto @@ -192,6 +192,18 @@ message AddBanScoreRequest { string message = 2; } +// Report invalid subtree reception +message ReportInvalidSubtreeRequest { + string peer_id = 1; // Peer ID that provided the subtree + string subtree_hash = 2; + string reason = 3; // Reason why the subtree is considered invalid +} + +message ReportInvalidSubtreeResponse { + bool success = 1; + string message = 2; +} + // Report valid block reception message ReportValidBlockRequest { string peer_id = 1; // Peer ID that provided the block @@ -300,6 +312,7 @@ message AddBanScoreRequest { // Subtree and block validation reporting rpc ReportValidSubtree(ReportValidSubtreeRequest) returns (ReportValidSubtreeResponse) {} + rpc ReportInvalidSubtree(ReportInvalidSubtreeRequest) returns (ReportInvalidSubtreeResponse) {} rpc ReportValidBlock(ReportValidBlockRequest) returns (ReportValidBlockResponse) {} // Peer status checking diff --git a/services/p2p/p2p_api/p2p_api_grpc.pb.go b/services/p2p/p2p_api/p2p_api_grpc.pb.go index 8a9541e758..60d6e657c9 100644 --- a/services/p2p/p2p_api/p2p_api_grpc.pb.go +++ b/services/p2p/p2p_api/p2p_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/p2p/p2p_api/p2p_api.proto package p2p_api @@ -38,6 +38,7 @@ const ( PeerService_ResetReputation_FullMethodName = "/p2p_api.PeerService/ResetReputation" PeerService_GetPeersForCatchup_FullMethodName = "/p2p_api.PeerService/GetPeersForCatchup" PeerService_ReportValidSubtree_FullMethodName = "/p2p_api.PeerService/ReportValidSubtree" + PeerService_ReportInvalidSubtree_FullMethodName = "/p2p_api.PeerService/reportInvalidSubtree" PeerService_ReportValidBlock_FullMethodName = "/p2p_api.PeerService/ReportValidBlock" PeerService_IsPeerMalicious_FullMethodName = "/p2p_api.PeerService/IsPeerMalicious" PeerService_IsPeerUnhealthy_FullMethodName = "/p2p_api.PeerService/IsPeerUnhealthy" @@ -72,6 +73,7 @@ type PeerServiceClient interface { GetPeersForCatchup(ctx context.Context, in *GetPeersForCatchupRequest, opts ...grpc.CallOption) (*GetPeersForCatchupResponse, error) // Subtree and block validation reporting ReportValidSubtree(ctx context.Context, in *ReportValidSubtreeRequest, opts ...grpc.CallOption) (*ReportValidSubtreeResponse, error) + ReportInvalidSubtree(ctx context.Context, in *ReportInvalidSubtreeRequest, opts ...grpc.CallOption) (*ReportInvalidSubtreeResponse, error) ReportValidBlock(ctx context.Context, in *ReportValidBlockRequest, opts ...grpc.CallOption) (*ReportValidBlockResponse, error) // Peer status checking IsPeerMalicious(ctx context.Context, in *IsPeerMaliciousRequest, opts ...grpc.CallOption) (*IsPeerMaliciousResponse, error) @@ -272,6 +274,16 @@ func (c *peerServiceClient) ReportValidSubtree(ctx context.Context, in *ReportVa return out, nil } +func (c *peerServiceClient) ReportInvalidSubtree(ctx context.Context, in *ReportInvalidSubtreeRequest, opts ...grpc.CallOption) (*ReportInvalidSubtreeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ReportInvalidSubtreeResponse) + err := c.cc.Invoke(ctx, PeerService_ReportInvalidSubtree_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *peerServiceClient) ReportValidBlock(ctx context.Context, in *ReportValidBlockRequest, opts ...grpc.CallOption) (*ReportValidBlockResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ReportValidBlockResponse) @@ -358,6 +370,7 @@ type PeerServiceServer interface { GetPeersForCatchup(context.Context, *GetPeersForCatchupRequest) (*GetPeersForCatchupResponse, error) // Subtree and block validation reporting ReportValidSubtree(context.Context, *ReportValidSubtreeRequest) (*ReportValidSubtreeResponse, error) + ReportInvalidSubtree(context.Context, *ReportInvalidSubtreeRequest) (*ReportInvalidSubtreeResponse, error) ReportValidBlock(context.Context, *ReportValidBlockRequest) (*ReportValidBlockResponse, error) // Peer status checking IsPeerMalicious(context.Context, *IsPeerMaliciousRequest) (*IsPeerMaliciousResponse, error) @@ -432,6 +445,9 @@ func (UnimplementedPeerServiceServer) GetPeersForCatchup(context.Context, *GetPe func (UnimplementedPeerServiceServer) ReportValidSubtree(context.Context, *ReportValidSubtreeRequest) (*ReportValidSubtreeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReportValidSubtree not implemented") } +func (UnimplementedPeerServiceServer) ReportInvalidSubtree(context.Context, *ReportInvalidSubtreeRequest) (*ReportInvalidSubtreeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method reportInvalidSubtree not implemented") +} func (UnimplementedPeerServiceServer) ReportValidBlock(context.Context, *ReportValidBlockRequest) (*ReportValidBlockResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReportValidBlock not implemented") } @@ -795,6 +811,24 @@ func _PeerService_ReportValidSubtree_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _PeerService_ReportInvalidSubtree_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReportInvalidSubtreeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PeerServiceServer).ReportInvalidSubtree(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PeerService_ReportInvalidSubtree_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PeerServiceServer).ReportInvalidSubtree(ctx, req.(*ReportInvalidSubtreeRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _PeerService_ReportValidBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ReportValidBlockRequest) if err := dec(in); err != nil { @@ -982,6 +1016,10 @@ var PeerService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ReportValidSubtree", Handler: _PeerService_ReportValidSubtree_Handler, }, + { + MethodName: "reportInvalidSubtree", + Handler: _PeerService_ReportInvalidSubtree_Handler, + }, { MethodName: "ReportValidBlock", Handler: _PeerService_ReportValidBlock_Handler, diff --git a/services/propagation/propagation_api/propagation_api.pb.go b/services/propagation/propagation_api/propagation_api.pb.go index 26639bcfa5..1fd329474b 100644 --- a/services/propagation/propagation_api/propagation_api.pb.go +++ b/services/propagation/propagation_api/propagation_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/propagation/propagation_api/propagation_api.proto package propagation_api diff --git a/services/propagation/propagation_api/propagation_api_grpc.pb.go b/services/propagation/propagation_api/propagation_api_grpc.pb.go index d6236b1a1f..51e41ead4e 100644 --- a/services/propagation/propagation_api/propagation_api_grpc.pb.go +++ b/services/propagation/propagation_api/propagation_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/propagation/propagation_api/propagation_api.proto package propagation_api diff --git a/services/rpc/handlers_additional_test.go b/services/rpc/handlers_additional_test.go index 52549592ca..839b42e0a9 100644 --- a/services/rpc/handlers_additional_test.go +++ b/services/rpc/handlers_additional_test.go @@ -5230,6 +5230,11 @@ type mockP2PClient struct { getPeerRegistryFunc func(ctx context.Context) ([]*p2p.PeerInfo, error) } +func (m *mockP2PClient) ReportInvalidSubtree(ctx context.context.Context, peerID string, subtreeHash string) error { + //TODO implement me + panic("implement me") +} + func (m *mockP2PClient) GetPeers(ctx context.Context) ([]*p2p.PeerInfo, error) { if m.getPeersFunc != nil { return m.getPeersFunc(ctx) diff --git a/services/subtreevalidation/SubtreeValidation.go b/services/subtreevalidation/SubtreeValidation.go index 78764c7d8a..afad475efc 100644 --- a/services/subtreevalidation/SubtreeValidation.go +++ b/services/subtreevalidation/SubtreeValidation.go @@ -929,10 +929,10 @@ func (u *Server) getSubtreeTxHashes(spanCtx context.Context, stat *gocore.Stat, u.logger.Debugf("[getSubtreeTxHashes][%s] done with subtree response", subtreeHash.String()) // TODO: Report successful subtree fetch to improve peer reputation - // Cannot call ReportValidSubtree here because we don't have peer ID, only baseURL (HTTP URL) + // Cannot call ReportValidSubtreeHandler here because we don't have peer ID, only baseURL (HTTP URL) // Need to track peer ID through the call chain if we want to enable this // if u.p2pClient != nil { - // if err := u.p2pClient.ReportValidSubtree(spanCtx, peerID, subtreeHash.String()); err != nil { + // if err := u.p2pClient.ReportValidSubtreeHandler(spanCtx, peerID, subtreeHash.String()); err != nil { // u.logger.Warnf("[getSubtreeTxHashes][%s] failed to report valid subtree: %v", subtreeHash.String(), err) // } // } @@ -1232,10 +1232,10 @@ func (u *Server) getSubtreeMissingTxs(ctx context.Context, subtreeHash chainhash subtreeDataExists = true // TODO: Report successful subtree data fetch to improve peer reputation - // Cannot call ReportValidSubtree here because we don't have peer ID, only baseURL (HTTP URL) + // Cannot call ReportValidSubtreeHandler here because we don't have peer ID, only baseURL (HTTP URL) // Need to track peer ID through the call chain if we want to enable this // if u.p2pClient != nil { - // if err := u.p2pClient.ReportValidSubtree(ctx, peerID, subtreeHash.String()); err != nil { + // if err := u.p2pClient.ReportValidSubtreeHandler(ctx, peerID, subtreeHash.String()); err != nil { // u.logger.Warnf("[validateSubtree][%s] failed to report valid subtree: %v", subtreeHash.String(), err) // } // } diff --git a/services/subtreevalidation/p2p_client_interface.go b/services/subtreevalidation/p2p_client_interface.go index 125d1aefd7..85ecedfb00 100644 --- a/services/subtreevalidation/p2p_client_interface.go +++ b/services/subtreevalidation/p2p_client_interface.go @@ -13,6 +13,9 @@ type P2PClientI interface { // ReportValidSubtree reports that a subtree was successfully fetched and validated from a peer. ReportValidSubtree(ctx context.Context, peerID string, subtreeHash string) error + // ReportInvalidSubtree reports that a subtree fetched from a peer was found to be invalid. + ReportInvalidSubtree(ctx context.Context, peerID string, subtreeHash string, reason string) error + // RecordBytesDownloaded records the number of bytes downloaded via HTTP from a peer. // This is called after downloading data (subtrees, etc.) from a peer's DataHub URL. RecordBytesDownloaded(ctx context.Context, peerID string, bytesDownloaded uint64) error diff --git a/services/subtreevalidation/subtreeHandler.go b/services/subtreevalidation/subtreeHandler.go index 99fb37c9e5..594bb03e8f 100644 --- a/services/subtreevalidation/subtreeHandler.go +++ b/services/subtreevalidation/subtreeHandler.go @@ -78,6 +78,7 @@ func (u *Server) subtreeMessageHandler(ctx context.Context) func(msg *kafka.Kafk } } +// subtreesHandler processes a Kafka message for subtree validation. func (u *Server) subtreesHandler(msg *kafka.KafkaMessage) error { if msg != nil { blockIDsMap := u.currentBlockIDsMap.Load() @@ -151,6 +152,11 @@ func (u *Server) subtreesHandler(msg *kafka.KafkaMessage) error { // validate the subtree as if it is for the next block height // this is because subtrees are always validated ahead of time before they are needed for a block if subtree, err = u.ValidateSubtreeInternal(ctx, v, bestBlockHeaderMeta.Height+1, *blockIDsMap); err != nil { + // if subtree validation fails, report invalid subtree to p2p client + p2pErr := u.p2pClient.ReportInvalidSubtree(ctx, kafkaMsg.PeerId, kafkaMsg.Hash, err.Error()) + if p2pErr != nil { + u.logger.Errorf("failed to report invalid subtree to p2p client: %v", p2pErr) + } return err } diff --git a/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api.pb.go b/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api.pb.go index ea96e214c7..0b03df3a07 100644 --- a/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api.pb.go +++ b/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/subtreevalidation/subtreevalidation_api/subtreevalidation_api.proto package subtreevalidation_api diff --git a/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api_grpc.pb.go b/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api_grpc.pb.go index 657e2b169c..3a0d6eb48a 100644 --- a/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api_grpc.pb.go +++ b/services/subtreevalidation/subtreevalidation_api/subtreevalidation_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/subtreevalidation/subtreevalidation_api/subtreevalidation_api.proto package subtreevalidation_api diff --git a/services/validator/validator_api/validator_api.pb.go b/services/validator/validator_api/validator_api.pb.go index 2cc2990b43..c3274f1de0 100644 --- a/services/validator/validator_api/validator_api.pb.go +++ b/services/validator/validator_api/validator_api.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: services/validator/validator_api/validator_api.proto package validator_api diff --git a/services/validator/validator_api/validator_api_grpc.pb.go b/services/validator/validator_api/validator_api_grpc.pb.go index cf39da97c0..4f199b2aa5 100644 --- a/services/validator/validator_api/validator_api_grpc.pb.go +++ b/services/validator/validator_api/validator_api_grpc.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v6.33.0 +// - protoc v6.32.1 // source: services/validator/validator_api/validator_api.proto package validator_api diff --git a/stores/utxo/status.pb.go b/stores/utxo/status.pb.go index 237316c69e..a129170e24 100644 --- a/stores/utxo/status.pb.go +++ b/stores/utxo/status.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: stores/utxo/status.proto package utxo diff --git a/util/kafka/kafka_message/kafka_messages.pb.go b/util/kafka/kafka_message/kafka_messages.pb.go index 175f25fd6e..95f6be898e 100644 --- a/util/kafka/kafka_message/kafka_messages.pb.go +++ b/util/kafka/kafka_message/kafka_messages.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.10 -// protoc v6.33.0 +// protoc v6.32.1 // source: util/kafka/kafka_message/kafka_messages.proto package kafkamessage From 2602d9d7e0d9b3bf0f1c9b34a0e82b628d659b9c Mon Sep 17 00:00:00 2001 From: Dylan Murray Date: Tue, 25 Nov 2025 00:02:26 -0500 Subject: [PATCH 2/2] Add a basic test --- services/p2p/Client_test.go | 8 ++++ services/p2p/Server.go | 43 +++---------------- .../p2p/catchup_metrics_integration_test.go | 35 +++++++++++++++ services/p2p/handler.go | 6 +-- 4 files changed, 53 insertions(+), 39 deletions(-) diff --git a/services/p2p/Client_test.go b/services/p2p/Client_test.go index 5f1cc1f33f..e81c799b68 100644 --- a/services/p2p/Client_test.go +++ b/services/p2p/Client_test.go @@ -36,6 +36,7 @@ type MockPeerServiceClient struct { UpdateCatchupErrorFunc func(ctx context.Context, in *p2p_api.UpdateCatchupErrorRequest, opts ...grpc.CallOption) (*p2p_api.UpdateCatchupErrorResponse, error) ResetReputationFunc func(ctx context.Context, in *p2p_api.ResetReputationRequest, opts ...grpc.CallOption) (*p2p_api.ResetReputationResponse, error) GetPeersForCatchupFunc func(ctx context.Context, in *p2p_api.GetPeersForCatchupRequest, opts ...grpc.CallOption) (*p2p_api.GetPeersForCatchupResponse, error) + ReportInvalidSubtreeFunc func(ctx context.Context, in *p2p_api.ReportInvalidSubtreeRequest, opts ...grpc.CallOption) (*p2p_api.ReportInvalidSubtreeResponse, error) ReportValidSubtreeFunc func(ctx context.Context, in *p2p_api.ReportValidSubtreeRequest, opts ...grpc.CallOption) (*p2p_api.ReportValidSubtreeResponse, error) ReportValidBlockFunc func(ctx context.Context, in *p2p_api.ReportValidBlockRequest, opts ...grpc.CallOption) (*p2p_api.ReportValidBlockResponse, error) IsPeerMaliciousFunc func(ctx context.Context, in *p2p_api.IsPeerMaliciousRequest, opts ...grpc.CallOption) (*p2p_api.IsPeerMaliciousResponse, error) @@ -163,6 +164,13 @@ func (m *MockPeerServiceClient) GetPeersForCatchup(ctx context.Context, in *p2p_ return &p2p_api.GetPeersForCatchupResponse{Peers: []*p2p_api.PeerInfoForCatchup{}}, nil } +func (m *MockPeerServiceClient) ReportInvalidSubtree(ctx context.Context, in *p2p_api.ReportInvalidSubtreeRequest, opts ...grpc.CallOption) (*p2p_api.ReportInvalidSubtreeResponse, error) { + if m.ReportInvalidSubtreeFunc != nil { + return m.ReportInvalidSubtreeFunc(ctx, in, opts...) + } + return &p2p_api.ReportInvalidSubtreeResponse{Success: true}, nil +} + func (m *MockPeerServiceClient) ReportValidSubtree(ctx context.Context, in *p2p_api.ReportValidSubtreeRequest, opts ...grpc.CallOption) (*p2p_api.ReportValidSubtreeResponse, error) { if m.ReportValidSubtreeFunc != nil { return m.ReportValidSubtreeFunc(ctx, in, opts...) diff --git a/services/p2p/Server.go b/services/p2p/Server.go index bc4e28f12c..ea0e4d2fb0 100644 --- a/services/p2p/Server.go +++ b/services/p2p/Server.go @@ -1808,49 +1808,20 @@ func (s *Server) ReportInvalidBlock(ctx context.Context, blockHash string, reaso } // reportInvalidSubtree handles invalid subtree reports with explicit peer URL -func (s *Server) reportInvalidSubtree(ctx context.Context, subtreeHash string, peerURL string, reason string) error { - var peerID string - - // First try to get peer ID from the subtreePeerMap (for subtrees received via P2P) - peerID, err := s.getPeerFromMap(&s.subtreePeerMap, subtreeHash, "subtree") - if err != nil && peerURL != "" { - // If not found in map and we have a peer URL, look up the peer ID from the URL - peerID = s.getPeerIDFromDataHubURL(peerURL) - if peerID == "" { - s.logger.Warnf("[reportInvalidSubtree] could not find peer ID for URL %s, subtree %s, reason: %s", - peerURL, subtreeHash, reason) - return nil // Don't return error, just log and continue - } - s.logger.Debugf("[reportInvalidSubtree] found peer %s from URL %s for subtree %s", - peerID, peerURL, subtreeHash) - } - - if peerID == "" { - s.logger.Warnf("[reportInvalidSubtree] could not determine peer for subtree %s, reason: %s", - subtreeHash, reason) - return nil - } - +func (s *Server) reportInvalidSubtree(ctx context.Context, subtreeHash string, peerID string, reason string) error { // Add ban score to the peer s.logger.Infof("[reportInvalidSubtree] adding ban score to peer %s for invalid subtree %s: %s", peerID, subtreeHash, reason) - // Record as malicious interaction for reputation tracking - s.peerRegistry.RecordMaliciousInteraction(peer.ID(peerID)) - - // Create the request to add ban score - req := &p2p_api.AddBanScoreRequest{ - PeerId: peerID, - Reason: "invalid_subtree", - } - - // Call the AddBanScore method - _, err = s.AddBanScore(ctx, req) + peerDecoded, err := peer.Decode(peerID) if err != nil { - s.logger.Errorf("[reportInvalidSubtree] error adding ban score to peer %s: %v", peerID, err) - return errors.NewServiceError("error adding ban score to peer %s", peerID, err) + s.logger.Errorf("[reportInvalidSubtree] error decoding peer ID %s: %v", peerID, err) + return errors.NewServiceError("error decoding peer ID %s", peerID, err) } + // Record as malicious interaction for reputation tracking + s.peerRegistry.RecordMaliciousInteraction(peerDecoded) + // Remove the subtree from the map to avoid memory leaks s.subtreePeerMap.Delete(subtreeHash) diff --git a/services/p2p/catchup_metrics_integration_test.go b/services/p2p/catchup_metrics_integration_test.go index b54b08b07e..aa1b512184 100644 --- a/services/p2p/catchup_metrics_integration_test.go +++ b/services/p2p/catchup_metrics_integration_test.go @@ -543,6 +543,41 @@ func TestReportValidSubtree_GRPCEndpoint(t *testing.T) { assert.Equal(t, int64(1), info.InteractionSuccesses) } +// TestReportInvalidSubtree_GRPCEndpoint tests the gRPC endpoint validation +func TestReportInvalidSubtree_GRPCEndpoint(t *testing.T) { + ctx := context.Background() + + // Create P2P service + p2pRegistry := NewPeerRegistry() + p2pServer := &Server{ + peerRegistry: p2pRegistry, + logger: ulogger.TestLogger{}, + } + + // Create a test peer + testPeerID, err := peer.Decode("12D3KooWBPqTBhshqRZMKZtqb5sfgckM9JYkWDR7eW5kSPEKwKCW") + require.NoError(t, err) + + // Add peer to registry + p2pRegistry.Put(testPeerID, "", 0, nil, "") + + // Test valid request returns success + req := &p2p_api.ReportInvalidSubtreeRequest{ + PeerId: testPeerID.String(), + SubtreeHash: "test_subtree_hash_123", + Reason: "reason", + } + resp, err := p2pServer.ReportInvalidSubtreeHandler(ctx, req) + require.NoError(t, err) + assert.True(t, resp.Success) + assert.Equal(t, "invalid subtree reported", resp.Message) + + // Verify peer metrics were updated + info, exists := p2pRegistry.Get(testPeerID) + require.True(t, exists) + assert.Equal(t, int64(1), info.InteractionFailures) +} + // TestReportValidSubtree_MissingHash tests error handling when subtree hash is missing func TestReportValidSubtree_MissingHash(t *testing.T) { ctx := context.Background() diff --git a/services/p2p/handler.go b/services/p2p/handler.go index aa4093f073..127efb848a 100644 --- a/services/p2p/handler.go +++ b/services/p2p/handler.go @@ -53,16 +53,16 @@ func (s *Server) ReportValidSubtreeHandler(_ context.Context, req *p2p_api.Repor } // ReportInvalidSubtreeHandler is a gRPC handler for reporting invalid subtree reception -func (s *Server) ReportInvalidSubtreeHandler(ctx context.Context, req *p2p_api.ReportInvalidSubtreeRequest) (*p2p_api.ReportValidSubtreeResponse, error) { +func (s *Server) ReportInvalidSubtreeHandler(ctx context.Context, req *p2p_api.ReportInvalidSubtreeRequest) (*p2p_api.ReportInvalidSubtreeResponse, error) { err := s.reportInvalidSubtree(ctx, req.SubtreeHash, req.PeerId, req.Reason) if err != nil { - return &p2p_api.ReportValidSubtreeResponse{ + return &p2p_api.ReportInvalidSubtreeResponse{ Success: false, Message: fmt.Sprintf("failed to report invalid subtree: %v", err), }, errors.WrapGRPC(err) } - return &p2p_api.ReportValidSubtreeResponse{ + return &p2p_api.ReportInvalidSubtreeResponse{ Success: true, Message: "invalid subtree reported", }, nil