Files
p2p/message/outbound_msg_builder_zap.go

696 lines
14 KiB
Go

//go:build !grpc
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package message
import (
"net/netip"
"time"
"github.com/luxfi/ids"
"github.com/luxfi/node/utils/compression"
"github.com/luxfi/node/utils/ips"
"github.com/luxfi/p2p/proto/pb/p2p"
)
var _ OutboundMsgBuilder = (*outMsgBuilder)(nil)
// OutboundMsgBuilder builds outbound messages. Outbound messages are returned
// with a reference count of 1. Once the reference count hits 0, the message
// bytes should no longer be accessed.
type OutboundMsgBuilder interface {
Handshake(
networkID uint32,
myTime uint64,
ip netip.AddrPort,
client string,
major uint32,
minor uint32,
patch uint32,
ipSigningTime uint64,
ipNodeIDSig []byte,
ipBLSSig []byte,
trackedNets []ids.ID,
supportedLPs []uint32,
objectedLPs []uint32,
knownPeersFilter []byte,
knownPeersSalt []byte,
requestAllNetIPs bool,
) (OutboundMessage, error)
GetPeerList(
knownPeersFilter []byte,
knownPeersSalt []byte,
requestAllNetIPs bool,
) (OutboundMessage, error)
PeerList(
peers []*ips.ClaimedIPPort,
bypassThrottling bool,
) (OutboundMessage, error)
Ping(
primaryUptime uint32,
) (OutboundMessage, error)
Pong() (OutboundMessage, error)
GetStateSummaryFrontier(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
) (OutboundMessage, error)
StateSummaryFrontier(
chainID ids.ID,
requestID uint32,
summary []byte,
) (OutboundMessage, error)
GetAcceptedStateSummary(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
heights []uint64,
) (OutboundMessage, error)
AcceptedStateSummary(
chainID ids.ID,
requestID uint32,
summaryIDs []ids.ID,
) (OutboundMessage, error)
GetAcceptedFrontier(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
) (OutboundMessage, error)
AcceptedFrontier(
chainID ids.ID,
requestID uint32,
containerID ids.ID,
) (OutboundMessage, error)
GetAccepted(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerIDs []ids.ID,
) (OutboundMessage, error)
Accepted(
chainID ids.ID,
requestID uint32,
containerIDs []ids.ID,
) (OutboundMessage, error)
GetAncestors(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerID ids.ID,
engineType p2p.EngineType,
) (OutboundMessage, error)
Ancestors(
chainID ids.ID,
requestID uint32,
containers [][]byte,
) (OutboundMessage, error)
Get(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerID ids.ID,
) (OutboundMessage, error)
Put(
chainID ids.ID,
requestID uint32,
container []byte,
) (OutboundMessage, error)
PushQuery(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
container []byte,
requestedHeight uint64,
) (OutboundMessage, error)
PullQuery(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerID ids.ID,
requestedHeight uint64,
) (OutboundMessage, error)
Chits(
chainID ids.ID,
requestID uint32,
preferredID ids.ID,
preferredIDAtHeight ids.ID,
acceptedID ids.ID,
acceptedHeight uint64,
) (OutboundMessage, error)
AppRequest(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
msg []byte,
) (OutboundMessage, error)
AppResponse(
chainID ids.ID,
requestID uint32,
msg []byte,
) (OutboundMessage, error)
AppError(
chainID ids.ID,
requestID uint32,
errorCode int32,
errorMessage string,
) (OutboundMessage, error)
AppGossip(
chainID ids.ID,
msg []byte,
) (OutboundMessage, error)
SimplexMessage(
msg *p2p.Simplex,
) (OutboundMessage, error)
}
type outMsgBuilder struct {
compressionType compression.Type
builder *msgBuilder
}
// Use "message.NewCreator" to import this function
// since we do not expose "msgBuilder" yet
func newOutboundBuilder(compressionType compression.Type, builder *msgBuilder) OutboundMsgBuilder {
return &outMsgBuilder{
compressionType: compressionType,
builder: builder,
}
}
func (b *outMsgBuilder) Ping(
primaryUptime uint32,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Ping: &p2p.Ping{
Uptime: primaryUptime,
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) Pong() (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Pong: &p2p.Pong{},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) Handshake(
networkID uint32,
myTime uint64,
ip netip.AddrPort,
client string,
major uint32,
minor uint32,
patch uint32,
ipSigningTime uint64,
ipNodeIDSig []byte,
ipBLSSig []byte,
trackedNets []ids.ID,
supportedLPs []uint32,
objectedLPs []uint32,
knownPeersFilter []byte,
knownPeersSalt []byte,
requestAllNetIPs bool,
) (OutboundMessage, error) {
chainIDBytes := make([][]byte, len(trackedNets))
encodeIDs(trackedNets, chainIDBytes)
return b.builder.createOutbound(
&p2p.Message{
Handshake: &p2p.Handshake{
NetworkId: networkID,
MyTime: myTime,
IpAddr: ip.Addr().AsSlice(),
IpPort: uint32(ip.Port()),
IpSigningTime: ipSigningTime,
IpNodeIdSig: ipNodeIDSig,
TrackedNets: chainIDBytes,
Client: &p2p.Client{
Name: client,
Major: major,
Minor: minor,
Patch: patch,
},
SupportedLps: supportedLPs,
ObjectedLps: objectedLPs,
KnownPeers: &p2p.BloomFilter{
Filter: knownPeersFilter,
Salt: knownPeersSalt,
},
IpBlsSig: ipBLSSig,
AllNets: requestAllNetIPs,
},
},
compression.TypeNone,
true,
)
}
func (b *outMsgBuilder) GetPeerList(
knownPeersFilter []byte,
knownPeersSalt []byte,
requestAllNetIPs bool,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
GetPeerList: &p2p.GetPeerList{
KnownPeers: &p2p.BloomFilter{
Filter: knownPeersFilter,
Salt: knownPeersSalt,
},
AllNets: requestAllNetIPs,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) PeerList(peers []*ips.ClaimedIPPort, bypassThrottling bool) (OutboundMessage, error) {
claimIPPorts := make([]*p2p.ClaimedIpPort, len(peers))
for i, p := range peers {
claimIPPorts[i] = &p2p.ClaimedIpPort{
X509Certificate: p.Cert.Raw,
IpAddr: p.AddrPort.Addr().AsSlice(),
IpPort: uint32(p.AddrPort.Port()),
Timestamp: p.Timestamp,
Signature: p.Signature,
TxId: ids.Empty[:],
}
}
return b.builder.createOutbound(
&p2p.Message{
PeerList: &p2p.PeerList{
ClaimedIpPorts: claimIPPorts,
},
},
b.compressionType,
bypassThrottling,
)
}
func (b *outMsgBuilder) GetStateSummaryFrontier(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
GetStateSummaryFrontier: &p2p.GetStateSummaryFrontier{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) StateSummaryFrontier(
chainID ids.ID,
requestID uint32,
summary []byte,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
StateSummaryFrontier: &p2p.StateSummaryFrontier{
ChainId: chainID[:],
RequestId: requestID,
Summary: summary,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) GetAcceptedStateSummary(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
heights []uint64,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
GetAcceptedStateSummary: &p2p.GetAcceptedStateSummary{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
Heights: heights,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) AcceptedStateSummary(
chainID ids.ID,
requestID uint32,
summaryIDs []ids.ID,
) (OutboundMessage, error) {
summaryIDBytes := make([][]byte, len(summaryIDs))
encodeIDs(summaryIDs, summaryIDBytes)
return b.builder.createOutbound(
&p2p.Message{
AcceptedStateSummary: &p2p.AcceptedStateSummary{
ChainId: chainID[:],
RequestId: requestID,
SummaryIds: summaryIDBytes,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) GetAcceptedFrontier(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
GetAcceptedFrontier: &p2p.GetAcceptedFrontier{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) AcceptedFrontier(
chainID ids.ID,
requestID uint32,
containerID ids.ID,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
AcceptedFrontier: &p2p.AcceptedFrontier{
ChainId: chainID[:],
RequestId: requestID,
ContainerId: containerID[:],
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) GetAccepted(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerIDs []ids.ID,
) (OutboundMessage, error) {
containerIDBytes := make([][]byte, len(containerIDs))
encodeIDs(containerIDs, containerIDBytes)
return b.builder.createOutbound(
&p2p.Message{
GetAccepted: &p2p.GetAccepted{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
ContainerIds: containerIDBytes,
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) Accepted(
chainID ids.ID,
requestID uint32,
containerIDs []ids.ID,
) (OutboundMessage, error) {
containerIDBytes := make([][]byte, len(containerIDs))
encodeIDs(containerIDs, containerIDBytes)
return b.builder.createOutbound(
&p2p.Message{
Accepted: &p2p.Accepted{
ChainId: chainID[:],
RequestId: requestID,
ContainerIds: containerIDBytes,
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) GetAncestors(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerID ids.ID,
engineType p2p.EngineType,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
GetAncestors: &p2p.GetAncestors{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
ContainerId: containerID[:],
EngineType: engineType,
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) Ancestors(
chainID ids.ID,
requestID uint32,
containers [][]byte,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Ancestors: &p2p.Ancestors{
ChainId: chainID[:],
RequestId: requestID,
Containers: containers,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) Get(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerID ids.ID,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Get: &p2p.Get{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
ContainerId: containerID[:],
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) Put(
chainID ids.ID,
requestID uint32,
container []byte,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Put: &p2p.Put{
ChainId: chainID[:],
RequestId: requestID,
Container: container,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) PushQuery(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
container []byte,
requestedHeight uint64,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
PushQuery: &p2p.PushQuery{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
Container: container,
RequestedHeight: requestedHeight,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) PullQuery(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
containerID ids.ID,
requestedHeight uint64,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
PullQuery: &p2p.PullQuery{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
ContainerId: containerID[:],
RequestedHeight: requestedHeight,
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) Chits(
chainID ids.ID,
requestID uint32,
preferredID ids.ID,
preferredIDAtHeight ids.ID,
acceptedID ids.ID,
acceptedHeight uint64,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Chits: &p2p.Chits{
ChainId: chainID[:],
RequestId: requestID,
PreferredId: preferredID[:],
PreferredIdAtHeight: preferredIDAtHeight[:],
AcceptedId: acceptedID[:],
AcceptedHeight: acceptedHeight,
},
},
compression.TypeNone,
false,
)
}
func (b *outMsgBuilder) AppRequest(
chainID ids.ID,
requestID uint32,
deadline time.Duration,
msg []byte,
) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
AppRequest: &p2p.AppRequest{
ChainId: chainID[:],
RequestId: requestID,
Deadline: uint64(deadline),
AppBytes: msg,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) AppResponse(chainID ids.ID, requestID uint32, msg []byte) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
AppResponse: &p2p.AppResponse{
ChainId: chainID[:],
RequestId: requestID,
AppBytes: msg,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) AppError(chainID ids.ID, requestID uint32, errorCode int32, errorMessage string) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
AppError: &p2p.AppError{
ChainId: chainID[:],
RequestId: requestID,
ErrorCode: errorCode,
ErrorMessage: errorMessage,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) AppGossip(chainID ids.ID, msg []byte) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
AppGossip: &p2p.AppGossip{
ChainId: chainID[:],
AppBytes: msg,
},
},
b.compressionType,
false,
)
}
func (b *outMsgBuilder) SimplexMessage(msg *p2p.Simplex) (OutboundMessage, error) {
return b.builder.createOutbound(
&p2p.Message{
Simplex: msg,
},
b.compressionType,
false,
)
}