diff --git a/config/config.go b/config/config.go index e4815bb652cc..70a1c782fcec 100644 --- a/config/config.go +++ b/config/config.go @@ -38,6 +38,7 @@ import ( "github.com/ava-labs/avalanchego/staking" "github.com/ava-labs/avalanchego/subnets" "github.com/ava-labs/avalanchego/trace" + "github.com/ava-labs/avalanchego/utils/compression" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/dynamicip" @@ -49,6 +50,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/storage" "github.com/ava-labs/avalanchego/utils/timer" + "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/platformvm/reward" "github.com/ava-labs/avalanchego/vms/proposervm" ) @@ -62,7 +64,9 @@ const ( var ( // Deprecated key --> deprecation message (i.e. which key replaces it) - deprecatedKeys = map[string]string{} + deprecatedKeys = map[string]string{ + NetworkCompressionEnabledKey: fmt.Sprintf("use --%s instead", NetworkCompressionTypeKey), + } errInvalidStakerWeights = errors.New("staking weights must be positive") errStakingDisableOnPublicNetwork = errors.New("staking disabled on public network") @@ -81,6 +85,7 @@ var ( errMissingStakingSigningKeyFile = errors.New("missing staking signing key file") errTracingEndpointEmpty = fmt.Errorf("%s cannot be empty", TracingEndpointKey) errPluginDirNotADirectory = errors.New("plugin dir is not a directory") + errZstdNotSupported = errors.New("zstd compression not supported until v1.10") ) func getConsensusConfig(v *viper.Viper) avalanche.Parameters { @@ -302,13 +307,45 @@ func getGossipConfig(v *viper.Viper) subnets.GossipConfig { } } -func getNetworkConfig(v *viper.Viper, stakingEnabled bool, halflife time.Duration) (network.Config, error) { +func getNetworkConfig( + v *viper.Viper, + stakingEnabled bool, + halflife time.Duration, + networkID uint32, // TODO remove after cortina upgrade +) (network.Config, error) { // Set the max number of recent inbound connections upgraded to be // equal to the max number of inbound connections per second. maxInboundConnsPerSec := v.GetFloat64(InboundThrottlerMaxConnsPerSecKey) upgradeCooldown := v.GetDuration(InboundConnUpgradeThrottlerCooldownKey) upgradeCooldownInSeconds := upgradeCooldown.Seconds() maxRecentConnsUpgraded := int(math.Ceil(maxInboundConnsPerSec * upgradeCooldownInSeconds)) + + var ( + compressionType compression.Type + err error + ) + if v.IsSet(NetworkCompressionTypeKey) { + if v.IsSet(NetworkCompressionEnabledKey) { + return network.Config{}, fmt.Errorf("cannot set both %q and %q", NetworkCompressionTypeKey, NetworkCompressionEnabledKey) + } + + compressionType, err = compression.TypeFromString(v.GetString(NetworkCompressionTypeKey)) + if err != nil { + return network.Config{}, err + } + } else { + if v.GetBool(NetworkCompressionEnabledKey) { + compressionType = constants.DefaultNetworkCompressionType + } else { + compressionType = compression.TypeNone + } + } + + cortinaTime := version.GetCortinaTime(networkID) + if compressionType == compression.TypeZstd && !time.Now().After(cortinaTime) { + // TODO remove after cortina upgrade + return network.Config{}, errZstdNotSupported + } config := network.Config{ // Throttling ThrottlerConfig: network.ThrottlerConfig{ @@ -383,7 +420,7 @@ func getNetworkConfig(v *viper.Viper, stakingEnabled bool, halflife time.Duratio }, MaxClockDifference: v.GetDuration(NetworkMaxClockDifferenceKey), - CompressionEnabled: v.GetBool(NetworkCompressionEnabledKey), + CompressionType: compressionType, PingFrequency: v.GetDuration(NetworkPingFrequencyKey), AllowPrivateIPs: v.GetBool(NetworkAllowPrivateIPsKey), UptimeMetricFreq: v.GetDuration(UptimeMetricFreqKey), @@ -1345,7 +1382,7 @@ func GetNodeConfig(v *viper.Viper) (node.Config, error) { } // Network Config - nodeConfig.NetworkConfig, err = getNetworkConfig(v, nodeConfig.EnableStaking, healthCheckAveragerHalflife) + nodeConfig.NetworkConfig, err = getNetworkConfig(v, nodeConfig.EnableStaking, healthCheckAveragerHalflife, nodeConfig.NetworkID) if err != nil { return node.Config{}, err } diff --git a/config/flags.go b/config/flags.go index 30c7cb937afe..98c782d0f161 100644 --- a/config/flags.go +++ b/config/flags.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/trace" + "github.com/ava-labs/avalanchego/utils/compression" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/ulimit" "github.com/ava-labs/avalanchego/utils/units" @@ -152,6 +153,8 @@ func addNodeFlags(fs *pflag.FlagSet) { fs.Duration(NetworkPingFrequencyKey, constants.DefaultPingFrequency, "Frequency of pinging other peers") fs.Bool(NetworkCompressionEnabledKey, constants.DefaultNetworkCompressionEnabled, "If true, compress certain outbound messages. This node will be able to parse compressed inbound messages regardless of this flag's value") + fs.String(NetworkCompressionTypeKey, constants.DefaultNetworkCompressionType.String(), fmt.Sprintf("Compression type for outbound messages. Must be one of [%s, %s, %s]", compression.TypeGzip, compression.TypeZstd, compression.TypeNone)) + fs.Duration(NetworkMaxClockDifferenceKey, constants.DefaultNetworkMaxClockDifference, "Max allowed clock difference value between this node and peers") fs.Bool(NetworkAllowPrivateIPsKey, constants.DefaultNetworkAllowPrivateIPs, "Allows the node to initiate outbound connection attempts to peers with private IPs") fs.Bool(NetworkRequireValidatorToConnectKey, constants.DefaultNetworkRequireValidatorToConnect, "If true, this node will only maintain a connection with another node if this node is a validator, the other node is a validator, or the other node is a beacon") diff --git a/config/keys.go b/config/keys.go index ca3d35b2aec8..1f9e0a00b21d 100644 --- a/config/keys.go +++ b/config/keys.go @@ -98,7 +98,8 @@ const ( NetworkPingTimeoutKey = "network-ping-timeout" NetworkPingFrequencyKey = "network-ping-frequency" NetworkMaxReconnectDelayKey = "network-max-reconnect-delay" - NetworkCompressionEnabledKey = "network-compression-enabled" + NetworkCompressionEnabledKey = "network-compression-enabled" // TODO this is deprecated. Eventually remove it and constants.DefaultNetworkCompressionEnabled + NetworkCompressionTypeKey = "network-compression-type" NetworkMaxClockDifferenceKey = "network-max-clock-difference" NetworkAllowPrivateIPsKey = "network-allow-private-ips" NetworkRequireValidatorToConnectKey = "network-require-validator-to-connect" diff --git a/go.mod b/go.mod index e1e5a438fbf4..fc2f9f2dad3e 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ module github.com/ava-labs/avalanchego go 1.19 require ( + github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 github.com/ava-labs/avalanche-network-runner-sdk v0.3.0 diff --git a/go.sum b/go.sum index 99766a6af14f..35c0caade4f0 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= diff --git a/message/creator.go b/message/creator.go index 9088165b9356..f1a6def2b21e 100644 --- a/message/creator.go +++ b/message/creator.go @@ -8,6 +8,9 @@ import ( "time" "github.com/prometheus/client_golang/prometheus" + + "github.com/ava-labs/avalanchego/utils/compression" + "github.com/ava-labs/avalanchego/utils/logging" ) var _ Creator = (*creator)(nil) @@ -23,13 +26,15 @@ type creator struct { } func NewCreator( + log logging.Logger, metrics prometheus.Registerer, parentNamespace string, - compressionEnabled bool, + compressionType compression.Type, maxMessageTimeout time.Duration, ) (Creator, error) { namespace := fmt.Sprintf("%s_codec", parentNamespace) builder, err := newMsgBuilder( + log, namespace, metrics, maxMessageTimeout, @@ -39,7 +44,7 @@ func NewCreator( } return &creator{ - OutboundMsgBuilder: newOutboundBuilder(compressionEnabled, builder), + OutboundMsgBuilder: newOutboundBuilder(compressionType, builder), InboundMsgBuilder: newInboundBuilder(builder), }, nil } diff --git a/message/inbound_msg_builder_test.go b/message/inbound_msg_builder_test.go index 9eb604b408a4..667a205d1df6 100644 --- a/message/inbound_msg_builder_test.go +++ b/message/inbound_msg_builder_test.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/timer/mockable" ) @@ -21,6 +22,7 @@ func Test_newMsgBuilder(t *testing.T) { require := require.New(t) mb, err := newMsgBuilder( + logging.NoLog{}, "test", prometheus.NewRegistry(), 10*time.Second, diff --git a/message/messages.go b/message/messages.go index 2c2ef9743f20..99ac9dc6c4b2 100644 --- a/message/messages.go +++ b/message/messages.go @@ -4,17 +4,21 @@ package message import ( + "errors" "fmt" "time" "github.com/prometheus/client_golang/prometheus" + "go.uber.org/zap" + "google.golang.org/protobuf/proto" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" "github.com/ava-labs/avalanchego/utils/compression" "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/metric" "github.com/ava-labs/avalanchego/utils/timer/mockable" @@ -24,6 +28,8 @@ import ( var ( _ InboundMessage = (*inboundMessage)(nil) _ OutboundMessage = (*outboundMessage)(nil) + + errUnknownCompressionType = errors.New("message is compressed with an unknown compression type") ) // InboundMessage represents a set of fields for an inbound message @@ -120,46 +126,75 @@ func (m *outboundMessage) BytesSavedCompression() int { // TODO: add other compression algorithms with extended interface type msgBuilder struct { - gzipCompressor compression.Compressor + log logging.Logger + + gzipCompressor compression.Compressor + gzipCompressTimeMetrics map[Op]metric.Averager + gzipDecompressTimeMetrics map[Op]metric.Averager - compressTimeMetrics map[Op]metric.Averager - decompressTimeMetrics map[Op]metric.Averager + zstdCompressor compression.Compressor + zstdCompressTimeMetrics map[Op]metric.Averager + zstdDecompressTimeMetrics map[Op]metric.Averager maxMessageTimeout time.Duration } func newMsgBuilder( + log logging.Logger, namespace string, metrics prometheus.Registerer, maxMessageTimeout time.Duration, ) (*msgBuilder, error) { - cpr, err := compression.NewGzipCompressor(constants.DefaultMaxMessageSize) + gzipCompressor, err := compression.NewGzipCompressor(constants.DefaultMaxMessageSize) + if err != nil { + return nil, err + } + zstdCompressor, err := compression.NewZstdCompressor(constants.DefaultMaxMessageSize) if err != nil { return nil, err } mb := &msgBuilder{ - gzipCompressor: cpr, + log: log, - compressTimeMetrics: make(map[Op]metric.Averager, len(ExternalOps)), - decompressTimeMetrics: make(map[Op]metric.Averager, len(ExternalOps)), + gzipCompressor: gzipCompressor, + gzipCompressTimeMetrics: make(map[Op]metric.Averager, len(ExternalOps)), + gzipDecompressTimeMetrics: make(map[Op]metric.Averager, len(ExternalOps)), + + zstdCompressor: zstdCompressor, + zstdCompressTimeMetrics: make(map[Op]metric.Averager, len(ExternalOps)), + zstdDecompressTimeMetrics: make(map[Op]metric.Averager, len(ExternalOps)), maxMessageTimeout: maxMessageTimeout, } errs := wrappers.Errs{} for _, op := range ExternalOps { - mb.compressTimeMetrics[op] = metric.NewAveragerWithErrs( + mb.gzipCompressTimeMetrics[op] = metric.NewAveragerWithErrs( + namespace, + fmt.Sprintf("gzip_%s_compress_time", op), + fmt.Sprintf("time (in ns) to compress %s messages with gzip", op), + metrics, + &errs, + ) + mb.gzipDecompressTimeMetrics[op] = metric.NewAveragerWithErrs( + namespace, + fmt.Sprintf("gzip_%s_decompress_time", op), + fmt.Sprintf("time (in ns) to decompress %s messages with gzip", op), + metrics, + &errs, + ) + mb.zstdCompressTimeMetrics[op] = metric.NewAveragerWithErrs( namespace, - fmt.Sprintf("%s_compress_time", op), - fmt.Sprintf("time (in ns) to compress %s messages", op), + fmt.Sprintf("zstd_%s_compress_time", op), + fmt.Sprintf("time (in ns) to compress %s messages with zstd", op), metrics, &errs, ) - mb.decompressTimeMetrics[op] = metric.NewAveragerWithErrs( + mb.zstdDecompressTimeMetrics[op] = metric.NewAveragerWithErrs( namespace, - fmt.Sprintf("%s_decompress_time", op), - fmt.Sprintf("time (in ns) to decompress %s messages", op), + fmt.Sprintf("zstd_%s_decompress_time", op), + fmt.Sprintf("time (in ns) to decompress %s messages with zstd", op), metrics, &errs, ) @@ -169,15 +204,16 @@ func newMsgBuilder( func (mb *msgBuilder) marshal( uncompressedMsg *p2p.Message, - gzipCompress bool, -) ([]byte, int, time.Duration, error) { + compressionType compression.Type, +) ([]byte, int, Op, error) { uncompressedMsgBytes, err := proto.Marshal(uncompressedMsg) if err != nil { return nil, 0, 0, err } - if !gzipCompress { - return uncompressedMsgBytes, 0, 0, nil + op, err := ToOp(uncompressedMsg) + if err != nil { + return nil, 0, 0, err } // If compression is enabled, we marshal twice: @@ -186,69 +222,125 @@ func (mb *msgBuilder) marshal( // // This recursive packing allows us to avoid an extra compression on/off // field in the message. - startTime := time.Now() - compressedBytes, err := mb.gzipCompressor.Compress(uncompressedMsgBytes) - if err != nil { - return nil, 0, 0, err + var ( + startTime = time.Now() + compressedMsg p2p.Message + opToCompressTimeMetrics map[Op]metric.Averager + ) + switch compressionType { + case compression.TypeNone: + return uncompressedMsgBytes, 0, op, nil + case compression.TypeGzip: + compressedBytes, err := mb.gzipCompressor.Compress(uncompressedMsgBytes) + if err != nil { + return nil, 0, 0, err + } + compressedMsg = p2p.Message{ + Message: &p2p.Message_CompressedGzip{ + CompressedGzip: compressedBytes, + }, + } + opToCompressTimeMetrics = mb.gzipCompressTimeMetrics + case compression.TypeZstd: + compressedBytes, err := mb.zstdCompressor.Compress(uncompressedMsgBytes) + if err != nil { + return nil, 0, 0, err + } + compressedMsg = p2p.Message{ + Message: &p2p.Message_CompressedZstd{ + CompressedZstd: compressedBytes, + }, + } + opToCompressTimeMetrics = mb.zstdCompressTimeMetrics + default: + return nil, 0, 0, errUnknownCompressionType } - compressedMsg := p2p.Message{ - Message: &p2p.Message_CompressedGzip{ - CompressedGzip: compressedBytes, - }, - } compressedMsgBytes, err := proto.Marshal(&compressedMsg) if err != nil { return nil, 0, 0, err } compressTook := time.Since(startTime) + if compressTimeMetric, ok := opToCompressTimeMetrics[op]; ok { + compressTimeMetric.Observe(float64(compressTook)) + } else { + // Should never happen + mb.log.Warn("no compression metric found for op", + zap.Stringer("op", op), + zap.Stringer("compressionType", compressionType), + ) + } + bytesSaved := len(uncompressedMsgBytes) - len(compressedMsgBytes) - return compressedMsgBytes, bytesSaved, compressTook, nil + return compressedMsgBytes, bytesSaved, op, nil } -func (mb *msgBuilder) unmarshal(b []byte) (*p2p.Message, bool, int, time.Duration, error) { +func (mb *msgBuilder) unmarshal(b []byte) (*p2p.Message, int, Op, error) { m := new(p2p.Message) if err := proto.Unmarshal(b, m); err != nil { - return nil, false, 0, 0, err + return nil, 0, 0, err } - compressed := m.GetCompressedGzip() - if len(compressed) == 0 { + // Figure out what compression type, if any, was used to compress the message. + var ( + opToDecompressTimeMetrics map[Op]metric.Averager + compressor compression.Compressor + compressedBytes []byte + gzipCompressed = m.GetCompressedGzip() + zstdCompressed = m.GetCompressedZstd() + ) + switch { + case len(gzipCompressed) > 0: + opToDecompressTimeMetrics = mb.gzipDecompressTimeMetrics + compressor = mb.gzipCompressor + compressedBytes = gzipCompressed + case len(zstdCompressed) > 0: + opToDecompressTimeMetrics = mb.zstdDecompressTimeMetrics + compressor = mb.zstdCompressor + compressedBytes = zstdCompressed + default: // The message wasn't compressed - return m, false, 0, 0, nil + op, err := ToOp(m) + return m, 0, op, err } startTime := time.Now() - decompressed, err := mb.gzipCompressor.Decompress(compressed) + + decompressed, err := compressor.Decompress(compressedBytes) if err != nil { - return nil, true, 0, 0, err + return nil, 0, 0, err } + bytesSavedCompression := len(decompressed) - len(compressedBytes) if err := proto.Unmarshal(decompressed, m); err != nil { - return nil, true, 0, 0, err + return nil, 0, 0, err } decompressTook := time.Since(startTime) - bytesSavedCompression := len(decompressed) - len(compressed) - return m, true, bytesSavedCompression, decompressTook, nil -} - -func (mb *msgBuilder) createOutbound(m *p2p.Message, gzipCompress bool, bypassThrottling bool) (*outboundMessage, error) { - b, saved, compressTook, err := mb.marshal(m, gzipCompress) + // Record decompression time metric + op, err := ToOp(m) if err != nil { - return nil, err + return nil, 0, 0, err + } + if decompressTimeMetric, ok := opToDecompressTimeMetrics[op]; ok { + decompressTimeMetric.Observe(float64(decompressTook)) + } else { + // Should never happen + mb.log.Warn("no decompression metric found for op", + zap.Stringer("op", op), + ) } - op, err := ToOp(m) + return m, bytesSavedCompression, op, nil +} + +func (mb *msgBuilder) createOutbound(m *p2p.Message, compressionType compression.Type, bypassThrottling bool) (*outboundMessage, error) { + b, saved, op, err := mb.marshal(m, compressionType) if err != nil { return nil, err } - if gzipCompress { - mb.compressTimeMetrics[op].Observe(float64(compressTook)) - } - return &outboundMessage{ bypassThrottling: bypassThrottling, op: op, @@ -262,12 +354,7 @@ func (mb *msgBuilder) parseInbound( nodeID ids.NodeID, onFinishedHandling func(), ) (*inboundMessage, error) { - m, wasCompressed, bytesSavedCompression, decompressTook, err := mb.unmarshal(bytes) - if err != nil { - return nil, err - } - - op, err := ToOp(m) + m, bytesSavedCompression, op, err := mb.unmarshal(bytes) if err != nil { return nil, err } @@ -277,10 +364,6 @@ func (mb *msgBuilder) parseInbound( return nil, err } - if wasCompressed { - mb.decompressTimeMetrics[op].Observe(float64(decompressTook)) - } - expiration := mockable.MaxTime if deadline, ok := GetDeadline(msg); ok { deadline = math.Min(deadline, mb.maxMessageTimeout) diff --git a/message/messages_benchmark_test.go b/message/messages_benchmark_test.go index 597111d6e126..f87493fc0248 100644 --- a/message/messages_benchmark_test.go +++ b/message/messages_benchmark_test.go @@ -17,6 +17,8 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/utils/compression" + "github.com/ava-labs/avalanchego/utils/logging" ) var ( @@ -62,7 +64,7 @@ func BenchmarkMarshalVersion(b *testing.B) { useBuilder := os.Getenv("USE_BUILDER") != "" - codec, err := newMsgBuilder("", prometheus.NewRegistry(), 10*time.Second) + codec, err := newMsgBuilder(logging.NoLog{}, "", prometheus.NewRegistry(), 10*time.Second) require.NoError(err) b.Logf("proto length %d-byte (use builder %v)", msgLen, useBuilder) @@ -70,7 +72,7 @@ func BenchmarkMarshalVersion(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { if useBuilder { - _, err = codec.createOutbound(&msg, false, false) + _, err = codec.createOutbound(&msg, compression.TypeNone, false) } else { _, err = proto.Marshal(&msg) } @@ -119,7 +121,7 @@ func BenchmarkUnmarshalVersion(b *testing.B) { require.NoError(err) useBuilder := os.Getenv("USE_BUILDER") != "" - codec, err := newMsgBuilder("", prometheus.NewRegistry(), 10*time.Second) + codec, err := newMsgBuilder(logging.NoLog{}, "", prometheus.NewRegistry(), 10*time.Second) require.NoError(err) b.StartTimer() diff --git a/message/messages_test.go b/message/messages_test.go index 55f5cf14c935..c04e3ea44dd2 100644 --- a/message/messages_test.go +++ b/message/messages_test.go @@ -18,6 +18,8 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" "github.com/ava-labs/avalanchego/staking" + "github.com/ava-labs/avalanchego/utils/compression" + "github.com/ava-labs/avalanchego/utils/logging" ) func TestMessage(t *testing.T) { @@ -26,6 +28,7 @@ func TestMessage(t *testing.T) { require := require.New(t) mb, err := newMsgBuilder( + logging.NoLog{}, "test", prometheus.NewRegistry(), 5*time.Second, @@ -51,7 +54,7 @@ func TestMessage(t *testing.T) { desc string op Op msg *p2p.Message - gzipCompress bool + compressionType compression.Type bypassThrottling bool bytesSaved bool // if true, outbound message saved bytes must be non-zero }{ @@ -63,7 +66,7 @@ func TestMessage(t *testing.T) { Ping: &p2p.Ping{}, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -77,7 +80,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -97,7 +100,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -118,7 +121,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -140,12 +143,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "peer_list message with compression", + desc: "peer_list message with gzip compression", op: PeerListOp, msg: &p2p.Message{ Message: &p2p.Message_PeerList{ @@ -162,7 +165,29 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "peer_list message with zstd compression", + op: PeerListOp, + msg: &p2p.Message{ + Message: &p2p.Message_PeerList{ + PeerList: &p2p.PeerList{ + ClaimedIpPorts: []*p2p.ClaimedIpPort{ + { + X509Certificate: testTLSCert.Certificate[0], + IpAddr: []byte(net.IPv6zero), + IpPort: 9651, + Timestamp: uint64(nowUnix), + Signature: compressibleContainers[0], + }, + }, + }, + }, + }, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -181,7 +206,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: false, bytesSaved: false, }, @@ -197,7 +222,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -213,12 +238,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "state_summary_frontier message with compression", + desc: "state_summary_frontier message with gzip compression", op: StateSummaryFrontierOp, msg: &p2p.Message{ Message: &p2p.Message_StateSummaryFrontier_{ @@ -229,7 +254,23 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "state_summary_frontier message with zstd compression", + op: StateSummaryFrontierOp, + msg: &p2p.Message{ + Message: &p2p.Message_StateSummaryFrontier_{ + StateSummaryFrontier_: &p2p.StateSummaryFrontier{ + ChainId: testID[:], + RequestId: 1, + Summary: compressibleContainers[0], + }, + }, + }, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -246,12 +287,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "get_accepted_state_summary message with compression", + desc: "get_accepted_state_summary message with gzip compression", op: GetAcceptedStateSummaryOp, msg: &p2p.Message{ Message: &p2p.Message_GetAcceptedStateSummary{ @@ -263,10 +304,27 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, bypassThrottling: true, bytesSaved: false, }, + { + desc: "get_accepted_state_summary message with zstd compression", + op: GetAcceptedStateSummaryOp, + msg: &p2p.Message{ + Message: &p2p.Message_GetAcceptedStateSummary{ + GetAcceptedStateSummary: &p2p.GetAcceptedStateSummary{ + ChainId: testID[:], + RequestId: 1, + Deadline: 1, + Heights: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + }, + }, + compressionType: compression.TypeZstd, + bypassThrottling: true, + bytesSaved: true, + }, { desc: "accepted_state_summary message with no compression", op: AcceptedStateSummaryOp, @@ -279,12 +337,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "accepted_state_summary message with compression", + desc: "accepted_state_summary message with gzip compression", op: AcceptedStateSummaryOp, msg: &p2p.Message{ Message: &p2p.Message_AcceptedStateSummary_{ @@ -295,7 +353,23 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "accepted_state_summary message with zstd compression", + op: AcceptedStateSummaryOp, + msg: &p2p.Message{ + Message: &p2p.Message_AcceptedStateSummary_{ + AcceptedStateSummary_: &p2p.AcceptedStateSummary{ + ChainId: testID[:], + RequestId: 1, + SummaryIds: [][]byte{testID[:], testID[:], testID[:], testID[:], testID[:], testID[:], testID[:], testID[:], testID[:]}, + }, + }, + }, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -312,7 +386,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -328,7 +402,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -346,7 +420,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -362,7 +436,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -380,7 +454,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -396,12 +470,28 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "ancestors message with compression", + desc: "ancestors message with gzip compression", + op: AncestorsOp, + msg: &p2p.Message{ + Message: &p2p.Message_Ancestors_{ + Ancestors_: &p2p.Ancestors{ + ChainId: testID[:], + RequestId: 12345, + Containers: compressibleContainers, + }, + }, + }, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "ancestors message with zstd compression", op: AncestorsOp, msg: &p2p.Message{ Message: &p2p.Message_Ancestors_{ @@ -412,7 +502,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -430,7 +520,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -447,12 +537,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "put message with compression", + desc: "put message with gzip compression", op: PutOp, msg: &p2p.Message{ Message: &p2p.Message_Put{ @@ -464,7 +554,24 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "put message with zstd compression", + op: PutOp, + msg: &p2p.Message{ + Message: &p2p.Message_Put{ + Put: &p2p.Put{ + ChainId: testID[:], + RequestId: 1, + Container: compressibleContainers[0], + EngineType: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + }, + }, + }, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -482,12 +589,30 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "push_query message with compression", + desc: "push_query message with gzip compression", + op: PushQueryOp, + msg: &p2p.Message{ + Message: &p2p.Message_PushQuery{ + PushQuery: &p2p.PushQuery{ + ChainId: testID[:], + RequestId: 1, + Deadline: 1, + Container: compressibleContainers[0], + EngineType: p2p.EngineType_ENGINE_TYPE_AVALANCHE, + }, + }, + }, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "push_query message with zstd compression", op: PushQueryOp, msg: &p2p.Message{ Message: &p2p.Message_PushQuery{ @@ -500,7 +625,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -518,7 +643,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -534,7 +659,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, @@ -551,12 +676,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "app_request message with compression", + desc: "app_request message with gzip compression", op: AppRequestOp, msg: &p2p.Message{ Message: &p2p.Message_AppRequest{ @@ -568,7 +693,24 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "app_request message with zstd compression", + op: AppRequestOp, + msg: &p2p.Message{ + Message: &p2p.Message_AppRequest{ + AppRequest: &p2p.AppRequest{ + ChainId: testID[:], + RequestId: 1, + Deadline: 1, + AppBytes: compressibleContainers[0], + }, + }, + }, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -584,12 +726,12 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "app_response message with compression", + desc: "app_response message with gzip compression", op: AppResponseOp, msg: &p2p.Message{ Message: &p2p.Message_AppResponse{ @@ -600,7 +742,23 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "app_response message with zstd compression", + op: AppResponseOp, + msg: &p2p.Message{ + Message: &p2p.Message_AppResponse{ + AppResponse: &p2p.AppResponse{ + ChainId: testID[:], + RequestId: 1, + AppBytes: compressibleContainers[0], + }, + }, + }, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -615,12 +773,27 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: false, + compressionType: compression.TypeNone, bypassThrottling: true, bytesSaved: false, }, { - desc: "app_gossip message with compression", + desc: "app_gossip message with gzip compression", + op: AppGossipOp, + msg: &p2p.Message{ + Message: &p2p.Message_AppGossip{ + AppGossip: &p2p.AppGossip{ + ChainId: testID[:], + AppBytes: compressibleContainers[0], + }, + }, + }, + compressionType: compression.TypeGzip, + bypassThrottling: true, + bytesSaved: true, + }, + { + desc: "app_gossip message with zstd compression", op: AppGossipOp, msg: &p2p.Message{ Message: &p2p.Message_AppGossip{ @@ -630,7 +803,7 @@ func TestMessage(t *testing.T) { }, }, }, - gzipCompress: true, + compressionType: compression.TypeZstd, bypassThrottling: true, bytesSaved: true, }, @@ -638,7 +811,7 @@ func TestMessage(t *testing.T) { for _, tv := range tests { require.True(t.Run(tv.desc, func(t2 *testing.T) { - encodedMsg, err := mb.createOutbound(tv.msg, tv.gzipCompress, tv.bypassThrottling) + encodedMsg, err := mb.createOutbound(tv.msg, tv.compressionType, tv.bypassThrottling) require.NoError(err) require.Equal(tv.bypassThrottling, encodedMsg.BypassThrottling()) @@ -660,6 +833,7 @@ func TestEmptyInboundMessage(t *testing.T) { require := require.New(t) mb, err := newMsgBuilder( + logging.NoLog{}, "test", prometheus.NewRegistry(), 5*time.Second, @@ -680,6 +854,7 @@ func TestNilInboundMessage(t *testing.T) { require := require.New(t) mb, err := newMsgBuilder( + logging.NoLog{}, "test", prometheus.NewRegistry(), 5*time.Second, diff --git a/message/outbound_msg_builder.go b/message/outbound_msg_builder.go index cabbfae44531..693120b10750 100644 --- a/message/outbound_msg_builder.go +++ b/message/outbound_msg_builder.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/proto/pb/p2p" + "github.com/ava-labs/avalanchego/utils/compression" "github.com/ava-labs/avalanchego/utils/ips" ) @@ -167,17 +168,17 @@ type OutboundMsgBuilder interface { } type outMsgBuilder struct { - compress bool // set to "true" if compression is enabled + compressionType compression.Type builder *msgBuilder } // Use "message.NewCreator" to import this function // since we do not expose "msgBuilder" yet -func newOutboundBuilder(enableCompression bool, builder *msgBuilder) OutboundMsgBuilder { +func newOutboundBuilder(compressionType compression.Type, builder *msgBuilder) OutboundMsgBuilder { return &outMsgBuilder{ - compress: enableCompression, - builder: builder, + compressionType: compressionType, + builder: builder, } } @@ -188,7 +189,7 @@ func (b *outMsgBuilder) Ping() (OutboundMessage, error) { Ping: &p2p.Ping{}, }, }, - false, + compression.TypeNone, false, ) } @@ -206,7 +207,7 @@ func (b *outMsgBuilder) Pong( }, }, }, - false, + compression.TypeNone, false, ) } @@ -237,7 +238,7 @@ func (b *outMsgBuilder) Version( }, }, }, - false, + compression.TypeNone, true, ) } @@ -262,7 +263,7 @@ func (b *outMsgBuilder) PeerList(peers []ips.ClaimedIPPort, bypassThrottling boo }, }, }, - b.compress, + b.compressionType, bypassThrottling, ) } @@ -276,7 +277,7 @@ func (b *outMsgBuilder) PeerListAck(peerAcks []*p2p.PeerAck) (OutboundMessage, e }, }, }, - false, + compression.TypeNone, false, ) } @@ -296,7 +297,7 @@ func (b *outMsgBuilder) GetStateSummaryFrontier( }, }, }, - false, + compression.TypeNone, false, ) } @@ -316,7 +317,7 @@ func (b *outMsgBuilder) StateSummaryFrontier( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -338,7 +339,7 @@ func (b *outMsgBuilder) GetAcceptedStateSummary( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -360,7 +361,7 @@ func (b *outMsgBuilder) AcceptedStateSummary( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -382,7 +383,7 @@ func (b *outMsgBuilder) GetAcceptedFrontier( }, }, }, - false, + compression.TypeNone, false, ) } @@ -404,7 +405,7 @@ func (b *outMsgBuilder) AcceptedFrontier( }, }, }, - false, + compression.TypeNone, false, ) } @@ -430,7 +431,7 @@ func (b *outMsgBuilder) GetAccepted( }, }, }, - false, + compression.TypeNone, false, ) } @@ -452,7 +453,7 @@ func (b *outMsgBuilder) Accepted( }, }, }, - false, + compression.TypeNone, false, ) } @@ -476,7 +477,7 @@ func (b *outMsgBuilder) GetAncestors( }, }, }, - false, + compression.TypeNone, false, ) } @@ -496,7 +497,7 @@ func (b *outMsgBuilder) Ancestors( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -520,7 +521,7 @@ func (b *outMsgBuilder) Get( }, }, }, - false, + compression.TypeNone, false, ) } @@ -542,7 +543,7 @@ func (b *outMsgBuilder) Put( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -566,7 +567,7 @@ func (b *outMsgBuilder) PushQuery( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -590,7 +591,7 @@ func (b *outMsgBuilder) PullQuery( }, }, }, - false, + compression.TypeNone, false, ) } @@ -616,7 +617,7 @@ func (b *outMsgBuilder) Chits( }, }, }, - false, + compression.TypeNone, false, ) } @@ -638,7 +639,7 @@ func (b *outMsgBuilder) AppRequest( }, }, }, - b.compress, + b.compressionType, false, ) } @@ -654,7 +655,7 @@ func (b *outMsgBuilder) AppResponse(chainID ids.ID, requestID uint32, msg []byte }, }, }, - b.compress, + b.compressionType, false, ) } @@ -669,7 +670,7 @@ func (b *outMsgBuilder) AppGossip(chainID ids.ID, msg []byte) (OutboundMessage, }, }, }, - b.compress, + b.compressionType, false, ) } diff --git a/message/outbound_msg_builder_test.go b/message/outbound_msg_builder_test.go index 1fadac03b8a7..50f273bf4b13 100644 --- a/message/outbound_msg_builder_test.go +++ b/message/outbound_msg_builder_test.go @@ -12,28 +12,37 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/compression" + "github.com/ava-labs/avalanchego/utils/logging" ) func Test_newOutboundBuilder(t *testing.T) { t.Parallel() - require := require.New(t) mb, err := newMsgBuilder( + logging.NoLog{}, "test", prometheus.NewRegistry(), 10*time.Second, ) - require.NoError(err) - - builder := newOutboundBuilder(true /*compress*/, mb) - - outMsg, err := builder.GetAcceptedStateSummary( - ids.GenerateTestID(), - 12345, - time.Hour, - []uint64{1000, 2000}, - ) - require.NoError(err) - - t.Logf("outbound message built with size %d", len(outMsg.Bytes())) + require.NoError(t, err) + + for _, compressionType := range []compression.Type{ + compression.TypeNone, + compression.TypeGzip, + compression.TypeZstd, + } { + t.Run(compressionType.String(), func(t *testing.T) { + builder := newOutboundBuilder(compressionType, mb) + + outMsg, err := builder.GetAcceptedStateSummary( + ids.GenerateTestID(), + 12345, + time.Hour, + []uint64{1000, 2000}, + ) + require.NoError(t, err) + t.Logf("outbound message with compression type %s built message with size %d", compressionType, len(outMsg.Bytes())) + }) + } } diff --git a/network/config.go b/network/config.go index 0cd95abd728a..11191b836067 100644 --- a/network/config.go +++ b/network/config.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/snow/networking/tracker" "github.com/ava-labs/avalanchego/snow/uptime" "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/compression" "github.com/ava-labs/avalanchego/utils/ips" "github.com/ava-labs/avalanchego/utils/set" ) @@ -125,9 +126,9 @@ type Config struct { PingFrequency time.Duration `json:"pingFrequency"` AllowPrivateIPs bool `json:"allowPrivateIPs"` - // CompressionEnabled will compress available outbound messages when set to - // true. - CompressionEnabled bool `json:"compressionEnabled"` + // The compression type to use when compressing outbound messages. + // Assumes all peers support this compression type. + CompressionType compression.Type `json:"compressionType"` // TLSKey is this node's TLS key that is used to sign IPs. TLSKey crypto.Signer `json:"-"` diff --git a/network/network_test.go b/network/network_test.go index ccb60425c650..63efee693d3c 100644 --- a/network/network_test.go +++ b/network/network_test.go @@ -110,7 +110,7 @@ var ( PingFrequency: constants.DefaultPingFrequency, AllowPrivateIPs: true, - CompressionEnabled: true, + CompressionType: constants.DefaultNetworkCompressionType, UptimeCalculator: uptime.NewManager(uptime.NewTestState()), UptimeMetricFreq: 30 * time.Second, @@ -183,9 +183,10 @@ func newMessageCreator(t *testing.T) message.Creator { t.Helper() mc, err := message.NewCreator( + logging.NoLog{}, prometheus.NewRegistry(), "", - true, + constants.DefaultNetworkCompressionType, 10*time.Second, ) require.NoError(t, err) diff --git a/network/peer/peer_test.go b/network/peer/peer_test.go index 2a1ae990323e..653a0c616e26 100644 --- a/network/peer/peer_test.go +++ b/network/peer/peer_test.go @@ -49,9 +49,10 @@ func newMessageCreator(t *testing.T) message.Creator { t.Helper() mc, err := message.NewCreator( + logging.NoLog{}, prometheus.NewRegistry(), "", - true, + constants.DefaultNetworkCompressionType, 10*time.Second, ) require.NoError(t, err) diff --git a/network/peer/test_peer.go b/network/peer/test_peer.go index d1d58b37ddca..d813a16a5637 100644 --- a/network/peer/test_peer.go +++ b/network/peer/test_peer.go @@ -70,9 +70,10 @@ func StartTestPeer( } mc, err := message.NewCreator( + logging.NoLog{}, prometheus.NewRegistry(), "", - true, + constants.DefaultNetworkCompressionType, 10*time.Second, ) if err != nil { diff --git a/network/test_network.go b/network/test_network.go index e2ab96a2d154..296108b714d9 100644 --- a/network/test_network.go +++ b/network/test_network.go @@ -79,9 +79,10 @@ func NewTestNetwork( ) (Network, error) { metrics := prometheus.NewRegistry() msgCreator, err := message.NewCreator( + logging.NoLog{}, metrics, "", - constants.DefaultNetworkCompressionEnabled, + constants.DefaultNetworkCompressionType, constants.DefaultNetworkMaximumInboundTimeout, ) if err != nil { @@ -163,7 +164,7 @@ func NewTestNetwork( }, MaxClockDifference: constants.DefaultNetworkMaxClockDifference, - CompressionEnabled: constants.DefaultNetworkCompressionEnabled, + CompressionType: constants.DefaultNetworkCompressionType, PingFrequency: constants.DefaultPingFrequency, AllowPrivateIPs: constants.DefaultNetworkAllowPrivateIPs, UptimeMetricFreq: constants.DefaultUptimeMetricFreq, diff --git a/node/node.go b/node/node.go index da35b15dca26..08868d28c6cc 100644 --- a/node/node.go +++ b/node/node.go @@ -1303,9 +1303,10 @@ func (n *Node) Initialize( // message.Creator currently record metrics under network namespace n.networkNamespace = "network" n.msgCreator, err = message.NewCreator( + n.Log, n.MetricsRegisterer, n.networkNamespace, - n.Config.NetworkConfig.CompressionEnabled, + constants.DefaultNetworkCompressionType, n.Config.NetworkConfig.MaximumInboundMessageTimeout, ) if err != nil { diff --git a/proto/p2p/p2p.proto b/proto/p2p/p2p.proto index 1e85f754e632..d6524a182605 100644 --- a/proto/p2p/p2p.proto +++ b/proto/p2p/p2p.proto @@ -17,8 +17,12 @@ message Message { // This field is only set if the message type supports compression. bytes compressed_gzip = 1; + // zstd-compressed bytes of a "p2p.Message" whose "oneof" "message" field is + // NOT compressed_* BUT one of the message types (e.g. ping, pong, etc.). + // This field is only set if the message type supports compression. + bytes compressed_zstd = 2; + // Fields lower than 10 are reserved for other compression algorithms. - // TODO: support COMPRESS_ZSTD // TODO: support COMPRESS_SNAPPY // Network messages: diff --git a/proto/pb/p2p/p2p.pb.go b/proto/pb/p2p/p2p.pb.go index 10c8fc0a5dae..ff5127f42e55 100644 --- a/proto/pb/p2p/p2p.pb.go +++ b/proto/pb/p2p/p2p.pb.go @@ -83,6 +83,7 @@ type Message struct { // Types that are assignable to Message: // // *Message_CompressedGzip + // *Message_CompressedZstd // *Message_Ping // *Message_Pong // *Message_Version @@ -155,6 +156,13 @@ func (x *Message) GetCompressedGzip() []byte { return nil } +func (x *Message) GetCompressedZstd() []byte { + if x, ok := x.GetMessage().(*Message_CompressedZstd); ok { + return x.CompressedZstd + } + return nil +} + func (x *Message) GetPing() *Ping { if x, ok := x.GetMessage().(*Message_Ping); ok { return x.Ping @@ -327,6 +335,13 @@ type Message_CompressedGzip struct { CompressedGzip []byte `protobuf:"bytes,1,opt,name=compressed_gzip,json=compressedGzip,proto3,oneof"` } +type Message_CompressedZstd struct { + // zstd-compressed bytes of a "p2p.Message" whose "oneof" "message" field is + // NOT compressed_* BUT one of the message types (e.g. ping, pong, etc.). + // This field is only set if the message type supports compression. + CompressedZstd []byte `protobuf:"bytes,2,opt,name=compressed_zstd,json=compressedZstd,proto3,oneof"` +} + type Message_Ping struct { // Network messages: Ping *Ping `protobuf:"bytes,11,opt,name=ping,proto3,oneof"` @@ -426,6 +441,8 @@ type Message_PeerListAck struct { func (*Message_CompressedGzip) isMessage_Message() {} +func (*Message_CompressedZstd) isMessage_Message() {} + func (*Message_Ping) isMessage_Message() {} func (*Message_Pong) isMessage_Message() {} @@ -2315,308 +2332,311 @@ var File_p2p_p2p_proto protoreflect.FileDescriptor var file_p2p_p2p_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x70, 0x32, 0x70, 0x2f, 0x70, 0x32, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x03, 0x70, 0x32, 0x70, 0x22, 0xb3, 0x0a, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x03, 0x70, 0x32, 0x70, 0x22, 0xde, 0x0a, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x7a, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x47, 0x7a, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x04, 0x70, - 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x32, 0x70, 0x2e, - 0x50, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x04, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x04, - 0x70, 0x6f, 0x6e, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x32, 0x70, - 0x2e, 0x50, 0x6f, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6f, 0x6e, 0x67, 0x12, 0x28, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, - 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x32, 0x70, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x08, 0x70, 0x65, 0x65, - 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x1a, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, - 0x69, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x32, 0x70, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, - 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x17, 0x67, 0x65, 0x74, 0x53, 0x74, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x47, 0x7a, 0x69, 0x70, 0x12, 0x29, 0x0a, 0x0f, 0x63, + 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x7a, 0x73, 0x74, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x64, 0x5a, 0x73, 0x74, 0x64, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x48, + 0x00, 0x52, 0x04, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x6f, 0x6e, 0x67, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x6f, 0x6e, 0x67, + 0x48, 0x00, 0x52, 0x04, 0x70, 0x6f, 0x6e, 0x67, 0x12, 0x28, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x32, 0x70, 0x2e, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x5b, 0x0a, 0x1a, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x0f, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, - 0x65, 0x72, 0x12, 0x51, 0x0a, 0x16, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, - 0x14, 0x73, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, - 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x5b, 0x0a, 0x1a, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x32, 0x70, 0x2e, - 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x00, 0x52, 0x17, 0x67, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x12, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, - 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x00, 0x52, - 0x14, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x4e, 0x0a, 0x15, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x48, 0x00, - 0x52, 0x13, 0x67, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, - 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, - 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, - 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0c, 0x67, - 0x65, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x67, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x16, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, - 0x38, 0x0a, 0x0d, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, - 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x67, 0x65, 0x74, - 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x09, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, - 0x32, 0x70, 0x2e, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x48, 0x00, 0x52, 0x09, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x03, 0x67, 0x65, 0x74, - 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, - 0x48, 0x00, 0x52, 0x03, 0x67, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x03, 0x70, 0x75, 0x74, 0x18, 0x1a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x75, 0x74, 0x48, 0x00, - 0x52, 0x03, 0x70, 0x75, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, 0x2e, - 0x50, 0x75, 0x73, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x09, 0x70, 0x75, 0x73, - 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x6c, 0x6c, 0x5f, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, - 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x09, 0x70, 0x75, - 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x22, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x74, 0x73, - 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x43, 0x68, 0x69, - 0x74, 0x73, 0x48, 0x00, 0x52, 0x05, 0x63, 0x68, 0x69, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x61, - 0x70, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x35, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, - 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x70, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x5f, 0x67, 0x6f, - 0x73, 0x73, 0x69, 0x70, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, - 0x2e, 0x41, 0x70, 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x48, 0x00, 0x52, 0x09, 0x61, 0x70, - 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x6b, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x6b, - 0x48, 0x00, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x6b, 0x42, - 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x50, 0x69, - 0x6e, 0x67, 0x22, 0x43, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x55, 0x70, 0x74, 0x69, - 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x12, - 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x58, 0x0a, 0x04, 0x50, 0x6f, 0x6e, 0x67, 0x12, - 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0e, 0x73, 0x75, 0x62, 0x6e, 0x65, - 0x74, 0x5f, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x55, 0x70, 0x74, 0x69, - 0x6d, 0x65, 0x52, 0x0d, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x22, 0xf5, 0x01, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, - 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, - 0x6d, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, - 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x17, - 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x06, 0x69, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x79, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x79, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x79, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0d, 0x6d, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x10, - 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, - 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x6e, - 0x65, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x6b, - 0x65, 0x64, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x0d, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x78, - 0x35, 0x30, 0x39, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x78, 0x35, 0x30, 0x39, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, - 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x08, 0x50, 0x65, 0x65, - 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, - 0x5f, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x70, 0x50, - 0x6f, 0x72, 0x74, 0x52, 0x0e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x70, 0x50, 0x6f, - 0x72, 0x74, 0x73, 0x22, 0x3c, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x12, 0x13, - 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, - 0x78, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x22, 0x3e, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x6b, - 0x12, 0x29, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x41, 0x63, - 0x6b, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, - 0x02, 0x22, 0x6f, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, - 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, - 0x6e, 0x65, 0x22, 0x6a, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x89, - 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x07, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x22, 0x71, 0x0a, 0x14, 0x41, 0x63, + 0x65, 0x72, 0x48, 0x00, 0x52, 0x17, 0x67, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x51, 0x0a, + 0x16, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x66, + 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x70, 0x32, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x14, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, + 0x12, 0x5b, 0x0a, 0x1a, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x11, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, - 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, - 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x0a, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x49, 0x64, 0x73, 0x22, 0x9d, 0x01, - 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, + 0x72, 0x79, 0x48, 0x00, 0x52, 0x17, 0x67, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, + 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x51, 0x0a, + 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x70, 0x32, 0x70, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x00, 0x52, 0x14, 0x61, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x12, 0x4e, 0x0a, 0x15, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, + 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x13, 0x67, 0x65, 0x74, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, + 0x12, 0x44, 0x0a, 0x11, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, + 0x6e, 0x74, 0x69, 0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x32, + 0x70, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, + 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, + 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0c, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, + 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x48, 0x00, + 0x52, 0x0b, 0x67, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x2b, 0x0a, + 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0d, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x48, 0x00, + 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0d, 0x67, 0x65, + 0x74, 0x5f, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x67, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x09, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, + 0x73, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x6e, + 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x48, 0x00, 0x52, 0x09, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x03, 0x67, 0x65, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x00, 0x52, 0x03, 0x67, + 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x03, 0x70, 0x75, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x08, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x75, 0x74, 0x48, 0x00, 0x52, 0x03, 0x70, 0x75, 0x74, + 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x1b, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x09, 0x70, 0x75, 0x73, 0x68, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x6c, 0x6c, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, + 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x75, 0x6c, 0x6c, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x09, 0x70, 0x75, 0x6c, 0x6c, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x12, 0x22, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x74, 0x73, 0x18, 0x1d, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x43, 0x68, 0x69, 0x74, 0x73, 0x48, 0x00, 0x52, + 0x05, 0x63, 0x68, 0x69, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x32, + 0x70, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0a, + 0x61, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x61, 0x70, + 0x70, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x5f, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x18, + 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x41, 0x70, 0x70, 0x47, + 0x6f, 0x73, 0x73, 0x69, 0x70, 0x48, 0x00, 0x52, 0x09, 0x61, 0x70, 0x70, 0x47, 0x6f, 0x73, 0x73, + 0x69, 0x70, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, + 0x61, 0x63, 0x6b, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x32, 0x70, 0x2e, + 0x50, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, + 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x22, 0x43, 0x0a, + 0x0c, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, + 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, + 0x6d, 0x65, 0x22, 0x58, 0x0a, 0x04, 0x50, 0x6f, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, + 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0e, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x75, 0x70, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x32, 0x70, + 0x2e, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x0d, 0x73, + 0x75, 0x62, 0x6e, 0x65, 0x74, 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x22, 0xf5, 0x01, 0x0a, + 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x79, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x79, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, + 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x79, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x74, + 0x72, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x18, 0x08, + 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x75, 0x62, + 0x6e, 0x65, 0x74, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x0d, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, + 0x49, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x78, 0x35, 0x30, 0x39, 0x5f, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0f, 0x78, 0x35, 0x30, 0x39, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x69, 0x70, 0x50, + 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, + 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x74, 0x78, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x3c, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x69, 0x70, 0x5f, 0x70, + 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x32, 0x70, + 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0e, + 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x49, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x3c, + 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3e, 0x0a, 0x0b, + 0x50, 0x65, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x6b, 0x12, 0x29, 0x0a, 0x09, 0x70, + 0x65, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x52, 0x08, 0x70, 0x65, + 0x65, 0x72, 0x41, 0x63, 0x6b, 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x6f, 0x0a, 0x17, + 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, + 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, + 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x6a, 0x0a, + 0x14, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, - 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x30, 0x0a, 0x0b, 0x65, - 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x77, 0x0a, - 0x10, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, - 0x72, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, - 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xba, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, - 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, - 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x23, 0x0a, 0x0d, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, - 0x73, 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, - 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x22, 0x6f, 0x0a, 0x08, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, - 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x4a, 0x04, - 0x08, 0x04, 0x10, 0x05, 0x22, 0xb9, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, - 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x89, 0x01, 0x0a, 0x17, 0x47, 0x65, + 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, - 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x6b, 0x0a, 0x09, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x19, 0x0a, + 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, 0x68, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x73, 0x22, 0x71, 0x0a, 0x14, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, + 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xb0, 0x01, - 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, - 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, - 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x8f, 0x01, 0x0a, 0x03, 0x50, 0x75, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x49, 0x64, 0x73, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, + 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x77, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, + 0x05, 0x22, 0xba, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, + 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, + 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x30, 0x0a, 0x0b, + 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x6f, + 0x0a, 0x08, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, + 0xb9, 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, + 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x6b, 0x0a, 0x09, 0x41, + 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x09, 0x50, 0x75, 0x73, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xb0, 0x01, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, - 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, - 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x09, 0x50, 0x75, 0x6c, 0x6c, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, + 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x03, + 0x50, 0x75, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, + 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x0b, 0x65, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb1, 0x01, + 0x0a, 0x09, 0x50, 0x75, 0x73, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x09, 0x50, 0x75, 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, + 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, + 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, + 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, + 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, + 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb5, 0x01, 0x0a, 0x05, 0x43, + 0x68, 0x69, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x30, 0x0a, - 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, - 0xb5, 0x01, 0x0a, 0x05, 0x43, 0x68, 0x69, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x15, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x14, 0x61, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, - 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x7f, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, - 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, - 0x70, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, - 0x61, 0x70, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, - 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x70, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x43, - 0x0a, 0x09, 0x41, 0x70, 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x70, 0x70, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x2a, 0x5d, 0x0a, 0x0a, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, - 0x0a, 0x15, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x56, - 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x48, 0x45, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x4e, 0x47, - 0x49, 0x4e, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4e, 0x4f, 0x57, 0x4d, 0x41, 0x4e, - 0x10, 0x02, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x68, 0x65, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x70, - 0x32, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x36, + 0x0a, 0x17, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x15, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x14, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x4a, 0x04, 0x08, 0x05, + 0x10, 0x06, 0x22, 0x7f, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, + 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x70, 0x70, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, + 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, + 0x61, 0x70, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x08, 0x61, 0x70, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x43, 0x0a, 0x09, 0x41, 0x70, 0x70, + 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x70, 0x70, 0x42, 0x79, 0x74, 0x65, 0x73, 0x2a, 0x5d, + 0x0a, 0x0a, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, + 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x4e, 0x47, + 0x49, 0x4e, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x56, 0x41, 0x4c, 0x41, 0x4e, 0x43, + 0x48, 0x45, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4e, 0x4f, 0x57, 0x4d, 0x41, 0x4e, 0x10, 0x02, 0x42, 0x2e, 0x5a, + 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x67, 0x6f, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x70, 0x32, 0x70, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3037,6 +3057,7 @@ func file_p2p_p2p_proto_init() { } file_p2p_p2p_proto_msgTypes[0].OneofWrappers = []interface{}{ (*Message_CompressedGzip)(nil), + (*Message_CompressedZstd)(nil), (*Message_Ping)(nil), (*Message_Pong)(nil), (*Message_Version)(nil), diff --git a/snow/networking/sender/sender_test.go b/snow/networking/sender/sender_test.go index 0625e32f55d8..db20b12b3c44 100644 --- a/snow/networking/sender/sender_test.go +++ b/snow/networking/sender/sender_test.go @@ -28,6 +28,7 @@ import ( "github.com/ava-labs/avalanchego/snow/networking/tracker" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/subnets" + "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math/meter" "github.com/ava-labs/avalanchego/utils/resource" @@ -70,9 +71,10 @@ func TestTimeout(t *testing.T) { metrics := prometheus.NewRegistry() mc, err := message.NewCreator( + logging.NoLog{}, metrics, "dummyNamespace", - true, + constants.DefaultNetworkCompressionType, 10*time.Second, ) require.NoError(err) @@ -341,9 +343,10 @@ func TestReliableMessages(t *testing.T) { metrics := prometheus.NewRegistry() mc, err := message.NewCreator( + logging.NoLog{}, metrics, "dummyNamespace", - true, + constants.DefaultNetworkCompressionType, 10*time.Second, ) require.NoError(t, err) @@ -488,9 +491,10 @@ func TestReliableMessagesToMyself(t *testing.T) { metrics := prometheus.NewRegistry() mc, err := message.NewCreator( + logging.NoLog{}, metrics, "dummyNamespace", - true, + constants.DefaultNetworkCompressionType, 10*time.Second, ) require.NoError(t, err) diff --git a/utils/compression/compressor_test.go b/utils/compression/compressor_test.go new file mode 100644 index 000000000000..4ba60dd90d48 --- /dev/null +++ b/utils/compression/compressor_test.go @@ -0,0 +1,146 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package compression + +import ( + "math" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/units" +) + +const maxMessageSize = 2 * units.MiB // Max message size. Can't import due to cycle. + +var newCompressorFuncs = map[Type]func(maxSize int64) (Compressor, error){ + TypeNone: func(int64) (Compressor, error) { //nolint:unparam // an error is needed to be returned to compile + return NewNoCompressor(), nil + }, + TypeGzip: NewGzipCompressor, + TypeZstd: NewZstdCompressor, +} + +func TestCompressDecompress(t *testing.T) { + for compressionType, newCompressorFunc := range newCompressorFuncs { + t.Run(compressionType.String(), func(t *testing.T) { + data := utils.RandomBytes(4096) + data2 := utils.RandomBytes(4096) + + compressor, err := newCompressorFunc(maxMessageSize) + require.NoError(t, err) + + dataCompressed, err := compressor.Compress(data) + require.NoError(t, err) + + data2Compressed, err := compressor.Compress(data2) + require.NoError(t, err) + + dataDecompressed, err := compressor.Decompress(dataCompressed) + require.NoError(t, err) + require.EqualValues(t, data, dataDecompressed) + + data2Decompressed, err := compressor.Decompress(data2Compressed) + require.NoError(t, err) + require.EqualValues(t, data2, data2Decompressed) + + dataDecompressed, err = compressor.Decompress(dataCompressed) + require.NoError(t, err) + require.EqualValues(t, data, dataDecompressed) + + maxMessage := utils.RandomBytes(maxMessageSize) + maxMessageCompressed, err := compressor.Compress(maxMessage) + require.NoError(t, err) + + maxMessageDecompressed, err := compressor.Decompress(maxMessageCompressed) + require.NoError(t, err) + + require.EqualValues(t, maxMessage, maxMessageDecompressed) + }) + } +} + +func TestSizeLimiting(t *testing.T) { + for compressionType, compressorFunc := range newCompressorFuncs { + if compressionType == TypeNone { + continue + } + t.Run(compressionType.String(), func(t *testing.T) { + compressor, err := compressorFunc(maxMessageSize) + require.NoError(t, err) + + data := make([]byte, maxMessageSize+1) + _, err = compressor.Compress(data) // should be too large + require.Error(t, err) + + compressor2, err := compressorFunc(2 * maxMessageSize) + require.NoError(t, err) + + dataCompressed, err := compressor2.Compress(data) + require.NoError(t, err) + + _, err = compressor.Decompress(dataCompressed) // should be too large + require.Error(t, err) + }) + } +} + +// Attempts to create a compressor with math.MaxInt64 +// which leads to undefined decompress behavior due to integer overflow +// in limit reader creation. +func TestNewCompressorWithInvalidLimit(t *testing.T) { + for compressionType, compressorFunc := range newCompressorFuncs { + if compressionType == TypeNone { + continue + } + t.Run(compressionType.String(), func(t *testing.T) { + require := require.New(t) + _, err := compressorFunc(math.MaxInt64) + require.ErrorIs(err, ErrInvalidMaxSizeCompressor) + }) + } +} + +func FuzzGzipCompressor(f *testing.F) { + fuzzHelper(f, TypeGzip) +} + +func FuzzZstdCompressor(f *testing.F) { + fuzzHelper(f, TypeZstd) +} + +func fuzzHelper(f *testing.F, compressionType Type) { + var ( + compressor Compressor + err error + ) + switch compressionType { + case TypeGzip: + compressor, err = NewGzipCompressor(maxMessageSize) + require.NoError(f, err) + case TypeZstd: + compressor, err = NewZstdCompressor(maxMessageSize) + require.NoError(f, err) + default: + f.Fatal("Unknown compression type") + } + + f.Fuzz(func(t *testing.T, data []byte) { + require := require.New(t) + + if len(data) > maxMessageSize { + _, err := compressor.Compress(data) + require.Error(err) + } + + compressed, err := compressor.Compress(data) + require.NoError(err) + + decompressed, err := compressor.Decompress(compressed) + require.NoError(err) + + require.Equal(data, decompressed) + }) +} diff --git a/utils/compression/gzip_compressor.go b/utils/compression/gzip_compressor.go index a603d036a08b..036cd8d4576b 100644 --- a/utils/compression/gzip_compressor.go +++ b/utils/compression/gzip_compressor.go @@ -18,7 +18,9 @@ import ( var ( _ Compressor = (*gzipCompressor)(nil) - ErrInvalidMaxSizeGzipCompressor = errors.New("invalid gzip compressor max size") + ErrInvalidMaxSizeCompressor = errors.New("invalid gzip compressor max size") + ErrDecompressedMsgTooLarge = errors.New("decompressed msg too large") + ErrMsgTooLarge = errors.New("msg too large to be compressed") ) type gzipCompressor struct { @@ -36,7 +38,7 @@ type gzipCompressor struct { // Compress [msg] and returns the compressed bytes. func (g *gzipCompressor) Compress(msg []byte) ([]byte, error) { if int64(len(msg)) > g.maxSize { - return nil, fmt.Errorf("msg length (%d) > maximum msg length (%d)", len(msg), g.maxSize) + return nil, fmt.Errorf("%w: (%d) > (%d)", ErrMsgTooLarge, len(msg), g.maxSize) } g.lock.Lock() @@ -76,7 +78,7 @@ func (g *gzipCompressor) Decompress(msg []byte) ([]byte, error) { return nil, err } if int64(len(decompressed)) > g.maxSize { - return nil, fmt.Errorf("msg length > maximum msg length (%d)", g.maxSize) + return nil, fmt.Errorf("%w: (%d) > (%d)", ErrDecompressedMsgTooLarge, len(decompressed), g.maxSize) } return decompressed, g.gzipReader.Close() } @@ -88,7 +90,7 @@ func NewGzipCompressor(maxSize int64) (Compressor, error) { // if the max size + 1 overflows, "io.LimitReader" reads nothing // returning 0 byte for the decompress call // require max size 2*units.MiB { - t.SkipNow() - } - - compressor, err := NewGzipCompressor(2 * units.MiB) - require.NoError(err) - - compressed, err := compressor.Compress(data) - require.NoError(err) - - decompressed, err := compressor.Decompress(compressed) - require.NoError(err) - - require.Equal(data, decompressed) - }) -} diff --git a/utils/compression/type.go b/utils/compression/type.go new file mode 100644 index 000000000000..fd58a21f70fa --- /dev/null +++ b/utils/compression/type.go @@ -0,0 +1,59 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package compression + +import ( + "errors" + "strings" +) + +var errUnknownCompressionType = errors.New("unknown compression type") + +type Type byte + +const ( + TypeNone Type = iota + 1 + TypeGzip + TypeZstd +) + +func (t Type) String() string { + switch t { + case TypeNone: + return "none" + case TypeGzip: + return "gzip" + case TypeZstd: + return "zstd" + default: + return "unknown" + } +} + +func TypeFromString(s string) (Type, error) { + switch s { + case TypeNone.String(): + return TypeNone, nil + case TypeGzip.String(): + return TypeGzip, nil + case TypeZstd.String(): + return TypeZstd, nil + default: + return TypeNone, errUnknownCompressionType + } +} + +func (t Type) MarshalJSON() ([]byte, error) { + var b strings.Builder + if _, err := b.WriteString(`"`); err != nil { + return nil, err + } + if _, err := b.WriteString(t.String()); err != nil { + return nil, err + } + if _, err := b.WriteString(`"`); err != nil { + return nil, err + } + return []byte(b.String()), nil +} diff --git a/utils/compression/type_test.go b/utils/compression/type_test.go new file mode 100644 index 000000000000..aa9a47f3ad96 --- /dev/null +++ b/utils/compression/type_test.go @@ -0,0 +1,56 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package compression + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestTypeString(t *testing.T) { + for _, compressionType := range []Type{TypeNone, TypeGzip, TypeZstd} { + s := compressionType.String() + parsedType, err := TypeFromString(s) + require.NoError(t, err) + require.Equal(t, compressionType, parsedType) + } + + _, err := TypeFromString("unknown") + require.Error(t, err) +} + +func TestTypeMarshalJSON(t *testing.T) { + type test struct { + Type Type + expected string + } + + tests := []test{ + { + Type: TypeNone, + expected: `"none"`, + }, + { + Type: TypeGzip, + expected: `"gzip"`, + }, + { + Type: TypeZstd, + expected: `"zstd"`, + }, + { + Type: Type(0), + expected: `"unknown"`, + }, + } + + for _, tt := range tests { + t.Run(tt.Type.String(), func(t *testing.T) { + b, err := tt.Type.MarshalJSON() + require.NoError(t, err) + require.Equal(t, tt.expected, string(b)) + }) + } +} diff --git a/utils/compression/zstd_compressor.go b/utils/compression/zstd_compressor.go new file mode 100644 index 000000000000..eafc1071845f --- /dev/null +++ b/utils/compression/zstd_compressor.go @@ -0,0 +1,58 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package compression + +import ( + "bytes" + "fmt" + "io" + "math" + + "github.com/DataDog/zstd" +) + +var _ Compressor = (*zstdCompressor)(nil) + +func NewZstdCompressor(maxSize int64) (Compressor, error) { + if maxSize == math.MaxInt64 { + // "Decompress" creates "io.LimitReader" with max size + 1: + // if the max size + 1 overflows, "io.LimitReader" reads nothing + // returning 0 byte for the decompress call + // require max size < math.MaxInt64 to prevent int64 overflows + return nil, ErrInvalidMaxSizeCompressor + } + + return &zstdCompressor{ + maxSize: maxSize, + }, nil +} + +type zstdCompressor struct { + maxSize int64 +} + +func (z *zstdCompressor) Compress(msg []byte) ([]byte, error) { + if int64(len(msg)) > z.maxSize { + return nil, fmt.Errorf("%w: (%d) > (%d)", ErrMsgTooLarge, len(msg), z.maxSize) + } + return zstd.Compress(nil, msg) +} + +func (z *zstdCompressor) Decompress(msg []byte) ([]byte, error) { + reader := zstd.NewReader(bytes.NewReader(msg)) + defer reader.Close() + + // We allow [io.LimitReader] to read up to [z.maxSize + 1] bytes, so that if + // the decompressed payload is greater than the maximum size, this function + // will return the appropriate error instead of an incomplete byte slice. + limitReader := io.LimitReader(reader, z.maxSize+1) + decompressed, err := io.ReadAll(limitReader) + if err != nil { + return nil, err + } + if int64(len(decompressed)) > z.maxSize { + return nil, fmt.Errorf("%w: (%d) > (%d)", ErrDecompressedMsgTooLarge, len(decompressed), z.maxSize) + } + return decompressed, nil +} diff --git a/utils/constants/networking.go b/utils/constants/networking.go index 9067fecb4791..b958e2c40889 100644 --- a/utils/constants/networking.go +++ b/utils/constants/networking.go @@ -7,6 +7,7 @@ import ( "math" "time" + "github.com/ava-labs/avalanchego/utils/compression" "github.com/ava-labs/avalanchego/utils/units" ) @@ -54,7 +55,8 @@ const ( DefaultNetworkTimeoutCoefficient = 2 DefaultNetworkReadHandshakeTimeout = 15 * time.Second - DefaultNetworkCompressionEnabled = true + DefaultNetworkCompressionEnabled = true // TODO remove when NetworkCompressionEnabledKey is removed + DefaultNetworkCompressionType = compression.TypeGzip DefaultNetworkMaxClockDifference = time.Minute DefaultNetworkAllowPrivateIPs = true DefaultNetworkRequireValidatorToConnect = false diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 311ee823f33c..f7b679d9a63e 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -1721,7 +1721,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { chainRouter := &router.ChainRouter{} metrics := prometheus.NewRegistry() - mc, err := message.NewCreator(metrics, "dummyNamespace", true, 10*time.Second) + mc, err := message.NewCreator(logging.NoLog{}, metrics, "dummyNamespace", constants.DefaultNetworkCompressionType, 10*time.Second) require.NoError(err) err = chainRouter.Initialize(