From dde076d626a575ff810b51968211c1da1d57f876 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 4 Jun 2025 21:17:36 -0700 Subject: [PATCH 01/18] add simplex pkg and bls structs --- simplex/bls.go | 127 ++++++++++++++++++++++++++++++++++++++++++ simplex/bls_test.go | 133 ++++++++++++++++++++++++++++++++++++++++++++ simplex/config.go | 33 +++++++++++ 3 files changed, 293 insertions(+) create mode 100644 simplex/bls.go create mode 100644 simplex/bls_test.go create mode 100644 simplex/config.go diff --git a/simplex/bls.go b/simplex/bls.go new file mode 100644 index 000000000000..7fa125d81434 --- /dev/null +++ b/simplex/bls.go @@ -0,0 +1,127 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "encoding/asn1" + "errors" + "fmt" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/simplex" +) + +var ( + errSignatureVerificationFailed = errors.New("signature verification failed") + errSignerNotFound = errors.New("signer not found in the membership set") +) + +var _ simplex.Signer = (*BLSSigner)(nil) + +type SignFunc func(msg []byte) (*bls.Signature, error) + +// BLSSigner signs messages encoded with the provided ChainID and NetworkID +// using the SignBLS function. +type BLSSigner struct { + chainID ids.ID + subnetID ids.ID + // signBLS is passed in because we support both software and hardware BLS signing. + signBLS SignFunc + nodeID ids.NodeID +} + +type BLSVerifier struct { + nodeID2PK map[ids.NodeID]bls.PublicKey + subnetID ids.ID + chainID ids.ID +} + +func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier) { + return BLSSigner{ + chainID: config.Ctx.ChainID, + subnetID: config.Ctx.SubnetID, + nodeID: config.Ctx.NodeID, + signBLS: config.SignBLS, + }, createVerifier(config) +} + +// Sign returns a signature on the given message using BLS signature scheme. +// It encodes the message to sign with the chain ID, and subnet ID, +func (s *BLSSigner) Sign(message []byte) ([]byte, error) { + message2Sign, err := encodeMessageToSign(message, s.chainID, s.subnetID) + if err != nil { + return nil, fmt.Errorf("failed to encode message to sign: %w", err) + } + + sig, err := s.signBLS(message2Sign) + if err != nil { + return nil, err + } + + sigBytes := bls.SignatureToBytes(sig) + return sigBytes, nil +} + +type encodedSimplexMessage struct { + Message []byte + ChainID []byte + SubnetID []byte +} + +// encodesMessageToSign returns a byte slice [simplexLabel][chainID][networkID][message length][message]. +func encodeMessageToSign(message []byte, chainID ids.ID, subnetID ids.ID) ([]byte, error) { + encodedSimplexMessage := encodedSimplexMessage{ + Message: message, + ChainID: chainID[:], + SubnetID: subnetID[:], + } + return asn1.Marshal(encodedSimplexMessage) +} + +func (v BLSVerifier) Verify(message []byte, signature []byte, signer simplex.NodeID) error { + if len(signer) != ids.NodeIDLen { + return fmt.Errorf("expected signer to be %d bytes but got %d bytes", ids.NodeIDLen, len(signer)) + } + + key := ids.NodeID(signer) + pk, exists := v.nodeID2PK[key] + if !exists { + return fmt.Errorf("%w: signer %x", errSignerNotFound, key) + } + + sig, err := bls.SignatureFromBytes(signature) + if err != nil { + return fmt.Errorf("failed to parse signature: %w", err) + } + + message2Verify, err := encodeMessageToSign(message, v.chainID, v.subnetID) + if err != nil { + return fmt.Errorf("failed to encode message to verify: %w", err) + } + + if !bls.Verify(&pk, sig, message2Verify) { + return errSignatureVerificationFailed + } + + return nil +} + +func createVerifier(config *Config) BLSVerifier { + verifier := BLSVerifier{ + nodeID2PK: make(map[ids.NodeID]bls.PublicKey), + subnetID: config.Ctx.SubnetID, + chainID: config.Ctx.ChainID, + } + + nodes := config.Validators.GetValidatorIDs(config.Ctx.SubnetID) + for _, node := range nodes { + validator, ok := config.Validators.GetValidator(config.Ctx.SubnetID, node) + if !ok { + continue + } + verifier.nodeID2PK[node] = *validator.PublicKey + } + return verifier +} diff --git a/simplex/bls_test.go b/simplex/bls_test.go new file mode 100644 index 000000000000..74dc3b5d0deb --- /dev/null +++ b/simplex/bls_test.go @@ -0,0 +1,133 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "testing" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" + "github.com/stretchr/testify/require" +) + +var _ ValidatorInfo = (*testValidatorInfo)(nil) + +// testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. +// it assumes all validators are in the same subnet and returns all of them for any subnetID. +type testValidatorInfo struct { + validators map[ids.NodeID]validators.Validator +} + +func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { + if v.validators == nil { + return nil + } + + ids := make([]ids.NodeID, 0, len(v.validators)) + for id := range v.validators { + ids = append(ids, id) + } + return ids +} + +func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) { + if v.validators == nil { + return nil, false + } + + val, exists := v.validators[nodeID] + if !exists { + return nil, false + } + return &val, true +} + +func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { + if len(nodeIds) != len(pks) { + panic("nodeIds and pks must have the same length") + } + + vds := make(map[ids.NodeID]validators.Validator, len(pks)) + for i, pk := range pks { + validator := validators.Validator{ + PublicKey: pk, + NodeID: nodeIds[i], + } + vds[nodeIds[i]] = validator + } + // all we need is to generate the public keys for the validators + return &testValidatorInfo{ + validators: vds, + } +} + +func newEngineConfig(ls *localsigner.LocalSigner) *Config { + nodeID := ids.GenerateTestNodeID() + + simplexChainContext := SimplexChainContext{ + NodeID: nodeID, + ChainID: ids.GenerateTestID(), + SubnetID: ids.GenerateTestID(), + } + + return &Config{ + Ctx: simplexChainContext, + Validators: newTestValidatorInfo([]ids.NodeID{nodeID}, []*bls.PublicKey{ls.PublicKey()}), + SignBLS: ls.Sign, + } +} + +func TestBLSSignVerify(t *testing.T) { + ls, err := localsigner.New() + require.NoError(t, err) + + config := newEngineConfig(ls) + + signer, verifier := NewBLSAuth(config) + + msg := "Begin at the beginning, and go on till you come to the end: then stop" + + sig, err := signer.Sign([]byte(msg)) + require.NoError(t, err) + + err = verifier.Verify([]byte(msg), sig, signer.nodeID[:]) + require.NoError(t, err) +} + +func TestSignerNotInMemberSet(t *testing.T) { + ls, err := localsigner.New() + require.NoError(t, err) + + config := newEngineConfig(ls) + signer, verifier := NewBLSAuth(config) + + msg := "Begin at the beginning, and go on till you come to the end: then stop" + + sig, err := signer.Sign([]byte(msg)) + require.NoError(t, err) + + notInMembershipSet := ids.GenerateTestNodeID() + err = verifier.Verify([]byte(msg), sig, notInMembershipSet[:]) + require.ErrorIs(t, err, errSignerNotFound) +} + +func TestSignerInvalidMessageEncoding(t *testing.T) { + ls, err := localsigner.New() + require.NoError(t, err) + + config := newEngineConfig(ls) + + // sign a message with invalid encoding + dummyMsg := []byte("dummy message") + sig, err := ls.Sign(dummyMsg) + require.NoError(t, err) + + sigBytes := bls.SignatureToBytes(sig) + + _, verifier := NewBLSAuth(config) + err = verifier.Verify(dummyMsg, sigBytes, config.Ctx.NodeID[:]) + require.ErrorIs(t, err, errSignatureVerificationFailed) +} diff --git a/simplex/config.go b/simplex/config.go new file mode 100644 index 000000000000..97e72e0f2efc --- /dev/null +++ b/simplex/config.go @@ -0,0 +1,33 @@ +// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/logging" +) + +type ValidatorInfo interface { + GetValidatorIDs(subnetID ids.ID) []ids.NodeID + GetValidator(subnetID ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) +} + +// Config wraps all the parameters needed for a simplex engine +type Config struct { + Ctx SimplexChainContext + Log logging.Logger + Validators ValidatorInfo + SignBLS SignFunc +} + +// Context is information about the current execution. +// [SubnitID] is the ID of the subnet this context exists within. +// [ChainID] is the ID of the chain this context exists within. +// [NodeID] is the ID of this node +type SimplexChainContext struct { + NodeID ids.NodeID + ChainID ids.ID + SubnetID ids.ID +} From c5be0a4459dd4c09f7d7c362a2b6052bc58c81fa Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 5 Jun 2025 10:26:54 -0700 Subject: [PATCH 02/18] add simplex to go mod + lint --- go.mod | 1 + go.sum | 2 ++ simplex/bls.go | 14 ++++++++------ simplex/bls_test.go | 5 +++-- simplex/config.go | 4 ++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 1b43e438972c..8b9ffb89a875 100644 --- a/go.mod +++ b/go.mod @@ -85,6 +85,7 @@ require ( github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/ava-labs/simplex v0.0.0-20250605162940-db8e6d44f53d github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect diff --git a/go.sum b/go.sum index b686626c524e..cddaf16b2fd9 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,8 @@ github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60 h1:EL github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60/go.mod h1:/7qKobTfbzBu7eSTVaXMTr56yTYk4j2Px6/8G+idxHo= github.com/ava-labs/libevm v1.13.14-0.2.0.release h1:uKGCc5/ceeBbfAPRVtBUxbQt50WzB2pEDb8Uy93ePgQ= github.com/ava-labs/libevm v1.13.14-0.2.0.release/go.mod h1:+Iol+sVQ1KyoBsHf3veyrBmHCXr3xXRWq6ZXkgVfNLU= +github.com/ava-labs/simplex v0.0.0-20250605162940-db8e6d44f53d h1:D/BOS3USdAigun2OP/6khvukKnn4BIKviYAdKLHN6zc= +github.com/ava-labs/simplex v0.0.0-20250605162940-db8e6d44f53d/go.mod h1:GVzumIo3zR23/qGRN2AdnVkIPHcKMq/D89EGWZfMGQ0= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= diff --git a/simplex/bls.go b/simplex/bls.go index 7fa125d81434..f767dba21651 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -8,28 +8,29 @@ import ( "errors" "fmt" + "github.com/ava-labs/simplex" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/simplex" ) var ( errSignatureVerificationFailed = errors.New("signature verification failed") errSignerNotFound = errors.New("signer not found in the membership set") + simplexLabel = []byte("simplex") ) var _ simplex.Signer = (*BLSSigner)(nil) type SignFunc func(msg []byte) (*bls.Signature, error) -// BLSSigner signs messages encoded with the provided ChainID and NetworkID +// BLSSigner signs messages encoded with the provided ChainID and SubnetID. // using the SignBLS function. type BLSSigner struct { chainID ids.ID subnetID ids.ID // signBLS is passed in because we support both software and hardware BLS signing. signBLS SignFunc - nodeID ids.NodeID } type BLSVerifier struct { @@ -42,7 +43,6 @@ func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier) { return BLSSigner{ chainID: config.Ctx.ChainID, subnetID: config.Ctx.SubnetID, - nodeID: config.Ctx.NodeID, signBLS: config.SignBLS, }, createVerifier(config) } @@ -64,18 +64,20 @@ func (s *BLSSigner) Sign(message []byte) ([]byte, error) { return sigBytes, nil } -type encodedSimplexMessage struct { +type encodedSimplexSignedPayload struct { Message []byte ChainID []byte SubnetID []byte + Label []byte } // encodesMessageToSign returns a byte slice [simplexLabel][chainID][networkID][message length][message]. func encodeMessageToSign(message []byte, chainID ids.ID, subnetID ids.ID) ([]byte, error) { - encodedSimplexMessage := encodedSimplexMessage{ + encodedSimplexMessage := encodedSimplexSignedPayload{ Message: message, ChainID: chainID[:], SubnetID: subnetID[:], + Label: simplexLabel, } return asn1.Marshal(encodedSimplexMessage) } diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 74dc3b5d0deb..8797866e03c8 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -6,11 +6,12 @@ package simplex import ( "testing" + "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" - "github.com/stretchr/testify/require" ) var _ ValidatorInfo = (*testValidatorInfo)(nil) @@ -93,7 +94,7 @@ func TestBLSSignVerify(t *testing.T) { sig, err := signer.Sign([]byte(msg)) require.NoError(t, err) - err = verifier.Verify([]byte(msg), sig, signer.nodeID[:]) + err = verifier.Verify([]byte(msg), sig, config.Ctx.NodeID[:]) require.NoError(t, err) } diff --git a/simplex/config.go b/simplex/config.go index 97e72e0f2efc..8e16e26e3e99 100644 --- a/simplex/config.go +++ b/simplex/config.go @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package simplex @@ -23,7 +23,7 @@ type Config struct { } // Context is information about the current execution. -// [SubnitID] is the ID of the subnet this context exists within. +// [SubnetID] is the ID of the subnet this context exists within. // [ChainID] is the ID of the chain this context exists within. // [NodeID] is the ID of this node type SimplexChainContext struct { From 52d343ebca586d51ac348456d92b7dea903142b9 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 5 Jun 2025 13:17:46 -0700 Subject: [PATCH 03/18] add log to createVerifier --- simplex/bls.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/simplex/bls.go b/simplex/bls.go index f767dba21651..e7b1ce25259c 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/ava-labs/simplex" + "go.uber.org/zap" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" @@ -121,6 +122,7 @@ func createVerifier(config *Config) BLSVerifier { for _, node := range nodes { validator, ok := config.Validators.GetValidator(config.Ctx.SubnetID, node) if !ok { + config.Log.Error("failed to get validator for node %s in subnet %s", zap.Stringer("node", node), zap.Stringer("subnetID", config.Ctx.SubnetID)) continue } verifier.nodeID2PK[node] = *validator.PublicKey From 68f0c26bb28a69c542a38cdf2b712c07b69efbc1 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 9 Jun 2025 10:42:33 -0500 Subject: [PATCH 04/18] add qc --- simplex/bls_test.go | 34 +++++++ simplex/quorum.go | 147 ++++++++++++++++++++++++++++ snow/consensus/snowball/tree.go | 168 ++++++++++++++++---------------- 3 files changed, 265 insertions(+), 84 deletions(-) create mode 100644 simplex/quorum.go diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 8797866e03c8..91403dcd14f3 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -132,3 +132,37 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { err = verifier.Verify(dummyMsg, sigBytes, config.Ctx.NodeID[:]) require.ErrorIs(t, err, errSignatureVerificationFailed) } + +// TestQCAggregateAndSign tests the aggregation of multiple signatures +// and then verifies the generated quorum certificate on that message. +func TestQCAggregateAndSign(t *testing.T) { + ls, err := localsigner.New() + require.NoError(t, err) + + config := newEngineConfig(ls) + signer, verifier := NewBLSAuth(config) + + msg := "Begin at the beginning, and go on till you come to the end: then stop" + + sig1, err := signer.Sign([]byte(msg)) + require.NoError(t, err) + + sig2, err := signer.Sign([]byte(msg)) + require.NoError(t, err) + + // Aggregate signatures + aggSig, err := bls.AggregateSignatures([]*bls.Signature{bls.SignatureFromBytes(sig1), bls.SignatureFromBytes(sig2)}) + require.NoError(t, err) + + err = verifier.Verify([]byte(msg), bls.SignatureToBytes(aggSig), config.Ctx.NodeID[:]) + require.NoError(t, err) +} + +func TestQCSignerNotInMembershipSet(t *testing.T) { + +} + +func TestQCNotInMembershipSet(t *testing.T) { + +} + diff --git a/simplex/quorum.go b/simplex/quorum.go new file mode 100644 index 000000000000..84df789a5e27 --- /dev/null +++ b/simplex/quorum.go @@ -0,0 +1,147 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "fmt" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/simplex" +) + +var _ simplex.QuorumCertificate = (*QC)(nil) +var _ simplex.QCDeserializer = QCDeserializer{} + +type QCDeserializer BLSVerifier + +// QC represents a quorum certificate in the Simplex consensus protocol. +type QC struct { + verifier BLSVerifier + sig bls.Signature + signers []simplex.NodeID +} + +// Signers returns the list of signers for the quorum certificate. +func (qc *QC) Signers() []simplex.NodeID { + return qc.signers +} + +// Verify checks if the quorum certificate is valid by verifying the aggregated signature against the signers' public keys. +func (qc *QC) Verify(msg []byte) error { + pks := make([]*bls.PublicKey, 0, len(qc.signers)) + + // ensure all signers are in the membership set + for _, signer := range qc.signers { + pk, exists := qc.verifier.nodeID2PK[ids.NodeID(signer)] + if !exists { + return fmt.Errorf("signer %x is not found in the membership set", signer) + } + pks = append(pks, &pk) + } + + // aggregate the public keys + aggPK, err := bls.AggregatePublicKeys(pks) + if err != nil { + return fmt.Errorf("failed to aggregate public keys: %w", err) + } + + message2Verify, err := encodeMessageToSign(msg, qc.verifier.chainID, qc.verifier.subnetID) + if err != nil { + return fmt.Errorf("failed to encode message to verify: %w", err) + } + + if !bls.Verify(aggPK, &qc.sig, message2Verify) { + return fmt.Errorf("signature verification failed") + } + + return nil +} + +// Bytes serializes the quorum certificate into bytes. +// The serialization format is: +// [signer1][signer2]...[signerN][signature] +// where each signer is represented by its NodeID and the signature is the BLS signature. +func (qc *QC) Bytes() []byte { + sigBytes := bls.SignatureToBytes(&qc.sig) + buff := make([]byte, len(sigBytes)+len(qc.signers)*ids.NodeIDLen) + var pos int + for _, signer := range qc.signers { + copy(buff[pos:], signer[:ids.NodeIDLen]) + pos += ids.NodeIDLen + } + + copy(buff[pos:], sigBytes) + return buff +} + +// DeserializeQuorumCertificate deserializes a quorum certificate from bytes. +func (d QCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex.QuorumCertificate, error) { + quorumSize := simplex.Quorum(len(d.nodeID2PK)) + expectedSize := quorumSize*ids.NodeIDLen + bls.SignatureLen + if len(bytes) != expectedSize { + return nil, fmt.Errorf("expected at least %d bytes but got %d bytes", expectedSize, len(bytes)) + } + + signers := make([]simplex.NodeID, 0, quorumSize) + + var pos int + for range quorumSize { + signers = append(signers, bytes[pos:pos+ids.NodeIDLen]) + pos += ids.NodeIDLen + } + + sig, err := bls.SignatureFromBytes(bytes[pos:]) + if err != nil { + return nil, fmt.Errorf("failed to parse signature: %w", err) + } + + return &QC{ + verifier: BLSVerifier(d), + signers: signers, + sig: *sig, + }, nil +} + +// SignatureAggregator aggregates signatures into a quorum certificate. +type SignatureAggregator BLSVerifier + +// Aggregate aggregates the provided signatures into a quorum certificate. +// It requires at least a quorum of signatures to succeed. +// If any signature is from a signer not in the membership set, it returns an error. +func (a SignatureAggregator) Aggregate(signatures []simplex.Signature) (simplex.QuorumCertificate, error) { + quorumSize := simplex.Quorum(len(a.nodeID2PK)) + if len(signatures) < quorumSize { + return nil, fmt.Errorf("expected at least %d signatures but got %d", quorumSize, len(signatures)) + } + + signatures = signatures[:quorumSize] + + signers := make([]simplex.NodeID, 0, quorumSize) + sigs := make([]*bls.Signature, 0, quorumSize) + for _, signature := range signatures { + signer := signature.Signer + _, exists := a.nodeID2PK[ids.NodeID(signer)] + if !exists { + return nil, fmt.Errorf("signer %x is not found in the membership set", signer) + } + signers = append(signers, signer) + sig, err := bls.SignatureFromBytes(signature.Value) + if err != nil { + return nil, fmt.Errorf("failed to parse signature: %w", err) + } + sigs = append(sigs, sig) + } + + aggregatedSig, err := bls.AggregateSignatures(sigs) + if err != nil { + return nil, fmt.Errorf("failed to aggregate signatures: %w", err) + } + + return &QC{ + verifier: BLSVerifier(a), + signers: signers, + sig: *aggregatedSig, + }, nil +} diff --git a/snow/consensus/snowball/tree.go b/snow/consensus/snowball/tree.go index a11b92e1fd03..d6b0fabc7384 100644 --- a/snow/consensus/snowball/tree.go +++ b/snow/consensus/snowball/tree.go @@ -175,8 +175,6 @@ func (u *unaryNode) DecidedPrefix() int { return u.decidedPrefix } -//nolint:gci,gofmt,gofumpt // this comment is formatted as intended -// // This is by far the most complicated function in this algorithm. // The intuition is that this instance represents a series of consecutive unary // snowball instances, and this function's purpose is convert one of these unary @@ -188,23 +186,23 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "00001" in this node: // -// +-------------------+ <-- This node will not be split -// | | -// | 0 0 0 | -// | | -// +-------------------+ <-- Pass the add to the child -// ^ -// | +// +-------------------+ <-- This node will not be split +// | | +// | 0 0 0 | +// | | +// +-------------------+ <-- Pass the add to the child +// ^ +// | // // Results in: // -// +-------------------+ -// | | -// | 0 0 0 | -// | | -// +-------------------+ <-- With the modified child -// ^ -// | +// +-------------------+ +// | | +// | 0 0 0 | +// | | +// +-------------------+ <-- With the modified child +// ^ +// | // // 2. This instance represents a series of only one unary instance and it must // be split. @@ -215,19 +213,19 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "1" in this tree: // -// +-------------------+ -// | | -// | 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ // // 3. This instance must be split on the first bit // @@ -237,26 +235,26 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "10" in this tree: // -// +-------------------+ -// | | -// | 0 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ -// ^ ^ -// / \ -// +-------------------+ +-------------------+ -// | | | | -// | 0 | | 0 | -// | | | | -// +-------------------+ +-------------------+ +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ +// ^ ^ +// / \ +// +-------------------+ +-------------------+ +// | | | | +// | 0 | | 0 | +// | | | | +// +-------------------+ +-------------------+ // // 4. This instance must be split on the last bit // @@ -267,26 +265,26 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "01" in this tree: // -// +-------------------+ -// | | -// | 0 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | -// | 0 | -// | | -// +-------------------+ -// ^ -// | -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 | +// | | +// +-------------------+ +// ^ +// | +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ // // 5. This instance must be split on an interior bit // @@ -298,33 +296,35 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "010" in this tree: // -// +-------------------+ -// | | -// | 0 0 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 0 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | -// | 0 | -// | | -// +-------------------+ -// ^ -// | -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ -// ^ ^ -// / \ -// +-------------------+ +-------------------+ -// | | | | -// | 0 | | 0 | -// | | | | -// +-------------------+ +-------------------+ +// +-------------------+ +// | | +// | 0 | +// | | +// +-------------------+ +// ^ +// | +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ +// ^ ^ +// / \ +// +-------------------+ +-------------------+ +// | | | | +// | 0 | | 0 | +// | | | | +// +-------------------+ +-------------------+ +// +//nolint:gci,gofmt,gofumpt // this comment is formatted as intended func (u *unaryNode) Add(newChoice ids.ID) node { if u.Finalized() { return u // Only happens if the tree is finalized, or it's a leaf node From 458d540ea0cf1adbcb018d7fbbe7ac86eca19345 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 9 Jun 2025 14:35:01 -0500 Subject: [PATCH 05/18] separate into utils file --- simplex/bls_test.go | 83 +++----------------------------------------- simplex/test_util.go | 83 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 79 deletions(-) create mode 100644 simplex/test_util.go diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 8797866e03c8..e5c59662b356 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -9,84 +9,13 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" ) -var _ ValidatorInfo = (*testValidatorInfo)(nil) - -// testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. -// it assumes all validators are in the same subnet and returns all of them for any subnetID. -type testValidatorInfo struct { - validators map[ids.NodeID]validators.Validator -} - -func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { - if v.validators == nil { - return nil - } - - ids := make([]ids.NodeID, 0, len(v.validators)) - for id := range v.validators { - ids = append(ids, id) - } - return ids -} - -func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) { - if v.validators == nil { - return nil, false - } - - val, exists := v.validators[nodeID] - if !exists { - return nil, false - } - return &val, true -} - -func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { - if len(nodeIds) != len(pks) { - panic("nodeIds and pks must have the same length") - } - - vds := make(map[ids.NodeID]validators.Validator, len(pks)) - for i, pk := range pks { - validator := validators.Validator{ - PublicKey: pk, - NodeID: nodeIds[i], - } - vds[nodeIds[i]] = validator - } - // all we need is to generate the public keys for the validators - return &testValidatorInfo{ - validators: vds, - } -} - -func newEngineConfig(ls *localsigner.LocalSigner) *Config { - nodeID := ids.GenerateTestNodeID() - - simplexChainContext := SimplexChainContext{ - NodeID: nodeID, - ChainID: ids.GenerateTestID(), - SubnetID: ids.GenerateTestID(), - } - - return &Config{ - Ctx: simplexChainContext, - Validators: newTestValidatorInfo([]ids.NodeID{nodeID}, []*bls.PublicKey{ls.PublicKey()}), - SignBLS: ls.Sign, - } -} - func TestBLSSignVerify(t *testing.T) { - ls, err := localsigner.New() + config, err := newEngineConfig() require.NoError(t, err) - config := newEngineConfig(ls) - signer, verifier := NewBLSAuth(config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -99,10 +28,8 @@ func TestBLSSignVerify(t *testing.T) { } func TestSignerNotInMemberSet(t *testing.T) { - ls, err := localsigner.New() + config, err := newEngineConfig() require.NoError(t, err) - - config := newEngineConfig(ls) signer, verifier := NewBLSAuth(config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -116,14 +43,12 @@ func TestSignerNotInMemberSet(t *testing.T) { } func TestSignerInvalidMessageEncoding(t *testing.T) { - ls, err := localsigner.New() + config, err := newEngineConfig() require.NoError(t, err) - config := newEngineConfig(ls) - // sign a message with invalid encoding dummyMsg := []byte("dummy message") - sig, err := ls.Sign(dummyMsg) + sig, err := config.SignBLS(dummyMsg) require.NoError(t, err) sigBytes := bls.SignatureToBytes(sig) diff --git a/simplex/test_util.go b/simplex/test_util.go new file mode 100644 index 000000000000..e926fe686a4a --- /dev/null +++ b/simplex/test_util.go @@ -0,0 +1,83 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" +) + +var _ ValidatorInfo = (*testValidatorInfo)(nil) + +// testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. +// it assumes all validators are in the same subnet and returns all of them for any subnetID. +type testValidatorInfo struct { + validators map[ids.NodeID]validators.Validator +} + +func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { + if v.validators == nil { + return nil + } + + ids := make([]ids.NodeID, 0, len(v.validators)) + for id := range v.validators { + ids = append(ids, id) + } + return ids +} + +func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) { + if v.validators == nil { + return nil, false + } + + val, exists := v.validators[nodeID] + if !exists { + return nil, false + } + return &val, true +} + +func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { + if len(nodeIds) != len(pks) { + panic("nodeIds and pks must have the same length") + } + + vds := make(map[ids.NodeID]validators.Validator, len(pks)) + for i, pk := range pks { + validator := validators.Validator{ + PublicKey: pk, + NodeID: nodeIds[i], + } + vds[nodeIds[i]] = validator + } + // all we need is to generate the public keys for the validators + return &testValidatorInfo{ + validators: vds, + } +} + +func newEngineConfig() (*Config, error) { + ls, err := localsigner.New() + if err != nil { + return nil, err + } + + nodeID := ids.GenerateTestNodeID() + + simplexChainContext := SimplexChainContext{ + NodeID: nodeID, + ChainID: ids.GenerateTestID(), + SubnetID: ids.GenerateTestID(), + } + + return &Config{ + Ctx: simplexChainContext, + Validators: newTestValidatorInfo([]ids.NodeID{nodeID}, []*bls.PublicKey{ls.PublicKey()}), + SignBLS: ls.Sign, + }, nil +} From 31293d7005a8ef6c9d8d82ae7ecc7ebbe18484b0 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 9 Jun 2025 18:24:44 -0500 Subject: [PATCH 06/18] add tests --- api/grpcclient/client.go | 67 + api/server/http2_router.go | 67 + api/server/http2_router_test.go | 72 + api/server/server.go | 98 +- go.mod | 2 +- go.sum | 4 +- proto/pb/vm/vm.pb.go | 1206 +++++++++-------- proto/pb/vm/vm_grpc.pb.go | 37 + proto/pb/xsvm/service.pb.go | 286 ++++ proto/pb/xsvm/service_grpc.pb.go | 179 +++ proto/vm/vm.proto | 7 + proto/xsvm/service.proto | 26 + simplex/bls.go | 7 +- simplex/bls_test.go | 312 +++-- simplex/quorum.go | 30 +- simplex/test_util.go | 124 ++ snow/consensus/snowball/tree.go | 168 +-- .../vertex/vertexmock/linearizable_vm.go | 15 + snow/engine/common/vm.go | 4 + snow/engine/enginetest/vm.go | 63 +- .../snowman/block/blockmock/chain_vm.go | 15 + tests/e2e/vms/xsvm.go | 83 ++ tests/fixture/tmpnet/kube_runtime.go | 20 +- vms/avm/vm.go | 4 + vms/example/xsvm/api/ping.go | 69 + vms/example/xsvm/vm.go | 8 + vms/platformvm/vm.go | 4 + vms/rpcchainvm/ghttp/http_client.go | 9 +- vms/rpcchainvm/vm_client.go | 19 + vms/rpcchainvm/vm_server.go | 28 + 30 files changed, 2214 insertions(+), 819 deletions(-) create mode 100644 api/grpcclient/client.go create mode 100644 api/server/http2_router.go create mode 100644 api/server/http2_router_test.go create mode 100644 proto/pb/xsvm/service.pb.go create mode 100644 proto/pb/xsvm/service_grpc.pb.go create mode 100644 proto/xsvm/service.proto create mode 100644 simplex/test_util.go create mode 100644 vms/example/xsvm/api/ping.go diff --git a/api/grpcclient/client.go b/api/grpcclient/client.go new file mode 100644 index 000000000000..fd0fbf3d67f6 --- /dev/null +++ b/api/grpcclient/client.go @@ -0,0 +1,67 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package grpcclient + +import ( + "context" + "fmt" + + "google.golang.org/grpc" + + "github.com/ava-labs/avalanchego/ids" +) + +// NewChainClient returns grpc.ClientConn that prefixes method calls with the +// provided chainID prefix +func NewChainClient(uri string, chainID ids.ID, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + dialOpts := []grpc.DialOption{ + grpc.WithUnaryInterceptor(PrefixChainIDUnaryClientInterceptor(chainID)), + grpc.WithStreamInterceptor(PrefixChainIDStreamClientInterceptor(chainID)), + } + + dialOpts = append(dialOpts, opts...) + + conn, err := grpc.NewClient(uri, dialOpts...) + if err != nil { + return nil, fmt.Errorf("failed to initialize chain grpc client: %w", err) + } + + return conn, nil +} + +// PrefixChainIDUnaryClientInterceptor prefixes unary grpc calls with the +// provided chainID prefix +func PrefixChainIDUnaryClientInterceptor(chainID ids.ID) grpc.UnaryClientInterceptor { + return func( + ctx context.Context, + method string, + req any, + reply any, + cc *grpc.ClientConn, + invoker grpc.UnaryInvoker, + opts ...grpc.CallOption, + ) error { + return invoker(ctx, prefix(chainID, method), req, reply, cc, opts...) + } +} + +// PrefixChainIDStreamClientInterceptor prefixes streaming grpc calls with the +// provided chainID prefix +func PrefixChainIDStreamClientInterceptor(chainID ids.ID) grpc.StreamClientInterceptor { + return func( + ctx context.Context, + desc *grpc.StreamDesc, + cc *grpc.ClientConn, + method string, + streamer grpc.Streamer, + opts ...grpc.CallOption, + ) (grpc.ClientStream, error) { + return streamer(ctx, desc, cc, prefix(chainID, method), opts...) + } +} + +// http/2 :path takes the form of /ChainID/Service/Method +func prefix(chainID ids.ID, method string) string { + return "/" + chainID.String() + method +} diff --git a/api/server/http2_router.go b/api/server/http2_router.go new file mode 100644 index 000000000000..76b664a7f961 --- /dev/null +++ b/api/server/http2_router.go @@ -0,0 +1,67 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package server + +import ( + "net/http" + "strings" + "sync" + + "github.com/ava-labs/avalanchego/ids" +) + +var _ http.Handler = (*http2Router)(nil) + +type http2Router struct { + lock sync.RWMutex + handlers map[string]http.Handler +} + +func newHTTP2Router() *http2Router { + return &http2Router{ + handlers: make(map[string]http.Handler), + } +} + +func (h *http2Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // The :path pseudo-header takes the form of /Prefix/Path + parsed := strings.Split(r.URL.Path, "/") + if len(parsed) < 2 { + w.WriteHeader(http.StatusBadRequest) + return + } + + chainID := parsed[1] + + h.lock.RLock() + handler, ok := h.handlers[chainID] + h.lock.RUnlock() + if !ok { + w.WriteHeader(http.StatusNotFound) + return + } + + // Deep copy the request to avoid weird behavior from modifying r + requestDeepCopy := r.Clone(r.Context()) + // Route this request to the http2 handler using the chain prefix + requestDeepCopy.URL.Path = strings.TrimPrefix( + requestDeepCopy.URL.Path, + "/"+chainID, + ) + + handler.ServeHTTP(w, requestDeepCopy) +} + +func (h *http2Router) Add(chainID ids.ID, handler http.Handler) bool { + h.lock.Lock() + defer h.lock.Unlock() + + chainIDStr := chainID.String() + if _, ok := h.handlers[chainIDStr]; ok { + return false + } + + h.handlers[chainIDStr] = handler + return true +} diff --git a/api/server/http2_router_test.go b/api/server/http2_router_test.go new file mode 100644 index 000000000000..1ffa488b0ff4 --- /dev/null +++ b/api/server/http2_router_test.go @@ -0,0 +1,72 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package server + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/ids" +) + +func TestHTTP2RouterAdd(t *testing.T) { + require := require.New(t) + h := newHTTP2Router() + handler := http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}) + + require.True(h.Add(ids.Empty, handler)) + require.False(h.Add(ids.Empty, handler)) +} + +func TestHTTP2RouterServeHTTP(t *testing.T) { + tests := []struct { + name string + chainIDs []ids.ID + path string + wantCode int + }{ + { + name: "invalid request", + path: "foo", + wantCode: http.StatusBadRequest, + }, + { + name: "invalid handler", + path: "/foo/bar/method", + wantCode: http.StatusNotFound, + }, + { + name: "valid handler", + chainIDs: []ids.ID{{'f', 'o', 'o'}}, + path: fmt.Sprintf("/%s/bar/method", ids.ID{'f', 'o', 'o'}.String()), + wantCode: http.StatusOK, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require := require.New(t) + + h := newHTTP2Router() + handler := http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}) + writer := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/", nil) + request.URL = &url.URL{ + Path: tt.path, + } + + for _, chainID := range tt.chainIDs { + require.True(h.Add(chainID, handler)) + } + + h.ServeHTTP(writer, request) + require.Equal(tt.wantCode, writer.Code) + }) + } +} diff --git a/api/server/server.go b/api/server/server.go index 8156a4964dcc..d19152c2c9e1 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -17,6 +17,7 @@ import ( "github.com/rs/cors" "go.uber.org/zap" "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" "github.com/ava-labs/avalanchego/api" "github.com/ava-labs/avalanchego/ids" @@ -88,7 +89,8 @@ type server struct { metrics *metrics // Maps endpoints to handlers - router *router + router *router + http2Router *http2Router srv *http.Server @@ -115,33 +117,30 @@ func New( } router := newRouter() - allowedHostsHandler := filterInvalidHosts(router, allowedHosts) - corsHandler := cors.New(cors.Options{ - AllowedOrigins: allowedOrigins, - AllowCredentials: true, - }).Handler(allowedHostsHandler) - gzipHandler := gziphandler.GzipHandler(corsHandler) - var handler http.Handler = http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { - // Attach this node's ID as a header - w.Header().Set("node-id", nodeID.String()) - gzipHandler.ServeHTTP(w, r) - }, - ) + handler := wrapHandler(router, nodeID, allowedOrigins, allowedHosts, true) + + http2Router := newHTTP2Router() + // Do not use gzip middleware because it breaks the grpc spec + http2Handler := wrapHandler(http2Router, nodeID, allowedOrigins, allowedHosts, false) httpServer := &http.Server{ - Handler: handler, + Handler: h2c.NewHandler( + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.ProtoMajor == 2 { + http2Handler.ServeHTTP(w, r) + return + } + + handler.ServeHTTP(w, r) + }), + &http2.Server{ + MaxConcurrentStreams: maxConcurrentStreams, + }), ReadTimeout: httpConfig.ReadTimeout, ReadHeaderTimeout: httpConfig.ReadHeaderTimeout, WriteTimeout: httpConfig.WriteTimeout, IdleTimeout: httpConfig.IdleTimeout, } - err = http2.ConfigureServer(httpServer, &http2.Server{ - MaxConcurrentStreams: maxConcurrentStreams, - }) - if err != nil { - return nil, err - } log.Info("API created", zap.Strings("allowedOrigins", allowedOrigins), @@ -154,6 +153,7 @@ func New( tracer: tracer, metrics: m, router: router, + http2Router: http2Router, srv: httpServer, listener: listener, }, nil @@ -199,6 +199,30 @@ func (s *server) RegisterChain(chainName string, ctx *snow.ConsensusContext, vm ) } } + + ctx.Lock.Lock() + http2Handler, err := vm.CreateHTTP2Handler(context.TODO()) + ctx.Lock.Unlock() + if err != nil { + s.log.Error("failed to create http2 handler", + zap.String("chainName", chainName), + zap.Error(err), + ) + return + } + + if http2Handler == nil { + return + } + + http2Handler = s.wrapMiddleware(chainName, http2Handler, ctx) + if !s.http2Router.Add(ctx.ChainID, http2Handler) { + s.log.Error( + "failed to add route to http2 handler", + zap.String("chainName", chainName), + zap.Error(err), + ) + } } func (s *server) addChainRoute(chainName string, handler http.Handler, ctx *snow.ConsensusContext, base, endpoint string) error { @@ -207,13 +231,17 @@ func (s *server) addChainRoute(chainName string, handler http.Handler, ctx *snow zap.String("url", url), zap.String("endpoint", endpoint), ) + handler = s.wrapMiddleware(chainName, handler, ctx) + return s.router.AddRouter(url, endpoint, handler) +} + +func (s *server) wrapMiddleware(chainName string, handler http.Handler, ctx *snow.ConsensusContext) http.Handler { if s.tracingEnabled { handler = api.TraceHandler(handler, chainName, s.tracer) } // Apply middleware to reject calls to the handler before the chain finishes bootstrapping handler = rejectMiddleware(handler, ctx) - handler = s.metrics.wrapHandler(chainName, handler) - return s.router.AddRouter(url, endpoint, handler) + return s.metrics.wrapHandler(chainName, handler) } func (s *server) AddRoute(handler http.Handler, base, endpoint string) error { @@ -299,3 +327,27 @@ func (a readPathAdder) AddRoute(handler http.Handler, base, endpoint string) err func (a readPathAdder) AddAliases(endpoint string, aliases ...string) error { return a.pather.AddAliasesWithReadLock(endpoint, aliases...) } + +func wrapHandler( + handler http.Handler, + nodeID ids.NodeID, + allowedOrigins []string, + allowedHosts []string, + gzip bool, +) http.Handler { + h := filterInvalidHosts(handler, allowedHosts) + h = cors.New(cors.Options{ + AllowedOrigins: allowedOrigins, + AllowCredentials: true, + }).Handler(h) + if gzip { + h = gziphandler.GzipHandler(h) + } + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + // Attach this node's ID as a header + w.Header().Set("node-id", nodeID.String()) + h.ServeHTTP(w, r) + }, + ) +} diff --git a/go.mod b/go.mod index 8b9ffb89a875..69cd28ed15d9 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/NYTimes/gziphandler v1.1.1 github.com/StephenButtolph/canoto v0.15.0 github.com/antithesishq/antithesis-sdk-go v0.3.8 - github.com/ava-labs/coreth v0.15.1-rc.0.0.20250530184801-28421010abae + github.com/ava-labs/coreth v0.15.2-rc.0 github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60 github.com/ava-labs/libevm v1.13.14-0.2.0.release github.com/btcsuite/btcd/btcutil v1.1.3 diff --git a/go.sum b/go.sum index cddaf16b2fd9..7fe862174fac 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,8 @@ github.com/antithesishq/antithesis-sdk-go v0.3.8/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/ava-labs/coreth v0.15.1-rc.0.0.20250530184801-28421010abae h1:PPcOEtY3SoXruzMPYJMxoeoExRVhf5UOiH7SvdPHQwY= -github.com/ava-labs/coreth v0.15.1-rc.0.0.20250530184801-28421010abae/go.mod h1:Tl6TfpOwSq0bXvN7DTENXB4As3hml8ma9OQEWS9DH9I= +github.com/ava-labs/coreth v0.15.2-rc.0 h1:RnCH59A/WMEdMyuqugaPIk1xrQQuo9vEgMVOjk9ZjWQ= +github.com/ava-labs/coreth v0.15.2-rc.0/go.mod h1:Tl6TfpOwSq0bXvN7DTENXB4As3hml8ma9OQEWS9DH9I= github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60 h1:EL66gtXOAwR/4KYBjOV03LTWgkEXvLePribLlJNu4g0= github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60/go.mod h1:/7qKobTfbzBu7eSTVaXMTr56yTYk4j2Px6/8G+idxHo= github.com/ava-labs/libevm v1.13.14-0.2.0.release h1:uKGCc5/ceeBbfAPRVtBUxbQt50WzB2pEDb8Uy93ePgQ= diff --git a/proto/pb/vm/vm.pb.go b/proto/pb/vm/vm.pb.go index 239ac90a3299..9ad3b5d3b5d2 100644 --- a/proto/pb/vm/vm.pb.go +++ b/proto/pb/vm/vm.pb.go @@ -177,7 +177,7 @@ func (x StateSummaryAcceptResponse_Mode) Number() protoreflect.EnumNumber { // Deprecated: Use StateSummaryAcceptResponse_Mode.Descriptor instead. func (StateSummaryAcceptResponse_Mode) EnumDescriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{41, 0} + return file_vm_vm_proto_rawDescGZIP(), []int{42, 0} } type InitializeRequest struct { @@ -751,6 +751,53 @@ func (x *CreateHandlersResponse) GetHandlers() []*Handler { return nil } +type CreateHTTP2HandlerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // server_addr is the address of the gRPC server which serves the + // HTTP service + ServerAddr string `protobuf:"bytes,1,opt,name=server_addr,json=serverAddr,proto3" json:"server_addr,omitempty"` +} + +func (x *CreateHTTP2HandlerResponse) Reset() { + *x = CreateHTTP2HandlerResponse{} + mi := &file_vm_vm_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateHTTP2HandlerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateHTTP2HandlerResponse) ProtoMessage() {} + +func (x *CreateHTTP2HandlerResponse) ProtoReflect() protoreflect.Message { + mi := &file_vm_vm_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateHTTP2HandlerResponse.ProtoReflect.Descriptor instead. +func (*CreateHTTP2HandlerResponse) Descriptor() ([]byte, []int) { + return file_vm_vm_proto_rawDescGZIP(), []int{6} +} + +func (x *CreateHTTP2HandlerResponse) GetServerAddr() string { + if x != nil { + return x.ServerAddr + } + return "" +} + type Handler struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -764,7 +811,7 @@ type Handler struct { func (x *Handler) Reset() { *x = Handler{} - mi := &file_vm_vm_proto_msgTypes[6] + mi := &file_vm_vm_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -776,7 +823,7 @@ func (x *Handler) String() string { func (*Handler) ProtoMessage() {} func (x *Handler) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[6] + mi := &file_vm_vm_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -789,7 +836,7 @@ func (x *Handler) ProtoReflect() protoreflect.Message { // Deprecated: Use Handler.ProtoReflect.Descriptor instead. func (*Handler) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{6} + return file_vm_vm_proto_rawDescGZIP(), []int{7} } func (x *Handler) GetPrefix() string { @@ -816,7 +863,7 @@ type BuildBlockRequest struct { func (x *BuildBlockRequest) Reset() { *x = BuildBlockRequest{} - mi := &file_vm_vm_proto_msgTypes[7] + mi := &file_vm_vm_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -828,7 +875,7 @@ func (x *BuildBlockRequest) String() string { func (*BuildBlockRequest) ProtoMessage() {} func (x *BuildBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[7] + mi := &file_vm_vm_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -841,7 +888,7 @@ func (x *BuildBlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BuildBlockRequest.ProtoReflect.Descriptor instead. func (*BuildBlockRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{7} + return file_vm_vm_proto_rawDescGZIP(), []int{8} } func (x *BuildBlockRequest) GetPChainHeight() uint64 { @@ -867,7 +914,7 @@ type BuildBlockResponse struct { func (x *BuildBlockResponse) Reset() { *x = BuildBlockResponse{} - mi := &file_vm_vm_proto_msgTypes[8] + mi := &file_vm_vm_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -879,7 +926,7 @@ func (x *BuildBlockResponse) String() string { func (*BuildBlockResponse) ProtoMessage() {} func (x *BuildBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[8] + mi := &file_vm_vm_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -892,7 +939,7 @@ func (x *BuildBlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BuildBlockResponse.ProtoReflect.Descriptor instead. func (*BuildBlockResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{8} + return file_vm_vm_proto_rawDescGZIP(), []int{9} } func (x *BuildBlockResponse) GetId() []byte { @@ -947,7 +994,7 @@ type ParseBlockRequest struct { func (x *ParseBlockRequest) Reset() { *x = ParseBlockRequest{} - mi := &file_vm_vm_proto_msgTypes[9] + mi := &file_vm_vm_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -959,7 +1006,7 @@ func (x *ParseBlockRequest) String() string { func (*ParseBlockRequest) ProtoMessage() {} func (x *ParseBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[9] + mi := &file_vm_vm_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -972,7 +1019,7 @@ func (x *ParseBlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ParseBlockRequest.ProtoReflect.Descriptor instead. func (*ParseBlockRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{9} + return file_vm_vm_proto_rawDescGZIP(), []int{10} } func (x *ParseBlockRequest) GetBytes() []byte { @@ -996,7 +1043,7 @@ type ParseBlockResponse struct { func (x *ParseBlockResponse) Reset() { *x = ParseBlockResponse{} - mi := &file_vm_vm_proto_msgTypes[10] + mi := &file_vm_vm_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1008,7 +1055,7 @@ func (x *ParseBlockResponse) String() string { func (*ParseBlockResponse) ProtoMessage() {} func (x *ParseBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[10] + mi := &file_vm_vm_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1021,7 +1068,7 @@ func (x *ParseBlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ParseBlockResponse.ProtoReflect.Descriptor instead. func (*ParseBlockResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{10} + return file_vm_vm_proto_rawDescGZIP(), []int{11} } func (x *ParseBlockResponse) GetId() []byte { @@ -1069,7 +1116,7 @@ type GetBlockRequest struct { func (x *GetBlockRequest) Reset() { *x = GetBlockRequest{} - mi := &file_vm_vm_proto_msgTypes[11] + mi := &file_vm_vm_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1081,7 +1128,7 @@ func (x *GetBlockRequest) String() string { func (*GetBlockRequest) ProtoMessage() {} func (x *GetBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[11] + mi := &file_vm_vm_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1094,7 +1141,7 @@ func (x *GetBlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlockRequest.ProtoReflect.Descriptor instead. func (*GetBlockRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{11} + return file_vm_vm_proto_rawDescGZIP(), []int{12} } func (x *GetBlockRequest) GetId() []byte { @@ -1120,7 +1167,7 @@ type GetBlockResponse struct { func (x *GetBlockResponse) Reset() { *x = GetBlockResponse{} - mi := &file_vm_vm_proto_msgTypes[12] + mi := &file_vm_vm_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1132,7 +1179,7 @@ func (x *GetBlockResponse) String() string { func (*GetBlockResponse) ProtoMessage() {} func (x *GetBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[12] + mi := &file_vm_vm_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1145,7 +1192,7 @@ func (x *GetBlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlockResponse.ProtoReflect.Descriptor instead. func (*GetBlockResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{12} + return file_vm_vm_proto_rawDescGZIP(), []int{13} } func (x *GetBlockResponse) GetParentId() []byte { @@ -1200,7 +1247,7 @@ type SetPreferenceRequest struct { func (x *SetPreferenceRequest) Reset() { *x = SetPreferenceRequest{} - mi := &file_vm_vm_proto_msgTypes[13] + mi := &file_vm_vm_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1212,7 +1259,7 @@ func (x *SetPreferenceRequest) String() string { func (*SetPreferenceRequest) ProtoMessage() {} func (x *SetPreferenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[13] + mi := &file_vm_vm_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1225,7 +1272,7 @@ func (x *SetPreferenceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetPreferenceRequest.ProtoReflect.Descriptor instead. func (*SetPreferenceRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{13} + return file_vm_vm_proto_rawDescGZIP(), []int{14} } func (x *SetPreferenceRequest) GetId() []byte { @@ -1248,7 +1295,7 @@ type BlockVerifyRequest struct { func (x *BlockVerifyRequest) Reset() { *x = BlockVerifyRequest{} - mi := &file_vm_vm_proto_msgTypes[14] + mi := &file_vm_vm_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1260,7 +1307,7 @@ func (x *BlockVerifyRequest) String() string { func (*BlockVerifyRequest) ProtoMessage() {} func (x *BlockVerifyRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[14] + mi := &file_vm_vm_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1273,7 +1320,7 @@ func (x *BlockVerifyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockVerifyRequest.ProtoReflect.Descriptor instead. func (*BlockVerifyRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{14} + return file_vm_vm_proto_rawDescGZIP(), []int{15} } func (x *BlockVerifyRequest) GetBytes() []byte { @@ -1300,7 +1347,7 @@ type BlockVerifyResponse struct { func (x *BlockVerifyResponse) Reset() { *x = BlockVerifyResponse{} - mi := &file_vm_vm_proto_msgTypes[15] + mi := &file_vm_vm_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1312,7 +1359,7 @@ func (x *BlockVerifyResponse) String() string { func (*BlockVerifyResponse) ProtoMessage() {} func (x *BlockVerifyResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[15] + mi := &file_vm_vm_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1325,7 +1372,7 @@ func (x *BlockVerifyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockVerifyResponse.ProtoReflect.Descriptor instead. func (*BlockVerifyResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{15} + return file_vm_vm_proto_rawDescGZIP(), []int{16} } func (x *BlockVerifyResponse) GetTimestamp() *timestamppb.Timestamp { @@ -1345,7 +1392,7 @@ type BlockAcceptRequest struct { func (x *BlockAcceptRequest) Reset() { *x = BlockAcceptRequest{} - mi := &file_vm_vm_proto_msgTypes[16] + mi := &file_vm_vm_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1357,7 +1404,7 @@ func (x *BlockAcceptRequest) String() string { func (*BlockAcceptRequest) ProtoMessage() {} func (x *BlockAcceptRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[16] + mi := &file_vm_vm_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1370,7 +1417,7 @@ func (x *BlockAcceptRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockAcceptRequest.ProtoReflect.Descriptor instead. func (*BlockAcceptRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{16} + return file_vm_vm_proto_rawDescGZIP(), []int{17} } func (x *BlockAcceptRequest) GetId() []byte { @@ -1390,7 +1437,7 @@ type BlockRejectRequest struct { func (x *BlockRejectRequest) Reset() { *x = BlockRejectRequest{} - mi := &file_vm_vm_proto_msgTypes[17] + mi := &file_vm_vm_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1402,7 +1449,7 @@ func (x *BlockRejectRequest) String() string { func (*BlockRejectRequest) ProtoMessage() {} func (x *BlockRejectRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[17] + mi := &file_vm_vm_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1415,7 +1462,7 @@ func (x *BlockRejectRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockRejectRequest.ProtoReflect.Descriptor instead. func (*BlockRejectRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{17} + return file_vm_vm_proto_rawDescGZIP(), []int{18} } func (x *BlockRejectRequest) GetId() []byte { @@ -1435,7 +1482,7 @@ type HealthResponse struct { func (x *HealthResponse) Reset() { *x = HealthResponse{} - mi := &file_vm_vm_proto_msgTypes[18] + mi := &file_vm_vm_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1447,7 +1494,7 @@ func (x *HealthResponse) String() string { func (*HealthResponse) ProtoMessage() {} func (x *HealthResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[18] + mi := &file_vm_vm_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1460,7 +1507,7 @@ func (x *HealthResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HealthResponse.ProtoReflect.Descriptor instead. func (*HealthResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{18} + return file_vm_vm_proto_rawDescGZIP(), []int{19} } func (x *HealthResponse) GetDetails() []byte { @@ -1480,7 +1527,7 @@ type VersionResponse struct { func (x *VersionResponse) Reset() { *x = VersionResponse{} - mi := &file_vm_vm_proto_msgTypes[19] + mi := &file_vm_vm_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1492,7 +1539,7 @@ func (x *VersionResponse) String() string { func (*VersionResponse) ProtoMessage() {} func (x *VersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[19] + mi := &file_vm_vm_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1505,7 +1552,7 @@ func (x *VersionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VersionResponse.ProtoReflect.Descriptor instead. func (*VersionResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{19} + return file_vm_vm_proto_rawDescGZIP(), []int{20} } func (x *VersionResponse) GetVersion() string { @@ -1532,7 +1579,7 @@ type AppRequestMsg struct { func (x *AppRequestMsg) Reset() { *x = AppRequestMsg{} - mi := &file_vm_vm_proto_msgTypes[20] + mi := &file_vm_vm_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1544,7 +1591,7 @@ func (x *AppRequestMsg) String() string { func (*AppRequestMsg) ProtoMessage() {} func (x *AppRequestMsg) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[20] + mi := &file_vm_vm_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1557,7 +1604,7 @@ func (x *AppRequestMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use AppRequestMsg.ProtoReflect.Descriptor instead. func (*AppRequestMsg) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{20} + return file_vm_vm_proto_rawDescGZIP(), []int{21} } func (x *AppRequestMsg) GetNodeId() []byte { @@ -1605,7 +1652,7 @@ type AppRequestFailedMsg struct { func (x *AppRequestFailedMsg) Reset() { *x = AppRequestFailedMsg{} - mi := &file_vm_vm_proto_msgTypes[21] + mi := &file_vm_vm_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1617,7 +1664,7 @@ func (x *AppRequestFailedMsg) String() string { func (*AppRequestFailedMsg) ProtoMessage() {} func (x *AppRequestFailedMsg) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[21] + mi := &file_vm_vm_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1630,7 +1677,7 @@ func (x *AppRequestFailedMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use AppRequestFailedMsg.ProtoReflect.Descriptor instead. func (*AppRequestFailedMsg) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{21} + return file_vm_vm_proto_rawDescGZIP(), []int{22} } func (x *AppRequestFailedMsg) GetNodeId() []byte { @@ -1676,7 +1723,7 @@ type AppResponseMsg struct { func (x *AppResponseMsg) Reset() { *x = AppResponseMsg{} - mi := &file_vm_vm_proto_msgTypes[22] + mi := &file_vm_vm_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1688,7 +1735,7 @@ func (x *AppResponseMsg) String() string { func (*AppResponseMsg) ProtoMessage() {} func (x *AppResponseMsg) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[22] + mi := &file_vm_vm_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1701,7 +1748,7 @@ func (x *AppResponseMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use AppResponseMsg.ProtoReflect.Descriptor instead. func (*AppResponseMsg) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{22} + return file_vm_vm_proto_rawDescGZIP(), []int{23} } func (x *AppResponseMsg) GetNodeId() []byte { @@ -1738,7 +1785,7 @@ type AppGossipMsg struct { func (x *AppGossipMsg) Reset() { *x = AppGossipMsg{} - mi := &file_vm_vm_proto_msgTypes[23] + mi := &file_vm_vm_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1750,7 +1797,7 @@ func (x *AppGossipMsg) String() string { func (*AppGossipMsg) ProtoMessage() {} func (x *AppGossipMsg) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[23] + mi := &file_vm_vm_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1763,7 +1810,7 @@ func (x *AppGossipMsg) ProtoReflect() protoreflect.Message { // Deprecated: Use AppGossipMsg.ProtoReflect.Descriptor instead. func (*AppGossipMsg) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{23} + return file_vm_vm_proto_rawDescGZIP(), []int{24} } func (x *AppGossipMsg) GetNodeId() []byte { @@ -1796,7 +1843,7 @@ type ConnectedRequest struct { func (x *ConnectedRequest) Reset() { *x = ConnectedRequest{} - mi := &file_vm_vm_proto_msgTypes[24] + mi := &file_vm_vm_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1808,7 +1855,7 @@ func (x *ConnectedRequest) String() string { func (*ConnectedRequest) ProtoMessage() {} func (x *ConnectedRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[24] + mi := &file_vm_vm_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1821,7 +1868,7 @@ func (x *ConnectedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectedRequest.ProtoReflect.Descriptor instead. func (*ConnectedRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{24} + return file_vm_vm_proto_rawDescGZIP(), []int{25} } func (x *ConnectedRequest) GetNodeId() []byte { @@ -1869,7 +1916,7 @@ type DisconnectedRequest struct { func (x *DisconnectedRequest) Reset() { *x = DisconnectedRequest{} - mi := &file_vm_vm_proto_msgTypes[25] + mi := &file_vm_vm_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1881,7 +1928,7 @@ func (x *DisconnectedRequest) String() string { func (*DisconnectedRequest) ProtoMessage() {} func (x *DisconnectedRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[25] + mi := &file_vm_vm_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1894,7 +1941,7 @@ func (x *DisconnectedRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DisconnectedRequest.ProtoReflect.Descriptor instead. func (*DisconnectedRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{25} + return file_vm_vm_proto_rawDescGZIP(), []int{26} } func (x *DisconnectedRequest) GetNodeId() []byte { @@ -1917,7 +1964,7 @@ type GetAncestorsRequest struct { func (x *GetAncestorsRequest) Reset() { *x = GetAncestorsRequest{} - mi := &file_vm_vm_proto_msgTypes[26] + mi := &file_vm_vm_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1929,7 +1976,7 @@ func (x *GetAncestorsRequest) String() string { func (*GetAncestorsRequest) ProtoMessage() {} func (x *GetAncestorsRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[26] + mi := &file_vm_vm_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1942,7 +1989,7 @@ func (x *GetAncestorsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAncestorsRequest.ProtoReflect.Descriptor instead. func (*GetAncestorsRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{26} + return file_vm_vm_proto_rawDescGZIP(), []int{27} } func (x *GetAncestorsRequest) GetBlkId() []byte { @@ -1983,7 +2030,7 @@ type GetAncestorsResponse struct { func (x *GetAncestorsResponse) Reset() { *x = GetAncestorsResponse{} - mi := &file_vm_vm_proto_msgTypes[27] + mi := &file_vm_vm_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1995,7 +2042,7 @@ func (x *GetAncestorsResponse) String() string { func (*GetAncestorsResponse) ProtoMessage() {} func (x *GetAncestorsResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[27] + mi := &file_vm_vm_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2008,7 +2055,7 @@ func (x *GetAncestorsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAncestorsResponse.ProtoReflect.Descriptor instead. func (*GetAncestorsResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{27} + return file_vm_vm_proto_rawDescGZIP(), []int{28} } func (x *GetAncestorsResponse) GetBlksBytes() [][]byte { @@ -2028,7 +2075,7 @@ type BatchedParseBlockRequest struct { func (x *BatchedParseBlockRequest) Reset() { *x = BatchedParseBlockRequest{} - mi := &file_vm_vm_proto_msgTypes[28] + mi := &file_vm_vm_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2040,7 +2087,7 @@ func (x *BatchedParseBlockRequest) String() string { func (*BatchedParseBlockRequest) ProtoMessage() {} func (x *BatchedParseBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[28] + mi := &file_vm_vm_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2053,7 +2100,7 @@ func (x *BatchedParseBlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BatchedParseBlockRequest.ProtoReflect.Descriptor instead. func (*BatchedParseBlockRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{28} + return file_vm_vm_proto_rawDescGZIP(), []int{29} } func (x *BatchedParseBlockRequest) GetRequest() [][]byte { @@ -2073,7 +2120,7 @@ type BatchedParseBlockResponse struct { func (x *BatchedParseBlockResponse) Reset() { *x = BatchedParseBlockResponse{} - mi := &file_vm_vm_proto_msgTypes[29] + mi := &file_vm_vm_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2085,7 +2132,7 @@ func (x *BatchedParseBlockResponse) String() string { func (*BatchedParseBlockResponse) ProtoMessage() {} func (x *BatchedParseBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[29] + mi := &file_vm_vm_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2098,7 +2145,7 @@ func (x *BatchedParseBlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BatchedParseBlockResponse.ProtoReflect.Descriptor instead. func (*BatchedParseBlockResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{29} + return file_vm_vm_proto_rawDescGZIP(), []int{30} } func (x *BatchedParseBlockResponse) GetResponse() []*ParseBlockResponse { @@ -2118,7 +2165,7 @@ type GetBlockIDAtHeightRequest struct { func (x *GetBlockIDAtHeightRequest) Reset() { *x = GetBlockIDAtHeightRequest{} - mi := &file_vm_vm_proto_msgTypes[30] + mi := &file_vm_vm_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2130,7 +2177,7 @@ func (x *GetBlockIDAtHeightRequest) String() string { func (*GetBlockIDAtHeightRequest) ProtoMessage() {} func (x *GetBlockIDAtHeightRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[30] + mi := &file_vm_vm_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2143,7 +2190,7 @@ func (x *GetBlockIDAtHeightRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlockIDAtHeightRequest.ProtoReflect.Descriptor instead. func (*GetBlockIDAtHeightRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{30} + return file_vm_vm_proto_rawDescGZIP(), []int{31} } func (x *GetBlockIDAtHeightRequest) GetHeight() uint64 { @@ -2164,7 +2211,7 @@ type GetBlockIDAtHeightResponse struct { func (x *GetBlockIDAtHeightResponse) Reset() { *x = GetBlockIDAtHeightResponse{} - mi := &file_vm_vm_proto_msgTypes[31] + mi := &file_vm_vm_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2176,7 +2223,7 @@ func (x *GetBlockIDAtHeightResponse) String() string { func (*GetBlockIDAtHeightResponse) ProtoMessage() {} func (x *GetBlockIDAtHeightResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[31] + mi := &file_vm_vm_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2189,7 +2236,7 @@ func (x *GetBlockIDAtHeightResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBlockIDAtHeightResponse.ProtoReflect.Descriptor instead. func (*GetBlockIDAtHeightResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{31} + return file_vm_vm_proto_rawDescGZIP(), []int{32} } func (x *GetBlockIDAtHeightResponse) GetBlkId() []byte { @@ -2216,7 +2263,7 @@ type GatherResponse struct { func (x *GatherResponse) Reset() { *x = GatherResponse{} - mi := &file_vm_vm_proto_msgTypes[32] + mi := &file_vm_vm_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2228,7 +2275,7 @@ func (x *GatherResponse) String() string { func (*GatherResponse) ProtoMessage() {} func (x *GatherResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[32] + mi := &file_vm_vm_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2241,7 +2288,7 @@ func (x *GatherResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GatherResponse.ProtoReflect.Descriptor instead. func (*GatherResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{32} + return file_vm_vm_proto_rawDescGZIP(), []int{33} } func (x *GatherResponse) GetMetricFamilies() []*_go.MetricFamily { @@ -2262,7 +2309,7 @@ type StateSyncEnabledResponse struct { func (x *StateSyncEnabledResponse) Reset() { *x = StateSyncEnabledResponse{} - mi := &file_vm_vm_proto_msgTypes[33] + mi := &file_vm_vm_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2274,7 +2321,7 @@ func (x *StateSyncEnabledResponse) String() string { func (*StateSyncEnabledResponse) ProtoMessage() {} func (x *StateSyncEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[33] + mi := &file_vm_vm_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2287,7 +2334,7 @@ func (x *StateSyncEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSyncEnabledResponse.ProtoReflect.Descriptor instead. func (*StateSyncEnabledResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{33} + return file_vm_vm_proto_rawDescGZIP(), []int{34} } func (x *StateSyncEnabledResponse) GetEnabled() bool { @@ -2317,7 +2364,7 @@ type GetOngoingSyncStateSummaryResponse struct { func (x *GetOngoingSyncStateSummaryResponse) Reset() { *x = GetOngoingSyncStateSummaryResponse{} - mi := &file_vm_vm_proto_msgTypes[34] + mi := &file_vm_vm_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2329,7 +2376,7 @@ func (x *GetOngoingSyncStateSummaryResponse) String() string { func (*GetOngoingSyncStateSummaryResponse) ProtoMessage() {} func (x *GetOngoingSyncStateSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[34] + mi := &file_vm_vm_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2342,7 +2389,7 @@ func (x *GetOngoingSyncStateSummaryResponse) ProtoReflect() protoreflect.Message // Deprecated: Use GetOngoingSyncStateSummaryResponse.ProtoReflect.Descriptor instead. func (*GetOngoingSyncStateSummaryResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{34} + return file_vm_vm_proto_rawDescGZIP(), []int{35} } func (x *GetOngoingSyncStateSummaryResponse) GetId() []byte { @@ -2386,7 +2433,7 @@ type GetLastStateSummaryResponse struct { func (x *GetLastStateSummaryResponse) Reset() { *x = GetLastStateSummaryResponse{} - mi := &file_vm_vm_proto_msgTypes[35] + mi := &file_vm_vm_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2398,7 +2445,7 @@ func (x *GetLastStateSummaryResponse) String() string { func (*GetLastStateSummaryResponse) ProtoMessage() {} func (x *GetLastStateSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[35] + mi := &file_vm_vm_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2411,7 +2458,7 @@ func (x *GetLastStateSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLastStateSummaryResponse.ProtoReflect.Descriptor instead. func (*GetLastStateSummaryResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{35} + return file_vm_vm_proto_rawDescGZIP(), []int{36} } func (x *GetLastStateSummaryResponse) GetId() []byte { @@ -2452,7 +2499,7 @@ type ParseStateSummaryRequest struct { func (x *ParseStateSummaryRequest) Reset() { *x = ParseStateSummaryRequest{} - mi := &file_vm_vm_proto_msgTypes[36] + mi := &file_vm_vm_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2464,7 +2511,7 @@ func (x *ParseStateSummaryRequest) String() string { func (*ParseStateSummaryRequest) ProtoMessage() {} func (x *ParseStateSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[36] + mi := &file_vm_vm_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2477,7 +2524,7 @@ func (x *ParseStateSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ParseStateSummaryRequest.ProtoReflect.Descriptor instead. func (*ParseStateSummaryRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{36} + return file_vm_vm_proto_rawDescGZIP(), []int{37} } func (x *ParseStateSummaryRequest) GetBytes() []byte { @@ -2499,7 +2546,7 @@ type ParseStateSummaryResponse struct { func (x *ParseStateSummaryResponse) Reset() { *x = ParseStateSummaryResponse{} - mi := &file_vm_vm_proto_msgTypes[37] + mi := &file_vm_vm_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2511,7 +2558,7 @@ func (x *ParseStateSummaryResponse) String() string { func (*ParseStateSummaryResponse) ProtoMessage() {} func (x *ParseStateSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[37] + mi := &file_vm_vm_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2524,7 +2571,7 @@ func (x *ParseStateSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ParseStateSummaryResponse.ProtoReflect.Descriptor instead. func (*ParseStateSummaryResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{37} + return file_vm_vm_proto_rawDescGZIP(), []int{38} } func (x *ParseStateSummaryResponse) GetId() []byte { @@ -2558,7 +2605,7 @@ type GetStateSummaryRequest struct { func (x *GetStateSummaryRequest) Reset() { *x = GetStateSummaryRequest{} - mi := &file_vm_vm_proto_msgTypes[38] + mi := &file_vm_vm_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2570,7 +2617,7 @@ func (x *GetStateSummaryRequest) String() string { func (*GetStateSummaryRequest) ProtoMessage() {} func (x *GetStateSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[38] + mi := &file_vm_vm_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2583,7 +2630,7 @@ func (x *GetStateSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStateSummaryRequest.ProtoReflect.Descriptor instead. func (*GetStateSummaryRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{38} + return file_vm_vm_proto_rawDescGZIP(), []int{39} } func (x *GetStateSummaryRequest) GetHeight() uint64 { @@ -2605,7 +2652,7 @@ type GetStateSummaryResponse struct { func (x *GetStateSummaryResponse) Reset() { *x = GetStateSummaryResponse{} - mi := &file_vm_vm_proto_msgTypes[39] + mi := &file_vm_vm_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2617,7 +2664,7 @@ func (x *GetStateSummaryResponse) String() string { func (*GetStateSummaryResponse) ProtoMessage() {} func (x *GetStateSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[39] + mi := &file_vm_vm_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2630,7 +2677,7 @@ func (x *GetStateSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStateSummaryResponse.ProtoReflect.Descriptor instead. func (*GetStateSummaryResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{39} + return file_vm_vm_proto_rawDescGZIP(), []int{40} } func (x *GetStateSummaryResponse) GetId() []byte { @@ -2664,7 +2711,7 @@ type StateSummaryAcceptRequest struct { func (x *StateSummaryAcceptRequest) Reset() { *x = StateSummaryAcceptRequest{} - mi := &file_vm_vm_proto_msgTypes[40] + mi := &file_vm_vm_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2676,7 +2723,7 @@ func (x *StateSummaryAcceptRequest) String() string { func (*StateSummaryAcceptRequest) ProtoMessage() {} func (x *StateSummaryAcceptRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[40] + mi := &file_vm_vm_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2689,7 +2736,7 @@ func (x *StateSummaryAcceptRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSummaryAcceptRequest.ProtoReflect.Descriptor instead. func (*StateSummaryAcceptRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{40} + return file_vm_vm_proto_rawDescGZIP(), []int{41} } func (x *StateSummaryAcceptRequest) GetBytes() []byte { @@ -2710,7 +2757,7 @@ type StateSummaryAcceptResponse struct { func (x *StateSummaryAcceptResponse) Reset() { *x = StateSummaryAcceptResponse{} - mi := &file_vm_vm_proto_msgTypes[41] + mi := &file_vm_vm_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2722,7 +2769,7 @@ func (x *StateSummaryAcceptResponse) String() string { func (*StateSummaryAcceptResponse) ProtoMessage() {} func (x *StateSummaryAcceptResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[41] + mi := &file_vm_vm_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2735,7 +2782,7 @@ func (x *StateSummaryAcceptResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSummaryAcceptResponse.ProtoReflect.Descriptor instead. func (*StateSummaryAcceptResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{41} + return file_vm_vm_proto_rawDescGZIP(), []int{42} } func (x *StateSummaryAcceptResponse) GetMode() StateSummaryAcceptResponse_Mode { @@ -2904,22 +2951,41 @@ var file_vm_vm_proto_rawDesc = []byte{ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x08, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x76, 0x6d, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x52, 0x08, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, - 0x22, 0x42, 0x0a, 0x07, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x70, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x41, 0x64, 0x64, 0x72, 0x22, 0x51, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x5f, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xd9, 0x01, 0x0a, 0x12, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x22, 0x3d, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, 0x32, 0x48, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x22, + 0x42, 0x0a, 0x07, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, + 0x64, 0x64, 0x72, 0x22, 0x51, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x5f, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x48, 0x00, 0x52, 0x0c, 0x70, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0xd9, 0x01, 0x0a, 0x12, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x2e, 0x0a, 0x13, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x77, 0x69, 0x74, + 0x68, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x22, 0x29, 0x0a, 0x11, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0xc3, 0x01, + 0x0a, 0x12, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, @@ -2927,334 +2993,323 @@ var file_vm_vm_proto_rawDesc = []byte{ 0x61, 0x6d, 0x70, 0x12, 0x2e, 0x0a, 0x13, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x22, 0x29, 0x0a, 0x11, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0xc3, - 0x01, 0x0a, 0x12, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2e, 0x0a, 0x13, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x22, 0x21, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0xe4, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, - 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, - 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x2e, - 0x0a, 0x13, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x76, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x26, - 0x0a, 0x14, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, + 0x65, 0x78, 0x74, 0x22, 0x21, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, - 0x0f, 0x5f, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x22, 0x4f, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x22, 0x24, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x24, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2a, 0x0a, - 0x0e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x2b, 0x0a, 0x0f, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x99, 0x01, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 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, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, - 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x91, 0x01, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, - 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, - 0x65, 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, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, - 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x64, 0x0a, 0x0e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 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, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x0a, 0x0c, - 0x41, 0x70, 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, - 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, - 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x81, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, - 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, - 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, - 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x22, 0x2e, 0x0a, 0x13, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0xb3, 0x01, 0x0a, 0x13, - 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x6c, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6b, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, - 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4e, 0x75, 0x6d, - 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x6d, 0x61, 0x78, 0x5f, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x76, 0x61, 0x6c, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x74, 0x72, 0x69, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, - 0x65, 0x22, 0x35, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6b, - 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x62, - 0x6c, 0x6b, 0x73, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x34, 0x0a, 0x18, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4f, - 0x0a, 0x19, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x33, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x22, 0x50, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x6c, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6b, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x5d, 0x0a, 0x0e, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, - 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, - 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, 0x6d, - 0x69, 0x6c, 0x69, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x18, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, - 0x6e, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x65, - 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x7f, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x4f, - 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, - 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, - 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x78, 0x0a, 0x1b, 0x47, 0x65, 0x74, - 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, - 0x65, 0x72, 0x72, 0x22, 0x30, 0x0a, 0x18, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0x60, 0x0a, 0x19, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x30, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x5c, 0x0a, 0x17, 0x47, 0x65, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x31, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x1a, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, - 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, - 0x51, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x4f, 0x44, 0x45, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, - 0x0c, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x0f, 0x0a, 0x0b, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x02, - 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, - 0x10, 0x03, 0x2a, 0x65, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, - 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, - 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x53, - 0x54, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x50, 0x49, - 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4e, 0x4f, - 0x52, 0x4d, 0x41, 0x4c, 0x5f, 0x4f, 0x50, 0x10, 0x03, 0x2a, 0x6b, 0x0a, 0x05, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, - 0x12, 0x24, 0x0a, 0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, - 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45, - 0x4e, 0x54, 0x45, 0x44, 0x10, 0x03, 0x32, 0x91, 0x0f, 0x0a, 0x02, 0x56, 0x4d, 0x12, 0x3b, 0x0a, - 0x0a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x15, 0x2e, 0x76, 0x6d, - 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x53, 0x65, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, - 0x2e, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, - 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x12, 0x14, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, - 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x17, - 0x2e, 0x76, 0x6d, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x3b, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, - 0x76, 0x6d, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0a, - 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, - 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, 0x2e, - 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x41, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x18, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, - 0x6d, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x11, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, - 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x10, 0x41, 0x70, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x17, - 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x39, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, - 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, - 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x41, 0x70, - 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x10, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, - 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x34, 0x0a, 0x06, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x6e, - 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x18, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, - 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, - 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x12, - 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x12, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, + 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0xe4, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, + 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x2e, 0x0a, + 0x13, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x76, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x26, 0x0a, + 0x14, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x12, 0x29, 0x0a, 0x0e, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, + 0x5f, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, + 0x4f, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x22, 0x24, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x24, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, + 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2a, 0x0a, 0x0e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x2b, 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x99, 0x01, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 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, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x64, + 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x91, 0x01, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, + 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, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x64, 0x0a, 0x0e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 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, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x0a, 0x0c, 0x41, + 0x70, 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x4d, 0x73, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x81, 0x01, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, + 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, + 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x22, 0x2e, 0x0a, 0x13, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0xb3, 0x01, 0x0a, 0x13, 0x47, + 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x6c, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6b, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, + 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4e, 0x75, 0x6d, 0x12, + 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x6d, 0x61, 0x78, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x76, 0x61, 0x6c, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6d, 0x61, 0x78, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x74, 0x72, 0x69, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, + 0x22, 0x35, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6b, 0x73, + 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, + 0x6b, 0x73, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x34, 0x0a, 0x18, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4f, 0x0a, + 0x19, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, + 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, + 0x0a, 0x19, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x22, 0x50, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, - 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x1a, 0x47, - 0x65, 0x74, 0x4f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x26, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, - 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x47, 0x65, 0x74, - 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, - 0x74, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x50, 0x61, 0x72, - 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, - 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, - 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x47, - 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1a, - 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x6d, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x65, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x6c, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6b, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x5d, 0x0a, 0x0e, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, 0x6d, 0x69, + 0x6c, 0x69, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x18, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, + 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x7f, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x4f, 0x6e, + 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, + 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x78, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x4c, + 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, + 0x72, 0x72, 0x22, 0x30, 0x0a, 0x18, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x22, 0x60, 0x0a, 0x19, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x30, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x5c, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x31, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x1a, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, + 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x51, + 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, + 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0f, + 0x0a, 0x0b, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x02, 0x12, + 0x10, 0x0a, 0x0c, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, + 0x03, 0x2a, 0x65, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, + 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, + 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, + 0x41, 0x54, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x50, 0x49, 0x4e, + 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4e, 0x4f, 0x52, + 0x4d, 0x41, 0x4c, 0x5f, 0x4f, 0x50, 0x10, 0x03, 0x2a, 0x6b, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, + 0x24, 0x0a, 0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, + 0x59, 0x4e, 0x43, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45, 0x4e, + 0x54, 0x45, 0x44, 0x10, 0x03, 0x32, 0xdf, 0x0f, 0x0a, 0x02, 0x56, 0x4d, 0x12, 0x3b, 0x0a, 0x0a, + 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, + 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x53, 0x65, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, 0x2e, + 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, 0x0e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, - 0x65, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, + 0x32, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x54, 0x54, 0x50, + 0x32, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x39, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x14, 0x2e, + 0x76, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0c, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x17, 0x2e, 0x76, 0x6d, + 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0a, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, + 0x0d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x18, + 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, + 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x76, + 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x17, 0x2e, 0x76, 0x6d, + 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x0b, + 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x2e, 0x76, 0x6d, + 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x47, 0x6f, + 0x73, 0x73, 0x69, 0x70, 0x12, 0x10, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x47, 0x6f, 0x73, + 0x73, 0x69, 0x70, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x34, + 0x0a, 0x06, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, + 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, + 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1c, 0x2e, 0x76, + 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, + 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, + 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, + 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, + 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, + 0x0a, 0x10, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x76, 0x6d, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4f, + 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x26, + 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, + 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x53, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x2e, 0x76, 0x6d, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, - 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 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, 0x76, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, + 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, 0x2e, 0x76, 0x6d, + 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1a, 0x2e, 0x76, 0x6d, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, 0x6d, + 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6a, 0x65, + 0x63, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6a, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x53, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 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, 0x76, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3270,7 +3325,7 @@ func file_vm_vm_proto_rawDescGZIP() []byte { } var file_vm_vm_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_vm_vm_proto_msgTypes = make([]protoimpl.MessageInfo, 42) +var file_vm_vm_proto_msgTypes = make([]protoimpl.MessageInfo, 43) var file_vm_vm_proto_goTypes = []any{ (State)(0), // 0: vm.State (Error)(0), // 1: vm.Error @@ -3281,75 +3336,76 @@ var file_vm_vm_proto_goTypes = []any{ (*SetStateRequest)(nil), // 6: vm.SetStateRequest (*SetStateResponse)(nil), // 7: vm.SetStateResponse (*CreateHandlersResponse)(nil), // 8: vm.CreateHandlersResponse - (*Handler)(nil), // 9: vm.Handler - (*BuildBlockRequest)(nil), // 10: vm.BuildBlockRequest - (*BuildBlockResponse)(nil), // 11: vm.BuildBlockResponse - (*ParseBlockRequest)(nil), // 12: vm.ParseBlockRequest - (*ParseBlockResponse)(nil), // 13: vm.ParseBlockResponse - (*GetBlockRequest)(nil), // 14: vm.GetBlockRequest - (*GetBlockResponse)(nil), // 15: vm.GetBlockResponse - (*SetPreferenceRequest)(nil), // 16: vm.SetPreferenceRequest - (*BlockVerifyRequest)(nil), // 17: vm.BlockVerifyRequest - (*BlockVerifyResponse)(nil), // 18: vm.BlockVerifyResponse - (*BlockAcceptRequest)(nil), // 19: vm.BlockAcceptRequest - (*BlockRejectRequest)(nil), // 20: vm.BlockRejectRequest - (*HealthResponse)(nil), // 21: vm.HealthResponse - (*VersionResponse)(nil), // 22: vm.VersionResponse - (*AppRequestMsg)(nil), // 23: vm.AppRequestMsg - (*AppRequestFailedMsg)(nil), // 24: vm.AppRequestFailedMsg - (*AppResponseMsg)(nil), // 25: vm.AppResponseMsg - (*AppGossipMsg)(nil), // 26: vm.AppGossipMsg - (*ConnectedRequest)(nil), // 27: vm.ConnectedRequest - (*DisconnectedRequest)(nil), // 28: vm.DisconnectedRequest - (*GetAncestorsRequest)(nil), // 29: vm.GetAncestorsRequest - (*GetAncestorsResponse)(nil), // 30: vm.GetAncestorsResponse - (*BatchedParseBlockRequest)(nil), // 31: vm.BatchedParseBlockRequest - (*BatchedParseBlockResponse)(nil), // 32: vm.BatchedParseBlockResponse - (*GetBlockIDAtHeightRequest)(nil), // 33: vm.GetBlockIDAtHeightRequest - (*GetBlockIDAtHeightResponse)(nil), // 34: vm.GetBlockIDAtHeightResponse - (*GatherResponse)(nil), // 35: vm.GatherResponse - (*StateSyncEnabledResponse)(nil), // 36: vm.StateSyncEnabledResponse - (*GetOngoingSyncStateSummaryResponse)(nil), // 37: vm.GetOngoingSyncStateSummaryResponse - (*GetLastStateSummaryResponse)(nil), // 38: vm.GetLastStateSummaryResponse - (*ParseStateSummaryRequest)(nil), // 39: vm.ParseStateSummaryRequest - (*ParseStateSummaryResponse)(nil), // 40: vm.ParseStateSummaryResponse - (*GetStateSummaryRequest)(nil), // 41: vm.GetStateSummaryRequest - (*GetStateSummaryResponse)(nil), // 42: vm.GetStateSummaryResponse - (*StateSummaryAcceptRequest)(nil), // 43: vm.StateSummaryAcceptRequest - (*StateSummaryAcceptResponse)(nil), // 44: vm.StateSummaryAcceptResponse - (*timestamppb.Timestamp)(nil), // 45: google.protobuf.Timestamp - (*_go.MetricFamily)(nil), // 46: io.prometheus.client.MetricFamily - (*emptypb.Empty)(nil), // 47: google.protobuf.Empty + (*CreateHTTP2HandlerResponse)(nil), // 9: vm.CreateHTTP2HandlerResponse + (*Handler)(nil), // 10: vm.Handler + (*BuildBlockRequest)(nil), // 11: vm.BuildBlockRequest + (*BuildBlockResponse)(nil), // 12: vm.BuildBlockResponse + (*ParseBlockRequest)(nil), // 13: vm.ParseBlockRequest + (*ParseBlockResponse)(nil), // 14: vm.ParseBlockResponse + (*GetBlockRequest)(nil), // 15: vm.GetBlockRequest + (*GetBlockResponse)(nil), // 16: vm.GetBlockResponse + (*SetPreferenceRequest)(nil), // 17: vm.SetPreferenceRequest + (*BlockVerifyRequest)(nil), // 18: vm.BlockVerifyRequest + (*BlockVerifyResponse)(nil), // 19: vm.BlockVerifyResponse + (*BlockAcceptRequest)(nil), // 20: vm.BlockAcceptRequest + (*BlockRejectRequest)(nil), // 21: vm.BlockRejectRequest + (*HealthResponse)(nil), // 22: vm.HealthResponse + (*VersionResponse)(nil), // 23: vm.VersionResponse + (*AppRequestMsg)(nil), // 24: vm.AppRequestMsg + (*AppRequestFailedMsg)(nil), // 25: vm.AppRequestFailedMsg + (*AppResponseMsg)(nil), // 26: vm.AppResponseMsg + (*AppGossipMsg)(nil), // 27: vm.AppGossipMsg + (*ConnectedRequest)(nil), // 28: vm.ConnectedRequest + (*DisconnectedRequest)(nil), // 29: vm.DisconnectedRequest + (*GetAncestorsRequest)(nil), // 30: vm.GetAncestorsRequest + (*GetAncestorsResponse)(nil), // 31: vm.GetAncestorsResponse + (*BatchedParseBlockRequest)(nil), // 32: vm.BatchedParseBlockRequest + (*BatchedParseBlockResponse)(nil), // 33: vm.BatchedParseBlockResponse + (*GetBlockIDAtHeightRequest)(nil), // 34: vm.GetBlockIDAtHeightRequest + (*GetBlockIDAtHeightResponse)(nil), // 35: vm.GetBlockIDAtHeightResponse + (*GatherResponse)(nil), // 36: vm.GatherResponse + (*StateSyncEnabledResponse)(nil), // 37: vm.StateSyncEnabledResponse + (*GetOngoingSyncStateSummaryResponse)(nil), // 38: vm.GetOngoingSyncStateSummaryResponse + (*GetLastStateSummaryResponse)(nil), // 39: vm.GetLastStateSummaryResponse + (*ParseStateSummaryRequest)(nil), // 40: vm.ParseStateSummaryRequest + (*ParseStateSummaryResponse)(nil), // 41: vm.ParseStateSummaryResponse + (*GetStateSummaryRequest)(nil), // 42: vm.GetStateSummaryRequest + (*GetStateSummaryResponse)(nil), // 43: vm.GetStateSummaryResponse + (*StateSummaryAcceptRequest)(nil), // 44: vm.StateSummaryAcceptRequest + (*StateSummaryAcceptResponse)(nil), // 45: vm.StateSummaryAcceptResponse + (*timestamppb.Timestamp)(nil), // 46: google.protobuf.Timestamp + (*_go.MetricFamily)(nil), // 47: io.prometheus.client.MetricFamily + (*emptypb.Empty)(nil), // 48: google.protobuf.Empty } var file_vm_vm_proto_depIdxs = []int32{ 4, // 0: vm.InitializeRequest.network_upgrades:type_name -> vm.NetworkUpgrades - 45, // 1: vm.NetworkUpgrades.apricot_phase_1_time:type_name -> google.protobuf.Timestamp - 45, // 2: vm.NetworkUpgrades.apricot_phase_2_time:type_name -> google.protobuf.Timestamp - 45, // 3: vm.NetworkUpgrades.apricot_phase_3_time:type_name -> google.protobuf.Timestamp - 45, // 4: vm.NetworkUpgrades.apricot_phase_4_time:type_name -> google.protobuf.Timestamp - 45, // 5: vm.NetworkUpgrades.apricot_phase_5_time:type_name -> google.protobuf.Timestamp - 45, // 6: vm.NetworkUpgrades.apricot_phase_pre_6_time:type_name -> google.protobuf.Timestamp - 45, // 7: vm.NetworkUpgrades.apricot_phase_6_time:type_name -> google.protobuf.Timestamp - 45, // 8: vm.NetworkUpgrades.apricot_phase_post_6_time:type_name -> google.protobuf.Timestamp - 45, // 9: vm.NetworkUpgrades.banff_time:type_name -> google.protobuf.Timestamp - 45, // 10: vm.NetworkUpgrades.cortina_time:type_name -> google.protobuf.Timestamp - 45, // 11: vm.NetworkUpgrades.durango_time:type_name -> google.protobuf.Timestamp - 45, // 12: vm.NetworkUpgrades.etna_time:type_name -> google.protobuf.Timestamp - 45, // 13: vm.NetworkUpgrades.fortuna_time:type_name -> google.protobuf.Timestamp - 45, // 14: vm.NetworkUpgrades.granite_time:type_name -> google.protobuf.Timestamp - 45, // 15: vm.InitializeResponse.timestamp:type_name -> google.protobuf.Timestamp + 46, // 1: vm.NetworkUpgrades.apricot_phase_1_time:type_name -> google.protobuf.Timestamp + 46, // 2: vm.NetworkUpgrades.apricot_phase_2_time:type_name -> google.protobuf.Timestamp + 46, // 3: vm.NetworkUpgrades.apricot_phase_3_time:type_name -> google.protobuf.Timestamp + 46, // 4: vm.NetworkUpgrades.apricot_phase_4_time:type_name -> google.protobuf.Timestamp + 46, // 5: vm.NetworkUpgrades.apricot_phase_5_time:type_name -> google.protobuf.Timestamp + 46, // 6: vm.NetworkUpgrades.apricot_phase_pre_6_time:type_name -> google.protobuf.Timestamp + 46, // 7: vm.NetworkUpgrades.apricot_phase_6_time:type_name -> google.protobuf.Timestamp + 46, // 8: vm.NetworkUpgrades.apricot_phase_post_6_time:type_name -> google.protobuf.Timestamp + 46, // 9: vm.NetworkUpgrades.banff_time:type_name -> google.protobuf.Timestamp + 46, // 10: vm.NetworkUpgrades.cortina_time:type_name -> google.protobuf.Timestamp + 46, // 11: vm.NetworkUpgrades.durango_time:type_name -> google.protobuf.Timestamp + 46, // 12: vm.NetworkUpgrades.etna_time:type_name -> google.protobuf.Timestamp + 46, // 13: vm.NetworkUpgrades.fortuna_time:type_name -> google.protobuf.Timestamp + 46, // 14: vm.NetworkUpgrades.granite_time:type_name -> google.protobuf.Timestamp + 46, // 15: vm.InitializeResponse.timestamp:type_name -> google.protobuf.Timestamp 0, // 16: vm.SetStateRequest.state:type_name -> vm.State - 45, // 17: vm.SetStateResponse.timestamp:type_name -> google.protobuf.Timestamp - 9, // 18: vm.CreateHandlersResponse.handlers:type_name -> vm.Handler - 45, // 19: vm.BuildBlockResponse.timestamp:type_name -> google.protobuf.Timestamp - 45, // 20: vm.ParseBlockResponse.timestamp:type_name -> google.protobuf.Timestamp - 45, // 21: vm.GetBlockResponse.timestamp:type_name -> google.protobuf.Timestamp + 46, // 17: vm.SetStateResponse.timestamp:type_name -> google.protobuf.Timestamp + 10, // 18: vm.CreateHandlersResponse.handlers:type_name -> vm.Handler + 46, // 19: vm.BuildBlockResponse.timestamp:type_name -> google.protobuf.Timestamp + 46, // 20: vm.ParseBlockResponse.timestamp:type_name -> google.protobuf.Timestamp + 46, // 21: vm.GetBlockResponse.timestamp:type_name -> google.protobuf.Timestamp 1, // 22: vm.GetBlockResponse.err:type_name -> vm.Error - 45, // 23: vm.BlockVerifyResponse.timestamp:type_name -> google.protobuf.Timestamp - 45, // 24: vm.AppRequestMsg.deadline:type_name -> google.protobuf.Timestamp - 13, // 25: vm.BatchedParseBlockResponse.response:type_name -> vm.ParseBlockResponse + 46, // 23: vm.BlockVerifyResponse.timestamp:type_name -> google.protobuf.Timestamp + 46, // 24: vm.AppRequestMsg.deadline:type_name -> google.protobuf.Timestamp + 14, // 25: vm.BatchedParseBlockResponse.response:type_name -> vm.ParseBlockResponse 1, // 26: vm.GetBlockIDAtHeightResponse.err:type_name -> vm.Error - 46, // 27: vm.GatherResponse.metric_families:type_name -> io.prometheus.client.MetricFamily + 47, // 27: vm.GatherResponse.metric_families:type_name -> io.prometheus.client.MetricFamily 1, // 28: vm.StateSyncEnabledResponse.err:type_name -> vm.Error 1, // 29: vm.GetOngoingSyncStateSummaryResponse.err:type_name -> vm.Error 1, // 30: vm.GetLastStateSummaryResponse.err:type_name -> vm.Error @@ -3359,64 +3415,66 @@ var file_vm_vm_proto_depIdxs = []int32{ 1, // 34: vm.StateSummaryAcceptResponse.err:type_name -> vm.Error 3, // 35: vm.VM.Initialize:input_type -> vm.InitializeRequest 6, // 36: vm.VM.SetState:input_type -> vm.SetStateRequest - 47, // 37: vm.VM.Shutdown:input_type -> google.protobuf.Empty - 47, // 38: vm.VM.CreateHandlers:input_type -> google.protobuf.Empty - 27, // 39: vm.VM.Connected:input_type -> vm.ConnectedRequest - 28, // 40: vm.VM.Disconnected:input_type -> vm.DisconnectedRequest - 10, // 41: vm.VM.BuildBlock:input_type -> vm.BuildBlockRequest - 12, // 42: vm.VM.ParseBlock:input_type -> vm.ParseBlockRequest - 14, // 43: vm.VM.GetBlock:input_type -> vm.GetBlockRequest - 16, // 44: vm.VM.SetPreference:input_type -> vm.SetPreferenceRequest - 47, // 45: vm.VM.Health:input_type -> google.protobuf.Empty - 47, // 46: vm.VM.Version:input_type -> google.protobuf.Empty - 23, // 47: vm.VM.AppRequest:input_type -> vm.AppRequestMsg - 24, // 48: vm.VM.AppRequestFailed:input_type -> vm.AppRequestFailedMsg - 25, // 49: vm.VM.AppResponse:input_type -> vm.AppResponseMsg - 26, // 50: vm.VM.AppGossip:input_type -> vm.AppGossipMsg - 47, // 51: vm.VM.Gather:input_type -> google.protobuf.Empty - 29, // 52: vm.VM.GetAncestors:input_type -> vm.GetAncestorsRequest - 31, // 53: vm.VM.BatchedParseBlock:input_type -> vm.BatchedParseBlockRequest - 33, // 54: vm.VM.GetBlockIDAtHeight:input_type -> vm.GetBlockIDAtHeightRequest - 47, // 55: vm.VM.StateSyncEnabled:input_type -> google.protobuf.Empty - 47, // 56: vm.VM.GetOngoingSyncStateSummary:input_type -> google.protobuf.Empty - 47, // 57: vm.VM.GetLastStateSummary:input_type -> google.protobuf.Empty - 39, // 58: vm.VM.ParseStateSummary:input_type -> vm.ParseStateSummaryRequest - 41, // 59: vm.VM.GetStateSummary:input_type -> vm.GetStateSummaryRequest - 17, // 60: vm.VM.BlockVerify:input_type -> vm.BlockVerifyRequest - 19, // 61: vm.VM.BlockAccept:input_type -> vm.BlockAcceptRequest - 20, // 62: vm.VM.BlockReject:input_type -> vm.BlockRejectRequest - 43, // 63: vm.VM.StateSummaryAccept:input_type -> vm.StateSummaryAcceptRequest - 5, // 64: vm.VM.Initialize:output_type -> vm.InitializeResponse - 7, // 65: vm.VM.SetState:output_type -> vm.SetStateResponse - 47, // 66: vm.VM.Shutdown:output_type -> google.protobuf.Empty - 8, // 67: vm.VM.CreateHandlers:output_type -> vm.CreateHandlersResponse - 47, // 68: vm.VM.Connected:output_type -> google.protobuf.Empty - 47, // 69: vm.VM.Disconnected:output_type -> google.protobuf.Empty - 11, // 70: vm.VM.BuildBlock:output_type -> vm.BuildBlockResponse - 13, // 71: vm.VM.ParseBlock:output_type -> vm.ParseBlockResponse - 15, // 72: vm.VM.GetBlock:output_type -> vm.GetBlockResponse - 47, // 73: vm.VM.SetPreference:output_type -> google.protobuf.Empty - 21, // 74: vm.VM.Health:output_type -> vm.HealthResponse - 22, // 75: vm.VM.Version:output_type -> vm.VersionResponse - 47, // 76: vm.VM.AppRequest:output_type -> google.protobuf.Empty - 47, // 77: vm.VM.AppRequestFailed:output_type -> google.protobuf.Empty - 47, // 78: vm.VM.AppResponse:output_type -> google.protobuf.Empty - 47, // 79: vm.VM.AppGossip:output_type -> google.protobuf.Empty - 35, // 80: vm.VM.Gather:output_type -> vm.GatherResponse - 30, // 81: vm.VM.GetAncestors:output_type -> vm.GetAncestorsResponse - 32, // 82: vm.VM.BatchedParseBlock:output_type -> vm.BatchedParseBlockResponse - 34, // 83: vm.VM.GetBlockIDAtHeight:output_type -> vm.GetBlockIDAtHeightResponse - 36, // 84: vm.VM.StateSyncEnabled:output_type -> vm.StateSyncEnabledResponse - 37, // 85: vm.VM.GetOngoingSyncStateSummary:output_type -> vm.GetOngoingSyncStateSummaryResponse - 38, // 86: vm.VM.GetLastStateSummary:output_type -> vm.GetLastStateSummaryResponse - 40, // 87: vm.VM.ParseStateSummary:output_type -> vm.ParseStateSummaryResponse - 42, // 88: vm.VM.GetStateSummary:output_type -> vm.GetStateSummaryResponse - 18, // 89: vm.VM.BlockVerify:output_type -> vm.BlockVerifyResponse - 47, // 90: vm.VM.BlockAccept:output_type -> google.protobuf.Empty - 47, // 91: vm.VM.BlockReject:output_type -> google.protobuf.Empty - 44, // 92: vm.VM.StateSummaryAccept:output_type -> vm.StateSummaryAcceptResponse - 64, // [64:93] is the sub-list for method output_type - 35, // [35:64] is the sub-list for method input_type + 48, // 37: vm.VM.Shutdown:input_type -> google.protobuf.Empty + 48, // 38: vm.VM.CreateHandlers:input_type -> google.protobuf.Empty + 48, // 39: vm.VM.CreateHTTP2Handler:input_type -> google.protobuf.Empty + 28, // 40: vm.VM.Connected:input_type -> vm.ConnectedRequest + 29, // 41: vm.VM.Disconnected:input_type -> vm.DisconnectedRequest + 11, // 42: vm.VM.BuildBlock:input_type -> vm.BuildBlockRequest + 13, // 43: vm.VM.ParseBlock:input_type -> vm.ParseBlockRequest + 15, // 44: vm.VM.GetBlock:input_type -> vm.GetBlockRequest + 17, // 45: vm.VM.SetPreference:input_type -> vm.SetPreferenceRequest + 48, // 46: vm.VM.Health:input_type -> google.protobuf.Empty + 48, // 47: vm.VM.Version:input_type -> google.protobuf.Empty + 24, // 48: vm.VM.AppRequest:input_type -> vm.AppRequestMsg + 25, // 49: vm.VM.AppRequestFailed:input_type -> vm.AppRequestFailedMsg + 26, // 50: vm.VM.AppResponse:input_type -> vm.AppResponseMsg + 27, // 51: vm.VM.AppGossip:input_type -> vm.AppGossipMsg + 48, // 52: vm.VM.Gather:input_type -> google.protobuf.Empty + 30, // 53: vm.VM.GetAncestors:input_type -> vm.GetAncestorsRequest + 32, // 54: vm.VM.BatchedParseBlock:input_type -> vm.BatchedParseBlockRequest + 34, // 55: vm.VM.GetBlockIDAtHeight:input_type -> vm.GetBlockIDAtHeightRequest + 48, // 56: vm.VM.StateSyncEnabled:input_type -> google.protobuf.Empty + 48, // 57: vm.VM.GetOngoingSyncStateSummary:input_type -> google.protobuf.Empty + 48, // 58: vm.VM.GetLastStateSummary:input_type -> google.protobuf.Empty + 40, // 59: vm.VM.ParseStateSummary:input_type -> vm.ParseStateSummaryRequest + 42, // 60: vm.VM.GetStateSummary:input_type -> vm.GetStateSummaryRequest + 18, // 61: vm.VM.BlockVerify:input_type -> vm.BlockVerifyRequest + 20, // 62: vm.VM.BlockAccept:input_type -> vm.BlockAcceptRequest + 21, // 63: vm.VM.BlockReject:input_type -> vm.BlockRejectRequest + 44, // 64: vm.VM.StateSummaryAccept:input_type -> vm.StateSummaryAcceptRequest + 5, // 65: vm.VM.Initialize:output_type -> vm.InitializeResponse + 7, // 66: vm.VM.SetState:output_type -> vm.SetStateResponse + 48, // 67: vm.VM.Shutdown:output_type -> google.protobuf.Empty + 8, // 68: vm.VM.CreateHandlers:output_type -> vm.CreateHandlersResponse + 9, // 69: vm.VM.CreateHTTP2Handler:output_type -> vm.CreateHTTP2HandlerResponse + 48, // 70: vm.VM.Connected:output_type -> google.protobuf.Empty + 48, // 71: vm.VM.Disconnected:output_type -> google.protobuf.Empty + 12, // 72: vm.VM.BuildBlock:output_type -> vm.BuildBlockResponse + 14, // 73: vm.VM.ParseBlock:output_type -> vm.ParseBlockResponse + 16, // 74: vm.VM.GetBlock:output_type -> vm.GetBlockResponse + 48, // 75: vm.VM.SetPreference:output_type -> google.protobuf.Empty + 22, // 76: vm.VM.Health:output_type -> vm.HealthResponse + 23, // 77: vm.VM.Version:output_type -> vm.VersionResponse + 48, // 78: vm.VM.AppRequest:output_type -> google.protobuf.Empty + 48, // 79: vm.VM.AppRequestFailed:output_type -> google.protobuf.Empty + 48, // 80: vm.VM.AppResponse:output_type -> google.protobuf.Empty + 48, // 81: vm.VM.AppGossip:output_type -> google.protobuf.Empty + 36, // 82: vm.VM.Gather:output_type -> vm.GatherResponse + 31, // 83: vm.VM.GetAncestors:output_type -> vm.GetAncestorsResponse + 33, // 84: vm.VM.BatchedParseBlock:output_type -> vm.BatchedParseBlockResponse + 35, // 85: vm.VM.GetBlockIDAtHeight:output_type -> vm.GetBlockIDAtHeightResponse + 37, // 86: vm.VM.StateSyncEnabled:output_type -> vm.StateSyncEnabledResponse + 38, // 87: vm.VM.GetOngoingSyncStateSummary:output_type -> vm.GetOngoingSyncStateSummaryResponse + 39, // 88: vm.VM.GetLastStateSummary:output_type -> vm.GetLastStateSummaryResponse + 41, // 89: vm.VM.ParseStateSummary:output_type -> vm.ParseStateSummaryResponse + 43, // 90: vm.VM.GetStateSummary:output_type -> vm.GetStateSummaryResponse + 19, // 91: vm.VM.BlockVerify:output_type -> vm.BlockVerifyResponse + 48, // 92: vm.VM.BlockAccept:output_type -> google.protobuf.Empty + 48, // 93: vm.VM.BlockReject:output_type -> google.protobuf.Empty + 45, // 94: vm.VM.StateSummaryAccept:output_type -> vm.StateSummaryAcceptResponse + 65, // [65:95] is the sub-list for method output_type + 35, // [35:65] is the sub-list for method input_type 35, // [35:35] is the sub-list for extension type_name 35, // [35:35] is the sub-list for extension extendee 0, // [0:35] is the sub-list for field type_name @@ -3427,15 +3485,15 @@ func file_vm_vm_proto_init() { if File_vm_vm_proto != nil { return } - file_vm_vm_proto_msgTypes[7].OneofWrappers = []any{} - file_vm_vm_proto_msgTypes[14].OneofWrappers = []any{} + file_vm_vm_proto_msgTypes[8].OneofWrappers = []any{} + file_vm_vm_proto_msgTypes[15].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vm_vm_proto_rawDesc, NumEnums: 3, - NumMessages: 42, + NumMessages: 43, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/pb/vm/vm_grpc.pb.go b/proto/pb/vm/vm_grpc.pb.go index f1b43307faab..498daeb57a84 100644 --- a/proto/pb/vm/vm_grpc.pb.go +++ b/proto/pb/vm/vm_grpc.pb.go @@ -24,6 +24,7 @@ const ( VM_SetState_FullMethodName = "/vm.VM/SetState" VM_Shutdown_FullMethodName = "/vm.VM/Shutdown" VM_CreateHandlers_FullMethodName = "/vm.VM/CreateHandlers" + VM_CreateHTTP2Handler_FullMethodName = "/vm.VM/CreateHTTP2Handler" VM_Connected_FullMethodName = "/vm.VM/Connected" VM_Disconnected_FullMethodName = "/vm.VM/Disconnected" VM_BuildBlock_FullMethodName = "/vm.VM/BuildBlock" @@ -65,6 +66,7 @@ type VMClient interface { Shutdown(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) // Creates the HTTP handlers for custom chain network calls. CreateHandlers(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateHandlersResponse, error) + CreateHTTP2Handler(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateHTTP2HandlerResponse, error) Connected(ctx context.Context, in *ConnectedRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) Disconnected(ctx context.Context, in *DisconnectedRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Attempt to create a new block from data contained in the VM. @@ -161,6 +163,15 @@ func (c *vMClient) CreateHandlers(ctx context.Context, in *emptypb.Empty, opts . return out, nil } +func (c *vMClient) CreateHTTP2Handler(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*CreateHTTP2HandlerResponse, error) { + out := new(CreateHTTP2HandlerResponse) + err := c.cc.Invoke(ctx, VM_CreateHTTP2Handler_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *vMClient) Connected(ctx context.Context, in *ConnectedRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, VM_Connected_FullMethodName, in, out, opts...) @@ -400,6 +411,7 @@ type VMServer interface { Shutdown(context.Context, *emptypb.Empty) (*emptypb.Empty, error) // Creates the HTTP handlers for custom chain network calls. CreateHandlers(context.Context, *emptypb.Empty) (*CreateHandlersResponse, error) + CreateHTTP2Handler(context.Context, *emptypb.Empty) (*CreateHTTP2HandlerResponse, error) Connected(context.Context, *ConnectedRequest) (*emptypb.Empty, error) Disconnected(context.Context, *DisconnectedRequest) (*emptypb.Empty, error) // Attempt to create a new block from data contained in the VM. @@ -469,6 +481,9 @@ func (UnimplementedVMServer) Shutdown(context.Context, *emptypb.Empty) (*emptypb func (UnimplementedVMServer) CreateHandlers(context.Context, *emptypb.Empty) (*CreateHandlersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateHandlers not implemented") } +func (UnimplementedVMServer) CreateHTTP2Handler(context.Context, *emptypb.Empty) (*CreateHTTP2HandlerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateHTTP2Handler not implemented") +} func (UnimplementedVMServer) Connected(context.Context, *ConnectedRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Connected not implemented") } @@ -629,6 +644,24 @@ func _VM_CreateHandlers_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _VM_CreateHTTP2Handler_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VMServer).CreateHTTP2Handler(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: VM_CreateHTTP2Handler_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VMServer).CreateHTTP2Handler(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _VM_Connected_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ConnectedRequest) if err := dec(in); err != nil { @@ -1102,6 +1135,10 @@ var VM_ServiceDesc = grpc.ServiceDesc{ MethodName: "CreateHandlers", Handler: _VM_CreateHandlers_Handler, }, + { + MethodName: "CreateHTTP2Handler", + Handler: _VM_CreateHTTP2Handler_Handler, + }, { MethodName: "Connected", Handler: _VM_Connected_Handler, diff --git a/proto/pb/xsvm/service.pb.go b/proto/pb/xsvm/service.pb.go new file mode 100644 index 000000000000..738007b356cc --- /dev/null +++ b/proto/pb/xsvm/service.pb.go @@ -0,0 +1,286 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.35.1 +// protoc (unknown) +// source: xsvm/service.proto + +package xsvm + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + mi := &file_xsvm_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_xsvm_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_xsvm_service_proto_rawDescGZIP(), []int{0} +} + +func (x *PingRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type PingReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *PingReply) Reset() { + *x = PingReply{} + mi := &file_xsvm_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PingReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingReply) ProtoMessage() {} + +func (x *PingReply) ProtoReflect() protoreflect.Message { + mi := &file_xsvm_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingReply.ProtoReflect.Descriptor instead. +func (*PingReply) Descriptor() ([]byte, []int) { + return file_xsvm_service_proto_rawDescGZIP(), []int{1} +} + +func (x *PingReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type StreamPingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *StreamPingRequest) Reset() { + *x = StreamPingRequest{} + mi := &file_xsvm_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamPingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamPingRequest) ProtoMessage() {} + +func (x *StreamPingRequest) ProtoReflect() protoreflect.Message { + mi := &file_xsvm_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StreamPingRequest.ProtoReflect.Descriptor instead. +func (*StreamPingRequest) Descriptor() ([]byte, []int) { + return file_xsvm_service_proto_rawDescGZIP(), []int{2} +} + +func (x *StreamPingRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type StreamPingReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *StreamPingReply) Reset() { + *x = StreamPingReply{} + mi := &file_xsvm_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamPingReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamPingReply) ProtoMessage() {} + +func (x *StreamPingReply) ProtoReflect() protoreflect.Message { + mi := &file_xsvm_service_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StreamPingReply.ProtoReflect.Descriptor instead. +func (*StreamPingReply) Descriptor() ([]byte, []int) { + return file_xsvm_service_proto_rawDescGZIP(), []int{3} +} + +func (x *StreamPingReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_xsvm_service_proto protoreflect.FileDescriptor + +var file_xsvm_service_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x78, 0x73, 0x76, 0x6d, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x78, 0x73, 0x76, 0x6d, 0x22, 0x27, 0x0a, 0x0b, 0x50, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x22, 0x25, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2b, 0x0a, 0x0f, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x74, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x2a, + 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x11, 0x2e, 0x78, 0x73, 0x76, 0x6d, 0x2e, 0x50, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x78, 0x73, 0x76, 0x6d, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x2e, 0x78, 0x73, 0x76, 0x6d, 0x2e, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x15, 0x2e, 0x78, 0x73, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x28, 0x01, 0x30, 0x01, 0x42, 0x2f, 0x5a, 0x2d, + 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, 0x78, 0x73, 0x76, 0x6d, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_xsvm_service_proto_rawDescOnce sync.Once + file_xsvm_service_proto_rawDescData = file_xsvm_service_proto_rawDesc +) + +func file_xsvm_service_proto_rawDescGZIP() []byte { + file_xsvm_service_proto_rawDescOnce.Do(func() { + file_xsvm_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_xsvm_service_proto_rawDescData) + }) + return file_xsvm_service_proto_rawDescData +} + +var file_xsvm_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_xsvm_service_proto_goTypes = []any{ + (*PingRequest)(nil), // 0: xsvm.PingRequest + (*PingReply)(nil), // 1: xsvm.PingReply + (*StreamPingRequest)(nil), // 2: xsvm.StreamPingRequest + (*StreamPingReply)(nil), // 3: xsvm.StreamPingReply +} +var file_xsvm_service_proto_depIdxs = []int32{ + 0, // 0: xsvm.Ping.Ping:input_type -> xsvm.PingRequest + 2, // 1: xsvm.Ping.StreamPing:input_type -> xsvm.StreamPingRequest + 1, // 2: xsvm.Ping.Ping:output_type -> xsvm.PingReply + 3, // 3: xsvm.Ping.StreamPing:output_type -> xsvm.StreamPingReply + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_xsvm_service_proto_init() } +func file_xsvm_service_proto_init() { + if File_xsvm_service_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_xsvm_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_xsvm_service_proto_goTypes, + DependencyIndexes: file_xsvm_service_proto_depIdxs, + MessageInfos: file_xsvm_service_proto_msgTypes, + }.Build() + File_xsvm_service_proto = out.File + file_xsvm_service_proto_rawDesc = nil + file_xsvm_service_proto_goTypes = nil + file_xsvm_service_proto_depIdxs = nil +} diff --git a/proto/pb/xsvm/service_grpc.pb.go b/proto/pb/xsvm/service_grpc.pb.go new file mode 100644 index 000000000000..3a3c2e4cbf00 --- /dev/null +++ b/proto/pb/xsvm/service_grpc.pb.go @@ -0,0 +1,179 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: xsvm/service.proto + +package xsvm + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + Ping_Ping_FullMethodName = "/xsvm.Ping/Ping" + Ping_StreamPing_FullMethodName = "/xsvm.Ping/StreamPing" +) + +// PingClient is the client API for Ping service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PingClient interface { + Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingReply, error) + StreamPing(ctx context.Context, opts ...grpc.CallOption) (Ping_StreamPingClient, error) +} + +type pingClient struct { + cc grpc.ClientConnInterface +} + +func NewPingClient(cc grpc.ClientConnInterface) PingClient { + return &pingClient{cc} +} + +func (c *pingClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingReply, error) { + out := new(PingReply) + err := c.cc.Invoke(ctx, Ping_Ping_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pingClient) StreamPing(ctx context.Context, opts ...grpc.CallOption) (Ping_StreamPingClient, error) { + stream, err := c.cc.NewStream(ctx, &Ping_ServiceDesc.Streams[0], Ping_StreamPing_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &pingStreamPingClient{stream} + return x, nil +} + +type Ping_StreamPingClient interface { + Send(*StreamPingRequest) error + Recv() (*StreamPingReply, error) + grpc.ClientStream +} + +type pingStreamPingClient struct { + grpc.ClientStream +} + +func (x *pingStreamPingClient) Send(m *StreamPingRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *pingStreamPingClient) Recv() (*StreamPingReply, error) { + m := new(StreamPingReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// PingServer is the server API for Ping service. +// All implementations must embed UnimplementedPingServer +// for forward compatibility +type PingServer interface { + Ping(context.Context, *PingRequest) (*PingReply, error) + StreamPing(Ping_StreamPingServer) error + mustEmbedUnimplementedPingServer() +} + +// UnimplementedPingServer must be embedded to have forward compatible implementations. +type UnimplementedPingServer struct { +} + +func (UnimplementedPingServer) Ping(context.Context, *PingRequest) (*PingReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedPingServer) StreamPing(Ping_StreamPingServer) error { + return status.Errorf(codes.Unimplemented, "method StreamPing not implemented") +} +func (UnimplementedPingServer) mustEmbedUnimplementedPingServer() {} + +// UnsafePingServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PingServer will +// result in compilation errors. +type UnsafePingServer interface { + mustEmbedUnimplementedPingServer() +} + +func RegisterPingServer(s grpc.ServiceRegistrar, srv PingServer) { + s.RegisterService(&Ping_ServiceDesc, srv) +} + +func _Ping_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PingServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Ping_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PingServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Ping_StreamPing_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(PingServer).StreamPing(&pingStreamPingServer{stream}) +} + +type Ping_StreamPingServer interface { + Send(*StreamPingReply) error + Recv() (*StreamPingRequest, error) + grpc.ServerStream +} + +type pingStreamPingServer struct { + grpc.ServerStream +} + +func (x *pingStreamPingServer) Send(m *StreamPingReply) error { + return x.ServerStream.SendMsg(m) +} + +func (x *pingStreamPingServer) Recv() (*StreamPingRequest, error) { + m := new(StreamPingRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Ping_ServiceDesc is the grpc.ServiceDesc for Ping service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Ping_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "xsvm.Ping", + HandlerType: (*PingServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _Ping_Ping_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamPing", + Handler: _Ping_StreamPing_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "xsvm/service.proto", +} diff --git a/proto/vm/vm.proto b/proto/vm/vm.proto index 7990ebf733ff..34334e8e540a 100644 --- a/proto/vm/vm.proto +++ b/proto/vm/vm.proto @@ -21,6 +21,7 @@ service VM { rpc Shutdown(google.protobuf.Empty) returns (google.protobuf.Empty); // Creates the HTTP handlers for custom chain network calls. rpc CreateHandlers(google.protobuf.Empty) returns (CreateHandlersResponse); + rpc CreateHTTP2Handler(google.protobuf.Empty) returns (CreateHTTP2HandlerResponse); rpc Connected(ConnectedRequest) returns (google.protobuf.Empty); rpc Disconnected(DisconnectedRequest) returns (google.protobuf.Empty); // Attempt to create a new block from data contained in the VM. @@ -158,6 +159,12 @@ message CreateHandlersResponse { repeated Handler handlers = 1; } +message CreateHTTP2HandlerResponse { + // server_addr is the address of the gRPC server which serves the + // HTTP service + string server_addr = 1; +} + message Handler { string prefix = 1; // server_addr is the address of the gRPC server which serves the diff --git a/proto/xsvm/service.proto b/proto/xsvm/service.proto new file mode 100644 index 000000000000..5d6329356f59 --- /dev/null +++ b/proto/xsvm/service.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +package xsvm; + +option go_package = "github.com/ava-labs/avalanchego/proto/pb/xsvm"; + +service Ping { + rpc Ping(PingRequest) returns (PingReply); + rpc StreamPing(stream StreamPingRequest) returns (stream StreamPingReply); +} + +message PingRequest { + string message = 1; +} + +message PingReply { + string message = 1; +} + +message StreamPingRequest { + string message = 1; +} + +message StreamPingReply { + string message = 1; +} diff --git a/simplex/bls.go b/simplex/bls.go index e7b1ce25259c..9bf4a5043453 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -18,6 +18,11 @@ import ( var ( errSignatureVerificationFailed = errors.New("signature verification failed") errSignerNotFound = errors.New("signer not found in the membership set") + errFailedToParseSignature = errors.New("failed to parse signature") + errInvalidByteSliceLength = errors.New("invalid byte slice length") + errNotEnoughSigners = errors.New("not enough signers") + errSignatureAggregation = errors.New("signature aggregation failed") + errEncodingMessageToSign = errors.New("failed to encode message to sign") simplexLabel = []byte("simplex") ) @@ -53,7 +58,7 @@ func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier) { func (s *BLSSigner) Sign(message []byte) ([]byte, error) { message2Sign, err := encodeMessageToSign(message, s.chainID, s.subnetID) if err != nil { - return nil, fmt.Errorf("failed to encode message to sign: %w", err) + return nil, fmt.Errorf("%w: %w", errEncodingMessageToSign, err) } sig, err := s.signBLS(message2Sign) diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 91403dcd14f3..8bf3c4240129 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -6,87 +6,17 @@ package simplex import ( "testing" + "github.com/ava-labs/simplex" "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" ) -var _ ValidatorInfo = (*testValidatorInfo)(nil) - -// testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. -// it assumes all validators are in the same subnet and returns all of them for any subnetID. -type testValidatorInfo struct { - validators map[ids.NodeID]validators.Validator -} - -func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { - if v.validators == nil { - return nil - } - - ids := make([]ids.NodeID, 0, len(v.validators)) - for id := range v.validators { - ids = append(ids, id) - } - return ids -} - -func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) { - if v.validators == nil { - return nil, false - } - - val, exists := v.validators[nodeID] - if !exists { - return nil, false - } - return &val, true -} - -func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { - if len(nodeIds) != len(pks) { - panic("nodeIds and pks must have the same length") - } - - vds := make(map[ids.NodeID]validators.Validator, len(pks)) - for i, pk := range pks { - validator := validators.Validator{ - PublicKey: pk, - NodeID: nodeIds[i], - } - vds[nodeIds[i]] = validator - } - // all we need is to generate the public keys for the validators - return &testValidatorInfo{ - validators: vds, - } -} - -func newEngineConfig(ls *localsigner.LocalSigner) *Config { - nodeID := ids.GenerateTestNodeID() - - simplexChainContext := SimplexChainContext{ - NodeID: nodeID, - ChainID: ids.GenerateTestID(), - SubnetID: ids.GenerateTestID(), - } - - return &Config{ - Ctx: simplexChainContext, - Validators: newTestValidatorInfo([]ids.NodeID{nodeID}, []*bls.PublicKey{ls.PublicKey()}), - SignBLS: ls.Sign, - } -} - func TestBLSSignVerify(t *testing.T) { - ls, err := localsigner.New() + config, err := newEngineConfig(nil) require.NoError(t, err) - config := newEngineConfig(ls) - signer, verifier := NewBLSAuth(config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -99,10 +29,8 @@ func TestBLSSignVerify(t *testing.T) { } func TestSignerNotInMemberSet(t *testing.T) { - ls, err := localsigner.New() + config, err := newEngineConfig(nil) require.NoError(t, err) - - config := newEngineConfig(ls) signer, verifier := NewBLSAuth(config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -116,14 +44,12 @@ func TestSignerNotInMemberSet(t *testing.T) { } func TestSignerInvalidMessageEncoding(t *testing.T) { - ls, err := localsigner.New() + config, err := newEngineConfig(nil) require.NoError(t, err) - config := newEngineConfig(ls) - // sign a message with invalid encoding dummyMsg := []byte("dummy message") - sig, err := ls.Sign(dummyMsg) + sig, err := config.SignBLS(dummyMsg) require.NoError(t, err) sigBytes := bls.SignatureToBytes(sig) @@ -136,33 +62,237 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { // TestQCAggregateAndSign tests the aggregation of multiple signatures // and then verifies the generated quorum certificate on that message. func TestQCAggregateAndSign(t *testing.T) { - ls, err := localsigner.New() + options, err := withNodes(2) + require.NoError(t, err) + config, err := newEngineConfig(options) require.NoError(t, err) - config := newEngineConfig(ls) signer, verifier := NewBLSAuth(config) + // nodes 1 and 2 will sign the same message + msg := []byte("Begin at the beginning, and go on till you come to the end: then stop") + sig, err := signer.Sign(msg) + require.NoError(t, err) + require.NoError(t, verifier.Verify(msg, sig, config.Ctx.NodeID[:])) - msg := "Begin at the beginning, and go on till you come to the end: then stop" + options.curNode = options.allNodes[1] + config2, err := newEngineConfig(options) + config2.Ctx.ChainID = config.Ctx.ChainID + config2.Ctx.SubnetID = config.Ctx.SubnetID + require.NoError(t, err) - sig1, err := signer.Sign([]byte(msg)) + signer2, verifier2 := NewBLSAuth(config2) + sig2, err := signer2.Sign(msg) require.NoError(t, err) + require.NoError(t, verifier2.Verify(msg, sig2, config2.Ctx.NodeID[:])) + + // aggregate the signatures into a quorum certificate + signatureAggregator := SignatureAggregator(verifier) + qc, err := signatureAggregator.Aggregate( + []simplex.Signature{ + {Signer: config.Ctx.NodeID[:], Value: sig}, + {Signer: config2.Ctx.NodeID[:], Value: sig2}, + }, + ) + require.NoError(t, err) + require.Equal(t, []simplex.NodeID{config.Ctx.NodeID[:], config2.Ctx.NodeID[:]}, qc.Signers()) + // verify the quorum certificate + require.NoError(t, qc.Verify(msg)) - sig2, err := signer.Sign([]byte(msg)) + d := QCDeserializer(verifier) + // try to deserialize the quorum certificate + deserializedQC, err := d.DeserializeQuorumCertificate(qc.Bytes()) require.NoError(t, err) - // Aggregate signatures - aggSig, err := bls.AggregateSignatures([]*bls.Signature{bls.SignatureFromBytes(sig1), bls.SignatureFromBytes(sig2)}) + require.Equal(t, qc.Signers(), deserializedQC.Signers()) + require.NoError(t, deserializedQC.Verify(msg)) + require.Equal(t, qc.Bytes(), deserializedQC.Bytes()) +} + +func TestQCSignerNotInMembershipSet(t *testing.T) { + options, err := withNodes(2) + require.NoError(t, err) + config, err := newEngineConfig(options) + require.NoError(t, err) + + signer, verifier := NewBLSAuth(config) + // nodes 1 and 2 will sign the same message + msg := []byte("Begin at the beginning, and go on till you come to the end: then stop") + sig, err := signer.Sign(msg) require.NoError(t, err) + require.NoError(t, verifier.Verify(msg, sig, config.Ctx.NodeID[:])) - err = verifier.Verify([]byte(msg), bls.SignatureToBytes(aggSig), config.Ctx.NodeID[:]) + // vds is not in the membership set of the first node + vds, err := newTestValidators(1) require.NoError(t, err) + + options.curNode = vds[0] + options.allNodes[0] = vds[0] + config2, err := newEngineConfig(options) + require.NoError(t, err) + signer2, verifier2 := NewBLSAuth(config2) + sig2, err := signer2.Sign(msg) + require.NoError(t, err) + require.NoError(t, verifier2.Verify(msg, sig2, config2.Ctx.NodeID[:])) + + // aggregate the signatures into a quorum certificate + signatureAggregator := SignatureAggregator(verifier) + _, err = signatureAggregator.Aggregate( + []simplex.Signature{ + {Signer: config.Ctx.NodeID[:], Value: sig}, + {Signer: config2.Ctx.NodeID[:], Value: sig2}, + }, + ) + require.ErrorIs(t, err, errSignerNotFound) } -func TestQCSignerNotInMembershipSet(t *testing.T) { - +func TestQCDeserializerInvalidInput(t *testing.T) { + options, err := withNodes(2) + require.NoError(t, err) + config, err := newEngineConfig(options) + require.NoError(t, err) + + _, verifier := NewBLSAuth(config) + deserializer := QCDeserializer(verifier) + + tests := []struct { + name string + input []byte + err error + }{ + { + name: "too short input", + input: make([]byte, 10), + err: errInvalidByteSliceLength, + }, + { + name: "invalid signature bytes", + input: make([]byte, simplex.Quorum(len(verifier.nodeID2PK))*ids.NodeIDLen+bls.SignatureLen), + err: errFailedToParseSignature, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := deserializer.DeserializeQuorumCertificate(tt.input) + require.ErrorIs(t, err, tt.err) + }) + } } -func TestQCNotInMembershipSet(t *testing.T) { - +func TestSignatureAggregatorInsufficientSignatures(t *testing.T) { + options, err := withNodes(3) + require.NoError(t, err) + config, err := newEngineConfig(options) + require.NoError(t, err) + + signer, verifier := NewBLSAuth(config) + msg := []byte("test message") + sig, err := signer.Sign(msg) + require.NoError(t, err) + + // try to aggregate with only 1 signature when quorum is 2 + signatureAggregator := SignatureAggregator(verifier) + _, err = signatureAggregator.Aggregate( + []simplex.Signature{ + {Signer: config.Ctx.NodeID[:], Value: sig}, + }, + ) + require.ErrorIs(t, err, errNotEnoughSigners) +} + +func TestSignatureAggregatorInvalidSignatureBytes(t *testing.T) { + options, err := withNodes(2) + require.NoError(t, err) + config, err := newEngineConfig(options) + require.NoError(t, err) + + signer, verifier := NewBLSAuth(config) + msg := []byte("test message") + sig, err := signer.Sign(msg) + require.NoError(t, err) + + signatureAggregator := SignatureAggregator(verifier) + _, err = signatureAggregator.Aggregate( + []simplex.Signature{ + {Signer: config.Ctx.NodeID[:], Value: sig}, + {Signer: config.Ctx.NodeID[:], Value: []byte("invalid signature")}, + }, + ) + require.ErrorIs(t, err, errFailedToParseSignature) +} + +func TestSignatureAggregatorExcessSignatures(t *testing.T) { + options, err := withNodes(4) // quorum will be 3 + require.NoError(t, err) + config, err := newEngineConfig(options) + require.NoError(t, err) + + _, verifier := NewBLSAuth(config) + msg := []byte("test message") + + // Create signatures from all 4 nodes + signatures := make([]simplex.Signature, 4) + for i, node := range options.allNodes { + options.curNode = node + nodeConfig, err := newEngineConfig(options) + nodeConfig.Ctx.ChainID = config.Ctx.ChainID + nodeConfig.Ctx.SubnetID = config.Ctx.SubnetID + require.NoError(t, err) + + nodeSigner, _ := NewBLSAuth(nodeConfig) + sig, err := nodeSigner.Sign(msg) + require.NoError(t, err) + + signatures[i] = simplex.Signature{Signer: nodeConfig.Ctx.NodeID[:], Value: sig} + } + + // Aggregate should only use the first 3 signatures + signatureAggregator := SignatureAggregator(verifier) + qc, err := signatureAggregator.Aggregate(signatures) + require.NoError(t, err) + + // Should only have 3 signers, not 4 + require.Len(t, qc.Signers(), simplex.Quorum(len(options.allNodes))) + require.NoError(t, qc.Verify(msg)) } +func TestQCVerifyWithWrongMessage(t *testing.T) { + options, err := withNodes(2) + require.NoError(t, err) + config, err := newEngineConfig(options) + require.NoError(t, err) + + signer, verifier := NewBLSAuth(config) + originalMsg := []byte("original message") + wrongMsg := []byte("wrong message") + + // Create signatures for original message + sig1, err := signer.Sign(originalMsg) + require.NoError(t, err) + + options.curNode = options.allNodes[1] + config2, err := newEngineConfig(options) + config2.Ctx.ChainID = config.Ctx.ChainID + config2.Ctx.SubnetID = config.Ctx.SubnetID + require.NoError(t, err) + + signer2, _ := NewBLSAuth(config2) + sig2, err := signer2.Sign(originalMsg) + require.NoError(t, err) + + signatureAggregator := SignatureAggregator(verifier) + qc, err := signatureAggregator.Aggregate( + []simplex.Signature{ + {Signer: config.Ctx.NodeID[:], Value: sig1}, + {Signer: config2.Ctx.NodeID[:], Value: sig2}, + }, + ) + require.NoError(t, err) + + // Verify with original message should succeed + require.NoError(t, qc.Verify(originalMsg)) + + // Verify with wrong message should fail + err = qc.Verify(wrongMsg) + require.ErrorIs(t, err, errSignatureVerificationFailed) +} diff --git a/simplex/quorum.go b/simplex/quorum.go index 84df789a5e27..8b46f6da6b87 100644 --- a/simplex/quorum.go +++ b/simplex/quorum.go @@ -6,13 +6,16 @@ package simplex import ( "fmt" + "github.com/ava-labs/simplex" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/simplex" ) -var _ simplex.QuorumCertificate = (*QC)(nil) -var _ simplex.QCDeserializer = QCDeserializer{} +var ( + _ simplex.QuorumCertificate = (*QC)(nil) + _ simplex.QCDeserializer = QCDeserializer{} +) type QCDeserializer BLSVerifier @@ -36,24 +39,25 @@ func (qc *QC) Verify(msg []byte) error { for _, signer := range qc.signers { pk, exists := qc.verifier.nodeID2PK[ids.NodeID(signer)] if !exists { - return fmt.Errorf("signer %x is not found in the membership set", signer) + return fmt.Errorf("%w: %x", errSignerNotFound, signer) } + pks = append(pks, &pk) } // aggregate the public keys aggPK, err := bls.AggregatePublicKeys(pks) if err != nil { - return fmt.Errorf("failed to aggregate public keys: %w", err) + return fmt.Errorf("%w: %w", errSignatureAggregation, err) } message2Verify, err := encodeMessageToSign(msg, qc.verifier.chainID, qc.verifier.subnetID) if err != nil { - return fmt.Errorf("failed to encode message to verify: %w", err) + return fmt.Errorf("%w: %w", errEncodingMessageToSign, err) } if !bls.Verify(aggPK, &qc.sig, message2Verify) { - return fmt.Errorf("signature verification failed") + return errSignatureVerificationFailed } return nil @@ -81,7 +85,7 @@ func (d QCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex.Quor quorumSize := simplex.Quorum(len(d.nodeID2PK)) expectedSize := quorumSize*ids.NodeIDLen + bls.SignatureLen if len(bytes) != expectedSize { - return nil, fmt.Errorf("expected at least %d bytes but got %d bytes", expectedSize, len(bytes)) + return nil, fmt.Errorf("%w: %d expected but got %d bytes", errInvalidByteSliceLength, expectedSize, len(bytes)) } signers := make([]simplex.NodeID, 0, quorumSize) @@ -94,7 +98,7 @@ func (d QCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex.Quor sig, err := bls.SignatureFromBytes(bytes[pos:]) if err != nil { - return nil, fmt.Errorf("failed to parse signature: %w", err) + return nil, fmt.Errorf("%w: %w", errFailedToParseSignature, err) } return &QC{ @@ -113,7 +117,7 @@ type SignatureAggregator BLSVerifier func (a SignatureAggregator) Aggregate(signatures []simplex.Signature) (simplex.QuorumCertificate, error) { quorumSize := simplex.Quorum(len(a.nodeID2PK)) if len(signatures) < quorumSize { - return nil, fmt.Errorf("expected at least %d signatures but got %d", quorumSize, len(signatures)) + return nil, fmt.Errorf("%w: wanted %d signatures but got %d", errNotEnoughSigners, quorumSize, len(signatures)) } signatures = signatures[:quorumSize] @@ -124,19 +128,19 @@ func (a SignatureAggregator) Aggregate(signatures []simplex.Signature) (simplex. signer := signature.Signer _, exists := a.nodeID2PK[ids.NodeID(signer)] if !exists { - return nil, fmt.Errorf("signer %x is not found in the membership set", signer) + return nil, fmt.Errorf("%w: %x", errSignerNotFound, signer) } signers = append(signers, signer) sig, err := bls.SignatureFromBytes(signature.Value) if err != nil { - return nil, fmt.Errorf("failed to parse signature: %w", err) + return nil, fmt.Errorf("%w: %w", errFailedToParseSignature, err) } sigs = append(sigs, sig) } aggregatedSig, err := bls.AggregateSignatures(sigs) if err != nil { - return nil, fmt.Errorf("failed to aggregate signatures: %w", err) + return nil, fmt.Errorf("%w: %w", errSignatureAggregation, err) } return &QC{ diff --git a/simplex/test_util.go b/simplex/test_util.go new file mode 100644 index 000000000000..ad6096bf2eaa --- /dev/null +++ b/simplex/test_util.go @@ -0,0 +1,124 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" +) + +var _ ValidatorInfo = (*testValidatorInfo)(nil) + +// testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. +// it assumes all validators are in the same subnet and returns all of them for any subnetID. +type testValidatorInfo struct { + validators map[ids.NodeID]validators.Validator +} + +func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { + if v.validators == nil { + return nil + } + + ids := make([]ids.NodeID, 0, len(v.validators)) + for id := range v.validators { + ids = append(ids, id) + } + return ids +} + +func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) { + if v.validators == nil { + return nil, false + } + + val, exists := v.validators[nodeID] + if !exists { + return nil, false + } + return &val, true +} + +type testValidator struct { + nodeID ids.NodeID + pk *bls.PublicKey + sign SignFunc +} + +func newTestValidators(num uint64) ([]*testValidator, error) { + vdrs := make([]*testValidator, num) + + for i := uint64(0); i < num; i++ { + nodeID := ids.GenerateTestNodeID() + ls, err := localsigner.New() + if err != nil { + return nil, err + } + pk := ls.PublicKey() + vdrs[i] = &testValidator{ + nodeID: nodeID, + pk: pk, + sign: ls.Sign, + } + } + + return vdrs, nil +} + +func newTestValidatorInfo(all []*testValidator) *testValidatorInfo { + vds := make(map[ids.NodeID]validators.Validator, len(all)) + for _, vd := range all { + vds[vd.nodeID] = validators.Validator{ + NodeID: vd.nodeID, + PublicKey: vd.pk, + } + } + // all we need is to generate the public keys for the validators + return &testValidatorInfo{ + validators: vds, + } +} + +type testEngineConfig struct { + curNode *testValidator // defaults to the first node + allNodes []*testValidator // all nodes in the test. defaults to a single node +} + +func newEngineConfig(options *testEngineConfig) (*Config, error) { + if options == nil { + defaultOptions, err := withNodes(1) + if err != nil { + return nil, err + } + options = defaultOptions + } + + vdrs := newTestValidatorInfo(options.allNodes) + + simplexChainContext := SimplexChainContext{ + NodeID: options.curNode.nodeID, + ChainID: ids.GenerateTestID(), + SubnetID: ids.GenerateTestID(), + } + + return &Config{ + Ctx: simplexChainContext, + Validators: vdrs, + SignBLS: options.curNode.sign, + }, nil +} + +func withNodes(numNodes uint64) (*testEngineConfig, error) { + vds, err := newTestValidators(numNodes) + if err != nil { + return nil, err + } + + return &testEngineConfig{ + curNode: vds[0], + allNodes: vds, + }, nil +} diff --git a/snow/consensus/snowball/tree.go b/snow/consensus/snowball/tree.go index d6b0fabc7384..a11b92e1fd03 100644 --- a/snow/consensus/snowball/tree.go +++ b/snow/consensus/snowball/tree.go @@ -175,6 +175,8 @@ func (u *unaryNode) DecidedPrefix() int { return u.decidedPrefix } +//nolint:gci,gofmt,gofumpt // this comment is formatted as intended +// // This is by far the most complicated function in this algorithm. // The intuition is that this instance represents a series of consecutive unary // snowball instances, and this function's purpose is convert one of these unary @@ -186,23 +188,23 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "00001" in this node: // -// +-------------------+ <-- This node will not be split -// | | -// | 0 0 0 | -// | | -// +-------------------+ <-- Pass the add to the child -// ^ -// | +// +-------------------+ <-- This node will not be split +// | | +// | 0 0 0 | +// | | +// +-------------------+ <-- Pass the add to the child +// ^ +// | // // Results in: // -// +-------------------+ -// | | -// | 0 0 0 | -// | | -// +-------------------+ <-- With the modified child -// ^ -// | +// +-------------------+ +// | | +// | 0 0 0 | +// | | +// +-------------------+ <-- With the modified child +// ^ +// | // // 2. This instance represents a series of only one unary instance and it must // be split. @@ -213,19 +215,19 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "1" in this tree: // -// +-------------------+ -// | | -// | 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ // // 3. This instance must be split on the first bit // @@ -235,26 +237,26 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "10" in this tree: // -// +-------------------+ -// | | -// | 0 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ -// ^ ^ -// / \ -// +-------------------+ +-------------------+ -// | | | | -// | 0 | | 0 | -// | | | | -// +-------------------+ +-------------------+ +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ +// ^ ^ +// / \ +// +-------------------+ +-------------------+ +// | | | | +// | 0 | | 0 | +// | | | | +// +-------------------+ +-------------------+ // // 4. This instance must be split on the last bit // @@ -265,26 +267,26 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "01" in this tree: // -// +-------------------+ -// | | -// | 0 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | -// | 0 | -// | | -// +-------------------+ -// ^ -// | -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 | +// | | +// +-------------------+ +// ^ +// | +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ // // 5. This instance must be split on an interior bit // @@ -296,35 +298,33 @@ func (u *unaryNode) DecidedPrefix() int { // // For example, attempting to insert the value "010" in this tree: // -// +-------------------+ -// | | -// | 0 0 0 | -// | | -// +-------------------+ +// +-------------------+ +// | | +// | 0 0 0 | +// | | +// +-------------------+ // // Results in: // -// +-------------------+ -// | | -// | 0 | -// | | -// +-------------------+ -// ^ -// | -// +-------------------+ -// | | | -// | 0 | 1 | -// | | | -// +-------------------+ -// ^ ^ -// / \ -// +-------------------+ +-------------------+ -// | | | | -// | 0 | | 0 | -// | | | | -// +-------------------+ +-------------------+ -// -//nolint:gci,gofmt,gofumpt // this comment is formatted as intended +// +-------------------+ +// | | +// | 0 | +// | | +// +-------------------+ +// ^ +// | +// +-------------------+ +// | | | +// | 0 | 1 | +// | | | +// +-------------------+ +// ^ ^ +// / \ +// +-------------------+ +-------------------+ +// | | | | +// | 0 | | 0 | +// | | | | +// +-------------------+ +-------------------+ func (u *unaryNode) Add(newChoice ids.ID) node { if u.Finalized() { return u // Only happens if the tree is finalized, or it's a leaf node diff --git a/snow/engine/avalanche/vertex/vertexmock/linearizable_vm.go b/snow/engine/avalanche/vertex/vertexmock/linearizable_vm.go index 19c2c4290475..abd1acc33599 100644 --- a/snow/engine/avalanche/vertex/vertexmock/linearizable_vm.go +++ b/snow/engine/avalanche/vertex/vertexmock/linearizable_vm.go @@ -134,6 +134,21 @@ func (mr *LinearizableVMMockRecorder) Connected(ctx, nodeID, nodeVersion any) *g return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connected", reflect.TypeOf((*LinearizableVM)(nil).Connected), ctx, nodeID, nodeVersion) } +// CreateHTTP2Handler mocks base method. +func (m *LinearizableVM) CreateHTTP2Handler(ctx context.Context) (http.Handler, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateHTTP2Handler", ctx) + ret0, _ := ret[0].(http.Handler) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateHTTP2Handler indicates an expected call of CreateHTTP2Handler. +func (mr *LinearizableVMMockRecorder) CreateHTTP2Handler(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateHTTP2Handler", reflect.TypeOf((*LinearizableVM)(nil).CreateHTTP2Handler), ctx) +} + // CreateHandlers mocks base method. func (m *LinearizableVM) CreateHandlers(arg0 context.Context) (map[string]http.Handler, error) { m.ctrl.T.Helper() diff --git a/snow/engine/common/vm.go b/snow/engine/common/vm.go index 65cbfb158656..3d9c021d208d 100644 --- a/snow/engine/common/vm.go +++ b/snow/engine/common/vm.go @@ -77,4 +77,8 @@ type VM interface { // it have an extension called `accounts`, where clients could get // information about their accounts. CreateHandlers(context.Context) (map[string]http.Handler, error) + + // CreateHTTP2Handler returns the http/2 handler to register into the + // avalanchego api server. + CreateHTTP2Handler(ctx context.Context) (http.Handler, error) } diff --git a/snow/engine/enginetest/vm.go b/snow/engine/enginetest/vm.go index f3c430e58404..6a69b70a1a4c 100644 --- a/snow/engine/enginetest/vm.go +++ b/snow/engine/enginetest/vm.go @@ -20,18 +20,19 @@ import ( ) var ( - errInitialize = errors.New("unexpectedly called Initialize") - errSetState = errors.New("unexpectedly called SetState") - errShutdown = errors.New("unexpectedly called Shutdown") - errCreateHandlers = errors.New("unexpectedly called CreateHandlers") - errHealthCheck = errors.New("unexpectedly called HealthCheck") - errConnected = errors.New("unexpectedly called Connected") - errDisconnected = errors.New("unexpectedly called Disconnected") - errVersion = errors.New("unexpectedly called Version") - errAppRequest = errors.New("unexpectedly called AppRequest") - errAppResponse = errors.New("unexpectedly called AppResponse") - errAppRequestFailed = errors.New("unexpectedly called AppRequestFailed") - errAppGossip = errors.New("unexpectedly called AppGossip") + errInitialize = errors.New("unexpectedly called Initialize") + errSetState = errors.New("unexpectedly called SetState") + errShutdown = errors.New("unexpectedly called Shutdown") + errCreateHandlers = errors.New("unexpectedly called CreateHandlers") + errCreateHTTP2Handler = errors.New("unexpectedly called CreateHTTP2Handler") + errHealthCheck = errors.New("unexpectedly called HealthCheck") + errConnected = errors.New("unexpectedly called Connected") + errDisconnected = errors.New("unexpectedly called Disconnected") + errVersion = errors.New("unexpectedly called Version") + errAppRequest = errors.New("unexpectedly called AppRequest") + errAppResponse = errors.New("unexpectedly called AppResponse") + errAppRequestFailed = errors.New("unexpectedly called AppRequestFailed") + errAppGossip = errors.New("unexpectedly called AppGossip") _ common.VM = (*VM)(nil) ) @@ -41,22 +42,23 @@ type VM struct { T *testing.T CantInitialize, CantSetState, - CantShutdown, CantCreateHandlers, + CantShutdown, CantCreateHandlers, CantCreateHTTP2Handler, CantHealthCheck, CantConnected, CantDisconnected, CantVersion, CantAppRequest, CantAppResponse, CantAppGossip, CantAppRequestFailed bool - InitializeF func(ctx context.Context, chainCtx *snow.Context, db database.Database, genesisBytes []byte, upgradeBytes []byte, configBytes []byte, msgChan chan<- common.Message, fxs []*common.Fx, appSender common.AppSender) error - SetStateF func(ctx context.Context, state snow.State) error - ShutdownF func(context.Context) error - CreateHandlersF func(context.Context) (map[string]http.Handler, error) - ConnectedF func(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error - DisconnectedF func(ctx context.Context, nodeID ids.NodeID) error - HealthCheckF func(context.Context) (interface{}, error) - AppRequestF func(ctx context.Context, nodeID ids.NodeID, requestID uint32, deadline time.Time, msg []byte) error - AppResponseF func(ctx context.Context, nodeID ids.NodeID, requestID uint32, msg []byte) error - AppGossipF func(ctx context.Context, nodeID ids.NodeID, msg []byte) error - AppRequestFailedF func(ctx context.Context, nodeID ids.NodeID, requestID uint32, appErr *common.AppError) error - VersionF func(context.Context) (string, error) + InitializeF func(ctx context.Context, chainCtx *snow.Context, db database.Database, genesisBytes []byte, upgradeBytes []byte, configBytes []byte, msgChan chan<- common.Message, fxs []*common.Fx, appSender common.AppSender) error + SetStateF func(ctx context.Context, state snow.State) error + ShutdownF func(context.Context) error + CreateHandlersF func(context.Context) (map[string]http.Handler, error) + CreateHTTP2HandlerF func(context.Context) (http.Handler, error) + ConnectedF func(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error + DisconnectedF func(ctx context.Context, nodeID ids.NodeID) error + HealthCheckF func(context.Context) (interface{}, error) + AppRequestF func(ctx context.Context, nodeID ids.NodeID, requestID uint32, deadline time.Time, msg []byte) error + AppResponseF func(ctx context.Context, nodeID ids.NodeID, requestID uint32, msg []byte) error + AppGossipF func(ctx context.Context, nodeID ids.NodeID, msg []byte) error + AppRequestFailedF func(ctx context.Context, nodeID ids.NodeID, requestID uint32, appErr *common.AppError) error + VersionF func(context.Context) (string, error) } func (vm *VM) Default(cant bool) { @@ -140,6 +142,17 @@ func (vm *VM) CreateHandlers(ctx context.Context) (map[string]http.Handler, erro return nil, nil } +func (vm *VM) CreateHTTP2Handler(ctx context.Context) (http.Handler, error) { + if vm.CreateHandlersF != nil { + return vm.CreateHTTP2HandlerF(ctx) + } + if vm.CantCreateHTTP2Handler && vm.T != nil { + require.FailNow(vm.T, errCreateHTTP2Handler.Error()) + } + + return nil, nil +} + func (vm *VM) HealthCheck(ctx context.Context) (interface{}, error) { if vm.HealthCheckF != nil { return vm.HealthCheckF(ctx) diff --git a/snow/engine/snowman/block/blockmock/chain_vm.go b/snow/engine/snowman/block/blockmock/chain_vm.go index 051287561454..a93f1be66e88 100644 --- a/snow/engine/snowman/block/blockmock/chain_vm.go +++ b/snow/engine/snowman/block/blockmock/chain_vm.go @@ -133,6 +133,21 @@ func (mr *ChainVMMockRecorder) Connected(ctx, nodeID, nodeVersion any) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connected", reflect.TypeOf((*ChainVM)(nil).Connected), ctx, nodeID, nodeVersion) } +// CreateHTTP2Handler mocks base method. +func (m *ChainVM) CreateHTTP2Handler(ctx context.Context) (http.Handler, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateHTTP2Handler", ctx) + ret0, _ := ret[0].(http.Handler) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateHTTP2Handler indicates an expected call of CreateHTTP2Handler. +func (mr *ChainVMMockRecorder) CreateHTTP2Handler(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateHTTP2Handler", reflect.TypeOf((*ChainVM)(nil).CreateHTTP2Handler), ctx) +} + // CreateHandlers mocks base method. func (m *ChainVM) CreateHandlers(arg0 context.Context) (map[string]http.Handler, error) { m.ctrl.T.Helper() diff --git a/tests/e2e/vms/xsvm.go b/tests/e2e/vms/xsvm.go index b81720917ac5..81b43fd86726 100644 --- a/tests/e2e/vms/xsvm.go +++ b/tests/e2e/vms/xsvm.go @@ -5,13 +5,18 @@ package vms import ( "fmt" + "strings" + "sync" "time" "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/proto/pb/xsvm" "github.com/ava-labs/avalanchego/tests/fixture/e2e" "github.com/ava-labs/avalanchego/tests/fixture/subnet" "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" @@ -178,6 +183,84 @@ var _ = ginkgo.Describe("[XSVM]", ginkgo.Label("xsvm"), func() { _ = e2e.CheckBootstrapIsPossible(tc, network) }) + + ginkgo.It("should serve grpc api requests", func() { + network := e2e.GetEnv(tc).GetNetwork() + log := tc.Log() + if network.DefaultRuntimeConfig.Kube != nil { + ginkgo.Skip("h2c is not currently supported in kube") + } + + tc.By("establishing connection") + nodeID := network.GetSubnet(subnetAName).ValidatorIDs[0] + node, err := network.GetNode(nodeID) + require.NoError(err) + + uri := strings.TrimPrefix(node.URI, "http://") + chainID := network.GetSubnet(subnetAName).Chains[0].ChainID + client, conn, err := api.NewPingClient( + uri, + chainID, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + require.NoError(err) + ginkgo.DeferCleanup(func() { + require.NoError(conn.Close()) + }) + + tc.By("serving unary rpc") + msg := "foobar" + reply, err := client.Ping(tc.DefaultContext(), &xsvm.PingRequest{ + Message: msg, + }) + require.NoError(err) + require.Equal(msg, reply.Message) + + tc.By("serving bidirectional streaming rpc") + stream, err := client.StreamPing(tc.DefaultContext()) + require.NoError(err) + + ginkgo.DeferCleanup(func() { + require.NoError(stream.CloseSend()) + }) + + // Stream pings to the server and block until all events are received + // back. + wg := &sync.WaitGroup{} + wg.Add(2) + + n := 10 + go func() { + defer func() { + ginkgo.GinkgoRecover() + wg.Done() + }() + + for i := 0; i < n; i++ { + msg := fmt.Sprintf("ping-%d", i) + require.NoError(stream.Send(&xsvm.StreamPingRequest{ + Message: msg, + })) + log.Info("sent message", zap.String("msg", msg)) + } + }() + + go func() { + defer func() { + ginkgo.GinkgoRecover() + wg.Done() + }() + + for i := 0; i < n; i++ { + reply, err := stream.Recv() + require.NoError(err) + require.Equal(fmt.Sprintf("ping-%d", i), reply.Message) + log.Info("received message", zap.String("msg", reply.Message)) + } + }() + + wg.Wait() + }) }) // Retrieve the nodes corresponding to the provided IDs diff --git a/tests/fixture/tmpnet/kube_runtime.go b/tests/fixture/tmpnet/kube_runtime.go index f100b42aafda..a4a8cc40571b 100644 --- a/tests/fixture/tmpnet/kube_runtime.go +++ b/tests/fixture/tmpnet/kube_runtime.go @@ -144,8 +144,10 @@ func (p *KubeRuntime) GetLocalURI(ctx context.Context) (string, func(), error) { } } - // TODO(marun) Detect whether this test code is running inside the cluster - // and use the URI directly + // Use direct pod URI if running inside the cluster + if isRunningInCluster() { + return p.node.URI, func() {}, nil + } port, stopChan, err := p.forwardPort(ctx, config.DefaultHTTPPort) if err != nil { @@ -164,8 +166,10 @@ func (p *KubeRuntime) GetLocalStakingAddress(ctx context.Context) (netip.AddrPor } } - // TODO(marun) Detect whether this test code is running inside the cluster - // and use the URI directly + // Use direct pod staking address if running inside the cluster + if isRunningInCluster() { + return p.node.StakingAddress, func() {}, nil + } port, stopChan, err := p.forwardPort(ctx, config.DefaultStakingPort) if err != nil { @@ -837,3 +841,11 @@ func configureExclusiveScheduling(template *corev1.PodTemplateSpec, labelKey str }, } } + +// isRunningInCluster detects if this code is running inside a Kubernetes cluster +// by checking for the presence of the service account token that's automatically +// mounted in every pod. +func isRunningInCluster() bool { + _, err := os.Stat("/var/run/secrets/kubernetes.io/serviceaccount/token") + return err == nil +} diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 89f76bebd08e..dd4c6d0ddc1b 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -318,6 +318,10 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { }, err } +func (*VM) CreateHTTP2Handler(context.Context) (http.Handler, error) { + return nil, nil +} + /* ****************************************************************************** ********************************** Chain VM ********************************** diff --git a/vms/example/xsvm/api/ping.go b/vms/example/xsvm/api/ping.go new file mode 100644 index 000000000000..f8c901c759e1 --- /dev/null +++ b/vms/example/xsvm/api/ping.go @@ -0,0 +1,69 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package api + +import ( + "context" + "errors" + "fmt" + "io" + + "go.uber.org/zap" + "google.golang.org/grpc" + + "github.com/ava-labs/avalanchego/api/grpcclient" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/proto/pb/xsvm" + "github.com/ava-labs/avalanchego/utils/logging" +) + +var _ xsvm.PingServer = (*PingService)(nil) + +type PingService struct { + xsvm.UnsafePingServer + + Log logging.Logger +} + +func (p *PingService) Ping(_ context.Context, request *xsvm.PingRequest) (*xsvm.PingReply, error) { + p.Log.Debug("ping", zap.String("message", request.Message)) + return &xsvm.PingReply{ + Message: request.Message, + }, nil +} + +func (p *PingService) StreamPing(server xsvm.Ping_StreamPingServer) error { + for { + request, err := server.Recv() + if errors.Is(err, io.EOF) { + // Client closed the send stream + return nil + } + if err != nil { + return fmt.Errorf("failed to receive message: %w", err) + } + + p.Log.Debug("stream ping", zap.String("message", request.Message)) + err = server.Send(&xsvm.StreamPingReply{ + Message: request.Message, + }) + if err != nil { + return fmt.Errorf("failed to send message: %w", err) + } + } +} + +// NewPingClient returns a client for PingService +func NewPingClient( + uri string, + chainID ids.ID, + opts ...grpc.DialOption, +) (xsvm.PingClient, *grpc.ClientConn, error) { + conn, err := grpcclient.NewChainClient(uri, chainID, opts...) + if err != nil { + return nil, nil, err + } + + return xsvm.NewPingClient(conn), conn, nil +} diff --git a/vms/example/xsvm/vm.go b/vms/example/xsvm/vm.go index d7386fafad40..aea40ed13c8e 100644 --- a/vms/example/xsvm/vm.go +++ b/vms/example/xsvm/vm.go @@ -11,12 +11,14 @@ import ( "github.com/gorilla/rpc/v2" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" + "google.golang.org/grpc" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/database/versiondb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/network/p2p/acp118" + "github.com/ava-labs/avalanchego/proto/pb/xsvm" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" @@ -152,6 +154,12 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { }, server.RegisterService(api, constants.XSVMName) } +func (vm *VM) CreateHTTP2Handler(context.Context) (http.Handler, error) { + server := grpc.NewServer() + server.RegisterService(&xsvm.Ping_ServiceDesc, &api.PingService{Log: vm.chainContext.Log}) + return server, nil +} + func (*VM) HealthCheck(context.Context) (interface{}, error) { return http.StatusOK, nil } diff --git a/vms/platformvm/vm.go b/vms/platformvm/vm.go index d5958a5703c2..e541452609e9 100644 --- a/vms/platformvm/vm.go +++ b/vms/platformvm/vm.go @@ -466,6 +466,10 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { }, err } +func (*VM) CreateHTTP2Handler(context.Context) (http.Handler, error) { + return nil, nil +} + func (vm *VM) Connected(ctx context.Context, nodeID ids.NodeID, version *version.Application) error { if err := vm.uptimeManager.Connect(nodeID); err != nil { return err diff --git a/vms/rpcchainvm/ghttp/http_client.go b/vms/rpcchainvm/ghttp/http_client.go index 7370d05dcd6c..f9eb586f877d 100644 --- a/vms/rpcchainvm/ghttp/http_client.go +++ b/vms/rpcchainvm/ghttp/http_client.go @@ -36,7 +36,10 @@ func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) { // to specify a communication protocols it supports and would like to // use. Upgrade (e.g. websockets) is a more expensive transaction and // if not required use the less expensive HTTPSimple. - if !isUpgradeRequest(r) { + // + // Http/2 explicitly does not allow the use of the Upgrade header. + // (ref: https://httpwg.org/specs/rfc9113.html#informational-responses) + if !isUpgradeRequest(r) && !isHTTP2Request(r) { c.serveHTTPSimple(w, r) return } @@ -218,3 +221,7 @@ func convertWriteResponse(w http.ResponseWriter, resp *httppb.HandleSimpleHTTPRe func isUpgradeRequest(req *http.Request) bool { return req.Header.Get("Upgrade") != "" } + +func isHTTP2Request(req *http.Request) bool { + return req.ProtoMajor == 2 +} diff --git a/vms/rpcchainvm/vm_client.go b/vms/rpcchainvm/vm_client.go index 497dc09d3dd7..1125e054fc2f 100644 --- a/vms/rpcchainvm/vm_client.go +++ b/vms/rpcchainvm/vm_client.go @@ -389,6 +389,25 @@ func (vm *VMClient) CreateHandlers(ctx context.Context) (map[string]http.Handler return handlers, nil } +func (vm *VMClient) CreateHTTP2Handler(ctx context.Context) (http.Handler, error) { + resp, err := vm.client.CreateHTTP2Handler(ctx, &emptypb.Empty{}) + if err != nil { + return nil, err + } + + if resp.ServerAddr == "" { + return nil, nil + } + + clientConn, err := grpcutils.Dial(resp.ServerAddr) + if err != nil { + return nil, err + } + + vm.conns = append(vm.conns, clientConn) + return ghttp.NewClient(httppb.NewHTTPClient(clientConn)), nil +} + func (vm *VMClient) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error { _, err := vm.client.Connected(ctx, &vmpb.ConnectedRequest{ NodeId: nodeID.Bytes(), diff --git a/vms/rpcchainvm/vm_server.go b/vms/rpcchainvm/vm_server.go index 9b9584066542..370f8ad633b8 100644 --- a/vms/rpcchainvm/vm_server.go +++ b/vms/rpcchainvm/vm_server.go @@ -359,6 +359,34 @@ func (vm *VMServer) CreateHandlers(ctx context.Context, _ *emptypb.Empty) (*vmpb return resp, nil } +func (vm *VMServer) CreateHTTP2Handler(ctx context.Context, _ *emptypb.Empty) (*vmpb.CreateHTTP2HandlerResponse, error) { + handler, err := vm.vm.CreateHTTP2Handler(ctx) + if err != nil { + return nil, err + } + + // The vm does not expose an HTTP2 handler + if handler == nil { + return &vmpb.CreateHTTP2HandlerResponse{}, nil + } + + serverListener, err := grpcutils.NewListener() + if err != nil { + return nil, err + } + + server := grpcutils.NewServer() + vm.serverCloser.Add(server) + httppb.RegisterHTTPServer(server, ghttp.NewServer(handler)) + + // Start HTTP service + go grpcutils.Serve(serverListener, server) + + return &vmpb.CreateHTTP2HandlerResponse{ + ServerAddr: serverListener.Addr().String(), + }, nil +} + func (vm *VMServer) Connected(ctx context.Context, req *vmpb.ConnectedRequest) (*emptypb.Empty, error) { nodeID, err := ids.ToNodeID(req.NodeId) if err != nil { From 08c3af1d7a148b02765834dd0c8152ed174784ba Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 9 Jun 2025 18:27:42 -0500 Subject: [PATCH 07/18] add chain id and subnet id to options --- simplex/bls_test.go | 6 ------ simplex/test_util.go | 8 ++++++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 8bf3c4240129..5c6ceba8400c 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -76,8 +76,6 @@ func TestQCAggregateAndSign(t *testing.T) { options.curNode = options.allNodes[1] config2, err := newEngineConfig(options) - config2.Ctx.ChainID = config.Ctx.ChainID - config2.Ctx.SubnetID = config.Ctx.SubnetID require.NoError(t, err) signer2, verifier2 := NewBLSAuth(config2) @@ -235,8 +233,6 @@ func TestSignatureAggregatorExcessSignatures(t *testing.T) { for i, node := range options.allNodes { options.curNode = node nodeConfig, err := newEngineConfig(options) - nodeConfig.Ctx.ChainID = config.Ctx.ChainID - nodeConfig.Ctx.SubnetID = config.Ctx.SubnetID require.NoError(t, err) nodeSigner, _ := NewBLSAuth(nodeConfig) @@ -272,8 +268,6 @@ func TestQCVerifyWithWrongMessage(t *testing.T) { options.curNode = options.allNodes[1] config2, err := newEngineConfig(options) - config2.Ctx.ChainID = config.Ctx.ChainID - config2.Ctx.SubnetID = config.Ctx.SubnetID require.NoError(t, err) signer2, _ := NewBLSAuth(config2) diff --git a/simplex/test_util.go b/simplex/test_util.go index ad6096bf2eaa..6fb7bcf6d537 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -85,6 +85,8 @@ func newTestValidatorInfo(all []*testValidator) *testValidatorInfo { type testEngineConfig struct { curNode *testValidator // defaults to the first node allNodes []*testValidator // all nodes in the test. defaults to a single node + chainID ids.ID + subnetID ids.ID } func newEngineConfig(options *testEngineConfig) (*Config, error) { @@ -100,8 +102,8 @@ func newEngineConfig(options *testEngineConfig) (*Config, error) { simplexChainContext := SimplexChainContext{ NodeID: options.curNode.nodeID, - ChainID: ids.GenerateTestID(), - SubnetID: ids.GenerateTestID(), + ChainID: options.chainID, + SubnetID: options.subnetID, } return &Config{ @@ -120,5 +122,7 @@ func withNodes(numNodes uint64) (*testEngineConfig, error) { return &testEngineConfig{ curNode: vds[0], allNodes: vds, + chainID: ids.GenerateTestID(), + subnetID: ids.GenerateTestID(), }, nil } From 69c797e883d39e869ccd6a011a012c3b8994dfb1 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 9 Jun 2025 18:34:13 -0500 Subject: [PATCH 08/18] no log copilot lint --- simplex/quorum.go | 5 +++-- simplex/test_util.go | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/simplex/quorum.go b/simplex/quorum.go index 8b46f6da6b87..3f96c03d87f1 100644 --- a/simplex/quorum.go +++ b/simplex/quorum.go @@ -13,8 +13,9 @@ import ( ) var ( - _ simplex.QuorumCertificate = (*QC)(nil) - _ simplex.QCDeserializer = QCDeserializer{} + _ simplex.QuorumCertificate = (*QC)(nil) + _ simplex.QCDeserializer = QCDeserializer{} + _ simplex.SignatureAggregator = (*SignatureAggregator)(nil) ) type QCDeserializer BLSVerifier diff --git a/simplex/test_util.go b/simplex/test_util.go index 6fb7bcf6d537..c042d05bdcba 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" + "github.com/ava-labs/avalanchego/utils/logging" ) var _ ValidatorInfo = (*testValidatorInfo)(nil) @@ -85,7 +86,7 @@ func newTestValidatorInfo(all []*testValidator) *testValidatorInfo { type testEngineConfig struct { curNode *testValidator // defaults to the first node allNodes []*testValidator // all nodes in the test. defaults to a single node - chainID ids.ID + chainID ids.ID subnetID ids.ID } @@ -110,6 +111,7 @@ func newEngineConfig(options *testEngineConfig) (*Config, error) { Ctx: simplexChainContext, Validators: vdrs, SignBLS: options.curNode.sign, + Log: logging.NoLog{}, // TODO: replace with a proper logger }, nil } From ea4bc129d1b2bd37fb41a19aed2dbfb1bab7e3ed Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 10 Jun 2025 16:08:18 -0500 Subject: [PATCH 09/18] serialize qc with asn1 encoding --- simplex/bls.go | 1 + simplex/quorum.go | 93 ++++++++++++++++++++++++++++++----------------- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/simplex/bls.go b/simplex/bls.go index 9bf4a5043453..74d63f2d850c 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -19,6 +19,7 @@ var ( errSignatureVerificationFailed = errors.New("signature verification failed") errSignerNotFound = errors.New("signer not found in the membership set") errFailedToParseSignature = errors.New("failed to parse signature") + errFailedToParseQC = errors.New("failed to parse quorum certificate") errInvalidByteSliceLength = errors.New("invalid byte slice length") errNotEnoughSigners = errors.New("not enough signers") errSignatureAggregation = errors.New("signature aggregation failed") diff --git a/simplex/quorum.go b/simplex/quorum.go index 3f96c03d87f1..bfca9fc5a71a 100644 --- a/simplex/quorum.go +++ b/simplex/quorum.go @@ -4,6 +4,8 @@ package simplex import ( + "encoding/asn1" + "errors" "fmt" "github.com/ava-labs/simplex" @@ -18,8 +20,6 @@ var ( _ simplex.SignatureAggregator = (*SignatureAggregator)(nil) ) -type QCDeserializer BLSVerifier - // QC represents a quorum certificate in the Simplex consensus protocol. type QC struct { verifier BLSVerifier @@ -35,6 +35,9 @@ func (qc *QC) Signers() []simplex.NodeID { // Verify checks if the quorum certificate is valid by verifying the aggregated signature against the signers' public keys. func (qc *QC) Verify(msg []byte) error { pks := make([]*bls.PublicKey, 0, len(qc.signers)) + if len(qc.signers) != simplex.Quorum(len(qc.verifier.nodeID2PK)) { + return fmt.Errorf("%w: expected %d signers but got %d", errNotEnoughSigners, simplex.Quorum(len(qc.verifier.nodeID2PK)), len(qc.signers)) + } // ensure all signers are in the membership set for _, signer := range qc.signers { @@ -64,49 +67,71 @@ func (qc *QC) Verify(msg []byte) error { return nil } -// Bytes serializes the quorum certificate into bytes. -// The serialization format is: -// [signer1][signer2]...[signerN][signature] -// where each signer is represented by its NodeID and the signature is the BLS signature. -func (qc *QC) Bytes() []byte { +// asn1QC is the ASN.1 structure for the quorum certificate. +// It contains the signers' public keys and the aggregated signature. +// The signers are represented as byte slices of their IDs. +type asn1QC struct { + Signers [][]byte + Signature []byte +} + +func (qc *QC) MarshalASN1() ([]byte, error) { sigBytes := bls.SignatureToBytes(&qc.sig) - buff := make([]byte, len(sigBytes)+len(qc.signers)*ids.NodeIDLen) - var pos int - for _, signer := range qc.signers { - copy(buff[pos:], signer[:ids.NodeIDLen]) - pos += ids.NodeIDLen - } - copy(buff[pos:], sigBytes) - return buff + signersBytes := make([][]byte, len(qc.signers)) + for i, signer := range qc.signers { + s := signer // avoid aliasing + signersBytes[i] = s[:] + } + asn1Data := asn1QC{ + Signers: signersBytes, + Signature: sigBytes, + } + return asn1.Marshal(asn1Data) } -// DeserializeQuorumCertificate deserializes a quorum certificate from bytes. -func (d QCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex.QuorumCertificate, error) { - quorumSize := simplex.Quorum(len(d.nodeID2PK)) - expectedSize := quorumSize*ids.NodeIDLen + bls.SignatureLen - if len(bytes) != expectedSize { - return nil, fmt.Errorf("%w: %d expected but got %d bytes", errInvalidByteSliceLength, expectedSize, len(bytes)) +func (qc *QC) UnmarshalASN1(data []byte) error { + var decoded asn1QC + _, err := asn1.Unmarshal(data, &decoded) + if err != nil { + return err + } + qc.signers = make([]simplex.NodeID, len(decoded.Signers)) + for i, signerBytes := range decoded.Signers { + if len(signerBytes) != ids.ShortIDLen { // TODO: so long as simplex is in a separate repo, we should decouple these ids as much as possible + return errors.New("invalid signer length") + } + qc.signers[i] = simplex.NodeID(signerBytes) } + sig, err := bls.SignatureFromBytes(decoded.Signature) + if err != nil { + return err + } + qc.sig = *sig - signers := make([]simplex.NodeID, 0, quorumSize) + return nil +} - var pos int - for range quorumSize { - signers = append(signers, bytes[pos:pos+ids.NodeIDLen]) - pos += ids.NodeIDLen +// Bytes serializes the quorum certificate into bytes. +func (qc *QC) Bytes() []byte { + bytes, err := qc.MarshalASN1() + if err != nil { + panic(fmt.Errorf("failed to marshal QC: %w", err)) } + return bytes +} - sig, err := bls.SignatureFromBytes(bytes[pos:]) - if err != nil { - return nil, fmt.Errorf("%w: %w", errFailedToParseSignature, err) +type QCDeserializer BLSVerifier + +// DeserializeQuorumCertificate deserializes a quorum certificate from bytes. +func (d QCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex.QuorumCertificate, error) { + var qc QC + if err := qc.UnmarshalASN1(bytes); err != nil { + return nil, fmt.Errorf("%w: %w", errFailedToParseQC, err) } + qc.verifier = BLSVerifier(d) - return &QC{ - verifier: BLSVerifier(d), - signers: signers, - sig: *sig, - }, nil + return &qc, nil } // SignatureAggregator aggregates signatures into a quorum certificate. From 49aa0bbd9152938a00cd20543fd0c7bf0e89eb5f Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 10 Jun 2025 16:17:25 -0500 Subject: [PATCH 10/18] style improvements --- simplex/bls.go | 1 - simplex/test_util.go | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/simplex/bls.go b/simplex/bls.go index e7b1ce25259c..be9687e26288 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -72,7 +72,6 @@ type encodedSimplexSignedPayload struct { Label []byte } -// encodesMessageToSign returns a byte slice [simplexLabel][chainID][networkID][message length][message]. func encodeMessageToSign(message []byte, chainID ids.ID, subnetID ids.ID) ([]byte, error) { encodedSimplexMessage := encodedSimplexSignedPayload{ Message: message, diff --git a/simplex/test_util.go b/simplex/test_util.go index e926fe686a4a..7cbbcbaf2a2c 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -19,10 +19,6 @@ type testValidatorInfo struct { } func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { - if v.validators == nil { - return nil - } - ids := make([]ids.NodeID, 0, len(v.validators)) for id := range v.validators { ids = append(ids, id) @@ -36,10 +32,7 @@ func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validato } val, exists := v.validators[nodeID] - if !exists { - return nil, false - } - return &val, true + return &val, exists } func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { From 4dfdb34cf8e0de2ee4732850a210be415506e60e Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 10 Jun 2025 19:52:56 -0500 Subject: [PATCH 11/18] use GetValidatorSet for consistent validator set --- simplex/bls.go | 26 +++++++++++++++----------- simplex/bls_test.go | 9 ++++++--- simplex/config.go | 12 ++++++++++-- simplex/test_util.go | 29 +++++++++++------------------ 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/simplex/bls.go b/simplex/bls.go index be9687e26288..626c66d3937b 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -4,6 +4,7 @@ package simplex import ( + "context" "encoding/asn1" "errors" "fmt" @@ -40,12 +41,14 @@ type BLSVerifier struct { chainID ids.ID } -func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier) { +func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier, error) { + verifier, err := createVerifier(config) + return BLSSigner{ chainID: config.Ctx.ChainID, subnetID: config.Ctx.SubnetID, signBLS: config.SignBLS, - }, createVerifier(config) + }, verifier, err } // Sign returns a signature on the given message using BLS signature scheme. @@ -110,21 +113,22 @@ func (v BLSVerifier) Verify(message []byte, signature []byte, signer simplex.Nod return nil } -func createVerifier(config *Config) BLSVerifier { +func createVerifier(config *Config) (BLSVerifier, error) { verifier := BLSVerifier{ nodeID2PK: make(map[ids.NodeID]bls.PublicKey), subnetID: config.Ctx.SubnetID, chainID: config.Ctx.ChainID, } - nodes := config.Validators.GetValidatorIDs(config.Ctx.SubnetID) + nodes, err := config.Validators.GetValidatorSet(context.Background(), 0, config.Ctx.SubnetID) + if err != nil { + config.Log.Error("failed to get validator set", zap.Error(err), zap.Stringer("subnetID", config.Ctx.SubnetID)) + return BLSVerifier{}, err + } + for _, node := range nodes { - validator, ok := config.Validators.GetValidator(config.Ctx.SubnetID, node) - if !ok { - config.Log.Error("failed to get validator for node %s in subnet %s", zap.Stringer("node", node), zap.Stringer("subnetID", config.Ctx.SubnetID)) - continue - } - verifier.nodeID2PK[node] = *validator.PublicKey + verifier.nodeID2PK[node.NodeID] = *node.PublicKey } - return verifier + + return verifier, nil } diff --git a/simplex/bls_test.go b/simplex/bls_test.go index e5c59662b356..b08b36ab2da5 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -16,7 +16,8 @@ func TestBLSSignVerify(t *testing.T) { config, err := newEngineConfig() require.NoError(t, err) - signer, verifier := NewBLSAuth(config) + signer, verifier, err := NewBLSAuth(config) + require.NoError(t, err) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -30,7 +31,8 @@ func TestBLSSignVerify(t *testing.T) { func TestSignerNotInMemberSet(t *testing.T) { config, err := newEngineConfig() require.NoError(t, err) - signer, verifier := NewBLSAuth(config) + signer, verifier, err := NewBLSAuth(config) + require.NoError(t, err) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -53,7 +55,8 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { sigBytes := bls.SignatureToBytes(sig) - _, verifier := NewBLSAuth(config) + _, verifier, err := NewBLSAuth(config) + require.NoError(t, err) err = verifier.Verify(dummyMsg, sigBytes, config.Ctx.NodeID[:]) require.ErrorIs(t, err, errSignatureVerificationFailed) } diff --git a/simplex/config.go b/simplex/config.go index 8e16e26e3e99..e778e408de12 100644 --- a/simplex/config.go +++ b/simplex/config.go @@ -4,14 +4,22 @@ package simplex import ( + "context" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/logging" ) type ValidatorInfo interface { - GetValidatorIDs(subnetID ids.ID) []ids.NodeID - GetValidator(subnetID ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) + // GetValidatorSet returns the validators of the provided subnet at the + // requested P-chain height. + // The returned map should not be modified. + GetValidatorSet( + ctx context.Context, + height uint64, + subnetID ids.ID, + ) (map[ids.NodeID]*validators.GetValidatorOutput, error) } // Config wraps all the parameters needed for a simplex engine diff --git a/simplex/test_util.go b/simplex/test_util.go index 7cbbcbaf2a2c..2ac87c13ffd2 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -4,6 +4,8 @@ package simplex import ( + "context" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" @@ -15,24 +17,15 @@ var _ ValidatorInfo = (*testValidatorInfo)(nil) // testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. // it assumes all validators are in the same subnet and returns all of them for any subnetID. type testValidatorInfo struct { - validators map[ids.NodeID]validators.Validator -} - -func (v *testValidatorInfo) GetValidatorIDs(_ ids.ID) []ids.NodeID { - ids := make([]ids.NodeID, 0, len(v.validators)) - for id := range v.validators { - ids = append(ids, id) - } - return ids + validators map[ids.NodeID]*validators.GetValidatorOutput } -func (v *testValidatorInfo) GetValidator(_ ids.ID, nodeID ids.NodeID) (*validators.Validator, bool) { - if v.validators == nil { - return nil, false - } - - val, exists := v.validators[nodeID] - return &val, exists +func (t *testValidatorInfo) GetValidatorSet( + context.Context, + uint64, + ids.ID, +) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + return t.validators, nil } func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { @@ -40,9 +33,9 @@ func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValid panic("nodeIds and pks must have the same length") } - vds := make(map[ids.NodeID]validators.Validator, len(pks)) + vds := make(map[ids.NodeID]*validators.GetValidatorOutput, len(pks)) for i, pk := range pks { - validator := validators.Validator{ + validator := &validators.GetValidatorOutput{ PublicKey: pk, NodeID: nodeIds[i], } From 8c78c03eb627fdb67dbee3d70ba74c70dc284a11 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 11 Jun 2025 11:23:56 -0500 Subject: [PATCH 12/18] pass in membership set to config --- simplex/bls.go | 20 ++++++-------------- simplex/bls_test.go | 9 +++------ simplex/config.go | 27 ++++++++++----------------- simplex/test_util.go | 24 ++---------------------- 4 files changed, 21 insertions(+), 59 deletions(-) diff --git a/simplex/bls.go b/simplex/bls.go index 626c66d3937b..524c91842da8 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -4,13 +4,11 @@ package simplex import ( - "context" "encoding/asn1" "errors" "fmt" "github.com/ava-labs/simplex" - "go.uber.org/zap" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" @@ -41,14 +39,14 @@ type BLSVerifier struct { chainID ids.ID } -func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier, error) { - verifier, err := createVerifier(config) +func NewBLSAuth(config *Config) (BLSSigner, BLSVerifier) { + verifier := createVerifier(config) return BLSSigner{ chainID: config.Ctx.ChainID, subnetID: config.Ctx.SubnetID, signBLS: config.SignBLS, - }, verifier, err + }, verifier } // Sign returns a signature on the given message using BLS signature scheme. @@ -113,22 +111,16 @@ func (v BLSVerifier) Verify(message []byte, signature []byte, signer simplex.Nod return nil } -func createVerifier(config *Config) (BLSVerifier, error) { +func createVerifier(config *Config) BLSVerifier { verifier := BLSVerifier{ nodeID2PK: make(map[ids.NodeID]bls.PublicKey), subnetID: config.Ctx.SubnetID, chainID: config.Ctx.ChainID, } - nodes, err := config.Validators.GetValidatorSet(context.Background(), 0, config.Ctx.SubnetID) - if err != nil { - config.Log.Error("failed to get validator set", zap.Error(err), zap.Stringer("subnetID", config.Ctx.SubnetID)) - return BLSVerifier{}, err - } - - for _, node := range nodes { + for _, node := range config.Validators { verifier.nodeID2PK[node.NodeID] = *node.PublicKey } - return verifier, nil + return verifier } diff --git a/simplex/bls_test.go b/simplex/bls_test.go index b08b36ab2da5..e5c59662b356 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -16,8 +16,7 @@ func TestBLSSignVerify(t *testing.T) { config, err := newEngineConfig() require.NoError(t, err) - signer, verifier, err := NewBLSAuth(config) - require.NoError(t, err) + signer, verifier := NewBLSAuth(config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -31,8 +30,7 @@ func TestBLSSignVerify(t *testing.T) { func TestSignerNotInMemberSet(t *testing.T) { config, err := newEngineConfig() require.NoError(t, err) - signer, verifier, err := NewBLSAuth(config) - require.NoError(t, err) + signer, verifier := NewBLSAuth(config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -55,8 +53,7 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { sigBytes := bls.SignatureToBytes(sig) - _, verifier, err := NewBLSAuth(config) - require.NoError(t, err) + _, verifier := NewBLSAuth(config) err = verifier.Verify(dummyMsg, sigBytes, config.Ctx.NodeID[:]) require.ErrorIs(t, err, errSignatureVerificationFailed) } diff --git a/simplex/config.go b/simplex/config.go index e778e408de12..ecd792eb3646 100644 --- a/simplex/config.go +++ b/simplex/config.go @@ -4,30 +4,23 @@ package simplex import ( - "context" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/logging" ) -type ValidatorInfo interface { - // GetValidatorSet returns the validators of the provided subnet at the - // requested P-chain height. - // The returned map should not be modified. - GetValidatorSet( - ctx context.Context, - height uint64, - subnetID ids.ID, - ) (map[ids.NodeID]*validators.GetValidatorOutput, error) -} - // Config wraps all the parameters needed for a simplex engine type Config struct { - Ctx SimplexChainContext - Log logging.Logger - Validators ValidatorInfo - SignBLS SignFunc + Ctx SimplexChainContext + Log logging.Logger + + // Validators is a map of node IDs to their validator information. + // This tells the node about the current membership set, and should be consistent + // across all nodes in the subnet. + Validators map[ids.NodeID]*validators.GetValidatorOutput + + // SignBLS is the signing function used for this node to sign messages. + SignBLS SignFunc } // Context is information about the current execution. diff --git a/simplex/test_util.go b/simplex/test_util.go index 2ac87c13ffd2..86e0c4323045 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -4,31 +4,13 @@ package simplex import ( - "context" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" ) -var _ ValidatorInfo = (*testValidatorInfo)(nil) - -// testValidatorInfo is a mock implementation of ValidatorInfo for testing purposes. -// it assumes all validators are in the same subnet and returns all of them for any subnetID. -type testValidatorInfo struct { - validators map[ids.NodeID]*validators.GetValidatorOutput -} - -func (t *testValidatorInfo) GetValidatorSet( - context.Context, - uint64, - ids.ID, -) (map[ids.NodeID]*validators.GetValidatorOutput, error) { - return t.validators, nil -} - -func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValidatorInfo { +func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) map[ids.NodeID]*validators.GetValidatorOutput { if len(nodeIds) != len(pks) { panic("nodeIds and pks must have the same length") } @@ -42,9 +24,7 @@ func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) *testValid vds[nodeIds[i]] = validator } // all we need is to generate the public keys for the validators - return &testValidatorInfo{ - validators: vds, - } + return vds } func newEngineConfig() (*Config, error) { From 14ad42faaa6b73395d4ceb651711efe0f2393a51 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 11 Jun 2025 11:31:19 -0500 Subject: [PATCH 13/18] remove comment --- simplex/test_util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplex/test_util.go b/simplex/test_util.go index 86e0c4323045..9541a6d2b2dd 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -23,7 +23,7 @@ func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) map[ids.No } vds[nodeIds[i]] = validator } - // all we need is to generate the public keys for the validators + return vds } From ed4422b956188ebd520aa00fcf447586551c6766 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 12 Jun 2025 14:03:38 -0500 Subject: [PATCH 14/18] test_util simplified --- simplex/test_util.go | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/simplex/test_util.go b/simplex/test_util.go index 9541a6d2b2dd..0e8a90378eb6 100644 --- a/simplex/test_util.go +++ b/simplex/test_util.go @@ -6,22 +6,13 @@ package simplex import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" ) -func newTestValidatorInfo(nodeIds []ids.NodeID, pks []*bls.PublicKey) map[ids.NodeID]*validators.GetValidatorOutput { - if len(nodeIds) != len(pks) { - panic("nodeIds and pks must have the same length") - } - - vds := make(map[ids.NodeID]*validators.GetValidatorOutput, len(pks)) - for i, pk := range pks { - validator := &validators.GetValidatorOutput{ - PublicKey: pk, - NodeID: nodeIds[i], - } - vds[nodeIds[i]] = validator +func newTestValidatorInfo(allVds []validators.GetValidatorOutput) map[ids.NodeID]*validators.GetValidatorOutput { + vds := make(map[ids.NodeID]*validators.GetValidatorOutput, len(allVds)) + for _, vd := range allVds { + vds[vd.NodeID] = &vd } return vds @@ -41,9 +32,14 @@ func newEngineConfig() (*Config, error) { SubnetID: ids.GenerateTestID(), } + nodeInfo := validators.GetValidatorOutput{ + NodeID: nodeID, + PublicKey: ls.PublicKey(), + } + return &Config{ Ctx: simplexChainContext, - Validators: newTestValidatorInfo([]ids.NodeID{nodeID}, []*bls.PublicKey{ls.PublicKey()}), + Validators: newTestValidatorInfo([]validators.GetValidatorOutput{nodeInfo}), SignBLS: ls.Sign, }, nil } From 88b06d5958dc29584ddacfd5bc4462c759b0c600 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 12 Jun 2025 14:38:28 -0500 Subject: [PATCH 15/18] go get --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 62b5e5bc8b69..18c41928d458 100644 --- a/go.mod +++ b/go.mod @@ -84,7 +84,7 @@ require ( github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect - github.com/ava-labs/simplex v0.0.0-20250605162940-db8e6d44f53d + github.com/ava-labs/simplex v0.0.0-20250611154800-78b82e9820e5 github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect diff --git a/go.sum b/go.sum index 265cffc1dda4..5eedbfcb4301 100644 --- a/go.sum +++ b/go.sum @@ -70,10 +70,10 @@ github.com/ava-labs/coreth v0.15.2-rc.0.0.20250610170140-2fcf45f828a2 h1:/E1w2S6 github.com/ava-labs/coreth v0.15.2-rc.0.0.20250610170140-2fcf45f828a2/go.mod h1:cqwBag+zzqifDutdPVzZKovfC2d0L8Zxq4YgTGaMCwg= github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60 h1:EL66gtXOAwR/4KYBjOV03LTWgkEXvLePribLlJNu4g0= github.com/ava-labs/ledger-avalanche/go v0.0.0-20241009183145-e6f90a8a1a60/go.mod h1:/7qKobTfbzBu7eSTVaXMTr56yTYk4j2Px6/8G+idxHo= -github.com/ava-labs/simplex v0.0.0-20250605162940-db8e6d44f53d h1:D/BOS3USdAigun2OP/6khvukKnn4BIKviYAdKLHN6zc= -github.com/ava-labs/simplex v0.0.0-20250605162940-db8e6d44f53d/go.mod h1:GVzumIo3zR23/qGRN2AdnVkIPHcKMq/D89EGWZfMGQ0= github.com/ava-labs/libevm v0.0.0-20250610142802-2672fbd7cdfc h1:cSXaUY4hdmoJ2FJOgOzn+WiovN/ZB/zkNRgnZhE50OA= github.com/ava-labs/libevm v0.0.0-20250610142802-2672fbd7cdfc/go.mod h1:+Iol+sVQ1KyoBsHf3veyrBmHCXr3xXRWq6ZXkgVfNLU= +github.com/ava-labs/simplex v0.0.0-20250611154800-78b82e9820e5 h1:rwPm63i5nJ2XIuNjO2H68gDmMKje0VW7orLZMISPrC8= +github.com/ava-labs/simplex v0.0.0-20250611154800-78b82e9820e5/go.mod h1:GVzumIo3zR23/qGRN2AdnVkIPHcKMq/D89EGWZfMGQ0= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= From 0c9c8bf8952e4d59856aff0a6a315b5a53bfac2d Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 13 Jun 2025 10:35:56 -0500 Subject: [PATCH 16/18] update tests --- simplex/bls.go | 1 - simplex/bls_test.go | 128 ++++++++++++++++--------------------------- simplex/test_util.go | 56 ------------------- simplex/util_test.go | 112 +++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 137 deletions(-) delete mode 100644 simplex/test_util.go create mode 100644 simplex/util_test.go diff --git a/simplex/bls.go b/simplex/bls.go index a6714364322c..3af19da74613 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -19,7 +19,6 @@ var ( errSignerNotFound = errors.New("signer not found in the membership set") errFailedToParseSignature = errors.New("failed to parse signature") errFailedToParseQC = errors.New("failed to parse quorum certificate") - errInvalidByteSliceLength = errors.New("invalid byte slice length") errNotEnoughSigners = errors.New("not enough signers") errSignatureAggregation = errors.New("signature aggregation failed") errEncodingMessageToSign = errors.New("failed to encode message to sign") diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 5c6ceba8400c..0db1d86ed5db 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -14,10 +14,9 @@ import ( ) func TestBLSSignVerify(t *testing.T) { - config, err := newEngineConfig(nil) - require.NoError(t, err) + config := newEngineConfig(t, 1) - signer, verifier := NewBLSAuth(config) + signer, verifier := NewBLSAuth(&config.Config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -29,9 +28,8 @@ func TestBLSSignVerify(t *testing.T) { } func TestSignerNotInMemberSet(t *testing.T) { - config, err := newEngineConfig(nil) - require.NoError(t, err) - signer, verifier := NewBLSAuth(config) + config := newEngineConfig(t, 1) + signer, verifier := NewBLSAuth(&config.Config) msg := "Begin at the beginning, and go on till you come to the end: then stop" @@ -44,8 +42,7 @@ func TestSignerNotInMemberSet(t *testing.T) { } func TestSignerInvalidMessageEncoding(t *testing.T) { - config, err := newEngineConfig(nil) - require.NoError(t, err) + config := newEngineConfig(t, 1) // sign a message with invalid encoding dummyMsg := []byte("dummy message") @@ -54,7 +51,7 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { sigBytes := bls.SignatureToBytes(sig) - _, verifier := NewBLSAuth(config) + _, verifier := NewBLSAuth(&config.Config) err = verifier.Verify(dummyMsg, sigBytes, config.Ctx.NodeID[:]) require.ErrorIs(t, err, errSignatureVerificationFailed) } @@ -62,37 +59,32 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { // TestQCAggregateAndSign tests the aggregation of multiple signatures // and then verifies the generated quorum certificate on that message. func TestQCAggregateAndSign(t *testing.T) { - options, err := withNodes(2) - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 2) - signer, verifier := NewBLSAuth(config) + signer, verifier := NewBLSAuth(&config.Config) // nodes 1 and 2 will sign the same message msg := []byte("Begin at the beginning, and go on till you come to the end: then stop") sig, err := signer.Sign(msg) require.NoError(t, err) require.NoError(t, verifier.Verify(msg, sig, config.Ctx.NodeID[:])) - options.curNode = options.allNodes[1] - config2, err := newEngineConfig(options) - require.NoError(t, err) - - signer2, verifier2 := NewBLSAuth(config2) + node2ID := getNewSigner(config.Nodes, config.Ctx.NodeID) + config.SignBLS = node2ID.sign + signer2, verifier2 := NewBLSAuth(&config.Config) sig2, err := signer2.Sign(msg) require.NoError(t, err) - require.NoError(t, verifier2.Verify(msg, sig2, config2.Ctx.NodeID[:])) + require.NoError(t, verifier2.Verify(msg, sig2, node2ID.NodeID[:])) // aggregate the signatures into a quorum certificate signatureAggregator := SignatureAggregator(verifier) qc, err := signatureAggregator.Aggregate( []simplex.Signature{ {Signer: config.Ctx.NodeID[:], Value: sig}, - {Signer: config2.Ctx.NodeID[:], Value: sig2}, + {Signer: node2ID.NodeID[:], Value: sig2}, }, ) require.NoError(t, err) - require.Equal(t, []simplex.NodeID{config.Ctx.NodeID[:], config2.Ctx.NodeID[:]}, qc.Signers()) + require.Equal(t, []simplex.NodeID{config.Ctx.NodeID[:], node2ID.NodeID[:]}, qc.Signers()) // verify the quorum certificate require.NoError(t, qc.Verify(msg)) @@ -107,49 +99,43 @@ func TestQCAggregateAndSign(t *testing.T) { } func TestQCSignerNotInMembershipSet(t *testing.T) { - options, err := withNodes(2) - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 2) + nodeID1 := config.Ctx.NodeID - signer, verifier := NewBLSAuth(config) + signer, verifier := NewBLSAuth(&config.Config) // nodes 1 and 2 will sign the same message msg := []byte("Begin at the beginning, and go on till you come to the end: then stop") sig, err := signer.Sign(msg) require.NoError(t, err) require.NoError(t, verifier.Verify(msg, sig, config.Ctx.NodeID[:])) - // vds is not in the membership set of the first node - vds, err := newTestValidators(1) - require.NoError(t, err) + // add a new validator, but it won't be in the membership set of the first node signer/verifier + vds := generateTestValidators(t, 1) + config.Ctx.NodeID = vds[0].NodeID + config.Validators[vds[0].NodeID] = &vds[0].GetValidatorOutput + config.SignBLS = vds[0].sign - options.curNode = vds[0] - options.allNodes[0] = vds[0] - config2, err := newEngineConfig(options) - require.NoError(t, err) - signer2, verifier2 := NewBLSAuth(config2) + // sign the same message with the new node + signer2, verifier2 := NewBLSAuth(&config.Config) sig2, err := signer2.Sign(msg) require.NoError(t, err) - require.NoError(t, verifier2.Verify(msg, sig2, config2.Ctx.NodeID[:])) + require.NoError(t, verifier2.Verify(msg, sig2, vds[0].NodeID[:])) // aggregate the signatures into a quorum certificate signatureAggregator := SignatureAggregator(verifier) _, err = signatureAggregator.Aggregate( []simplex.Signature{ - {Signer: config.Ctx.NodeID[:], Value: sig}, - {Signer: config2.Ctx.NodeID[:], Value: sig2}, + {Signer: nodeID1[:], Value: sig}, + {Signer: config.Ctx.NodeID[:], Value: sig2}, }, ) require.ErrorIs(t, err, errSignerNotFound) } func TestQCDeserializerInvalidInput(t *testing.T) { - options, err := withNodes(2) - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 2) - _, verifier := NewBLSAuth(config) + _, verifier := NewBLSAuth(&config.Config) deserializer := QCDeserializer(verifier) tests := []struct { @@ -160,12 +146,12 @@ func TestQCDeserializerInvalidInput(t *testing.T) { { name: "too short input", input: make([]byte, 10), - err: errInvalidByteSliceLength, + err: errFailedToParseQC, }, { name: "invalid signature bytes", input: make([]byte, simplex.Quorum(len(verifier.nodeID2PK))*ids.NodeIDLen+bls.SignatureLen), - err: errFailedToParseSignature, + err: errFailedToParseQC, }, } @@ -178,12 +164,9 @@ func TestQCDeserializerInvalidInput(t *testing.T) { } func TestSignatureAggregatorInsufficientSignatures(t *testing.T) { - options, err := withNodes(3) - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 3) - signer, verifier := NewBLSAuth(config) + signer, verifier := NewBLSAuth(&config.Config) msg := []byte("test message") sig, err := signer.Sign(msg) require.NoError(t, err) @@ -199,12 +182,9 @@ func TestSignatureAggregatorInsufficientSignatures(t *testing.T) { } func TestSignatureAggregatorInvalidSignatureBytes(t *testing.T) { - options, err := withNodes(2) - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 2) - signer, verifier := NewBLSAuth(config) + signer, verifier := NewBLSAuth(&config.Config) msg := []byte("test message") sig, err := signer.Sign(msg) require.NoError(t, err) @@ -220,26 +200,20 @@ func TestSignatureAggregatorInvalidSignatureBytes(t *testing.T) { } func TestSignatureAggregatorExcessSignatures(t *testing.T) { - options, err := withNodes(4) // quorum will be 3 - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 4) - _, verifier := NewBLSAuth(config) + _, verifier := NewBLSAuth(&config.Config) msg := []byte("test message") // Create signatures from all 4 nodes signatures := make([]simplex.Signature, 4) - for i, node := range options.allNodes { - options.curNode = node - nodeConfig, err := newEngineConfig(options) - require.NoError(t, err) - - nodeSigner, _ := NewBLSAuth(nodeConfig) + for i, node := range config.Nodes { + config.SignBLS = node.sign + nodeSigner, _ := NewBLSAuth(&config.Config) sig, err := nodeSigner.Sign(msg) require.NoError(t, err) - signatures[i] = simplex.Signature{Signer: nodeConfig.Ctx.NodeID[:], Value: sig} + signatures[i] = simplex.Signature{Signer: node.NodeID[:], Value: sig} } // Aggregate should only use the first 3 signatures @@ -248,17 +222,14 @@ func TestSignatureAggregatorExcessSignatures(t *testing.T) { require.NoError(t, err) // Should only have 3 signers, not 4 - require.Len(t, qc.Signers(), simplex.Quorum(len(options.allNodes))) + require.Len(t, qc.Signers(), simplex.Quorum(len(config.Nodes))) require.NoError(t, qc.Verify(msg)) } func TestQCVerifyWithWrongMessage(t *testing.T) { - options, err := withNodes(2) - require.NoError(t, err) - config, err := newEngineConfig(options) - require.NoError(t, err) + config := newEngineConfig(t, 2) - signer, verifier := NewBLSAuth(config) + signer, verifier := NewBLSAuth(&config.Config) originalMsg := []byte("original message") wrongMsg := []byte("wrong message") @@ -266,19 +237,16 @@ func TestQCVerifyWithWrongMessage(t *testing.T) { sig1, err := signer.Sign(originalMsg) require.NoError(t, err) - options.curNode = options.allNodes[1] - config2, err := newEngineConfig(options) - require.NoError(t, err) - - signer2, _ := NewBLSAuth(config2) + config.SignBLS = config.Nodes[1].sign + signer2, _ := NewBLSAuth(&config.Config) sig2, err := signer2.Sign(originalMsg) require.NoError(t, err) signatureAggregator := SignatureAggregator(verifier) qc, err := signatureAggregator.Aggregate( []simplex.Signature{ - {Signer: config.Ctx.NodeID[:], Value: sig1}, - {Signer: config2.Ctx.NodeID[:], Value: sig2}, + {Signer: config.Nodes[0].NodeID[:], Value: sig1}, + {Signer: config.Nodes[1].NodeID[:], Value: sig2}, }, ) require.NoError(t, err) diff --git a/simplex/test_util.go b/simplex/test_util.go deleted file mode 100644 index d245771056f9..000000000000 --- a/simplex/test_util.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package simplex - -import ( - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" - "github.com/ava-labs/avalanchego/utils/logging" -) - -func newTestValidatorInfo(allVds []validators.GetValidatorOutput) map[ids.NodeID]*validators.GetValidatorOutput { - vds := make(map[ids.NodeID]*validators.GetValidatorOutput, len(allVds)) - for _, vd := range allVds { - vds[vd.NodeID] = &vd - } - - return vds -} - -type testEngineConfig struct { - curNode *testValidator // defaults to the first node - allNodes []*testValidator // all nodes in the test. defaults to a single node - chainID ids.ID - subnetID ids.ID -} - -func newEngineConfig(options *testEngineConfig) (*Config, error) { - if options == nil { - defaultOptions, err := withNodes(1) - if err != nil { - return nil, err - } - options = defaultOptions - } - - vdrs := newTestValidatorInfo(options.allNodes) - - simplexChainContext := SimplexChainContext{ - NodeID: options.curNode.nodeID, - ChainID: options.chainID, - SubnetID: options.subnetID, - } - - nodeInfo := validators.GetValidatorOutput{ - NodeID: nodeID, - PublicKey: ls.PublicKey(), - } - - return &Config{ - Ctx: simplexChainContext, - Validators: newTestValidatorInfo([]validators.GetValidatorOutput{nodeInfo}), - SignBLS: ls.Sign, - }, nil -} diff --git a/simplex/util_test.go b/simplex/util_test.go new file mode 100644 index 000000000000..287ca1089f1f --- /dev/null +++ b/simplex/util_test.go @@ -0,0 +1,112 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package simplex + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner" +) + +type testConfig struct { + Config + Nodes []*testSigner +} + +type testSigner struct { + validators.GetValidatorOutput + sign SignFunc +} + +func newTestValidators(allVds []*testSigner) map[ids.NodeID]*validators.GetValidatorOutput { + vds := make(map[ids.NodeID]*validators.GetValidatorOutput, len(allVds)) + for _, vd := range allVds { + vds[vd.NodeID] = &validators.GetValidatorOutput{ + NodeID: vd.NodeID, + PublicKey: vd.PublicKey, + Weight: 1, // Default weight for testing + } + } + + return vds +} + +func newEngineConfig(t *testing.T, numNodes uint64) *testConfig { + if numNodes == 0 { + panic("numNodes must be greater than 0") + } + + ls, err := localsigner.New() + require.NoError(t, err) + + nodeID := ids.GenerateTestNodeID() + + simplexChainContext := SimplexChainContext{ + NodeID: nodeID, + ChainID: ids.GenerateTestID(), + SubnetID: ids.GenerateTestID(), + } + + nodeInfo := &testSigner{ + GetValidatorOutput: validators.GetValidatorOutput{ + NodeID: nodeID, + PublicKey: ls.PublicKey(), + }, + sign: ls.Sign, + } + + nodes := generateTestValidators(t, numNodes-1) + nodes = append([]*testSigner{nodeInfo}, nodes...) + + return &testConfig{ + Config: Config{ + Ctx: simplexChainContext, + Validators: newTestValidators(nodes), + SignBLS: ls.Sign, + }, + Nodes: nodes, + } +} + +func generateTestValidators(t *testing.T, num uint64) []*testSigner { + vds := make([]*testSigner, num) + for i := uint64(0); i < num; i++ { + ls, err := localsigner.New() + require.NoError(t, err) + + nodeID := ids.GenerateTestNodeID() + vds[i] = &testSigner{ + GetValidatorOutput: validators.GetValidatorOutput{ + NodeID: nodeID, + PublicKey: ls.PublicKey(), + }, + sign: ls.Sign, + } + } + return vds +} + +// getNewSigner returns a new signer that is not already selected. +func getNewSigner(signers []*testSigner, selected ...ids.NodeID) *testSigner { + for _, signer := range signers { + // if vd is already selected, skip it + found := false + for _, id := range selected { + if id == signer.NodeID { + found = true + break + } + } + + if !found { + return signer + } + } + + return nil +} From 0fdb95b75ad70af29a81d8e9c0c23db90c484f79 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 13 Jun 2025 14:25:20 -0500 Subject: [PATCH 17/18] lint and format --- simplex/bls_test.go | 13 +++++++------ simplex/util_test.go | 20 -------------------- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 0db1d86ed5db..e04a00f6339f 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -60,6 +60,7 @@ func TestSignerInvalidMessageEncoding(t *testing.T) { // and then verifies the generated quorum certificate on that message. func TestQCAggregateAndSign(t *testing.T) { config := newEngineConfig(t, 2) + nodeID1 := config.Ctx.NodeID signer, verifier := NewBLSAuth(&config.Config) // nodes 1 and 2 will sign the same message @@ -68,23 +69,23 @@ func TestQCAggregateAndSign(t *testing.T) { require.NoError(t, err) require.NoError(t, verifier.Verify(msg, sig, config.Ctx.NodeID[:])) - node2ID := getNewSigner(config.Nodes, config.Ctx.NodeID) - config.SignBLS = node2ID.sign + node2 := config.Nodes[1] + config.SignBLS = node2.sign signer2, verifier2 := NewBLSAuth(&config.Config) sig2, err := signer2.Sign(msg) require.NoError(t, err) - require.NoError(t, verifier2.Verify(msg, sig2, node2ID.NodeID[:])) + require.NoError(t, verifier2.Verify(msg, sig2, node2.NodeID[:])) // aggregate the signatures into a quorum certificate signatureAggregator := SignatureAggregator(verifier) qc, err := signatureAggregator.Aggregate( []simplex.Signature{ - {Signer: config.Ctx.NodeID[:], Value: sig}, - {Signer: node2ID.NodeID[:], Value: sig2}, + {Signer: nodeID1[:], Value: sig}, + {Signer: node2.NodeID[:], Value: sig2}, }, ) require.NoError(t, err) - require.Equal(t, []simplex.NodeID{config.Ctx.NodeID[:], node2ID.NodeID[:]}, qc.Signers()) + require.Equal(t, []simplex.NodeID{config.Ctx.NodeID[:], node2.NodeID[:]}, qc.Signers()) // verify the quorum certificate require.NoError(t, qc.Verify(msg)) diff --git a/simplex/util_test.go b/simplex/util_test.go index 287ca1089f1f..880da9fbf758 100644 --- a/simplex/util_test.go +++ b/simplex/util_test.go @@ -90,23 +90,3 @@ func generateTestValidators(t *testing.T, num uint64) []*testSigner { } return vds } - -// getNewSigner returns a new signer that is not already selected. -func getNewSigner(signers []*testSigner, selected ...ids.NodeID) *testSigner { - for _, signer := range signers { - // if vd is already selected, skip it - found := false - for _, id := range selected { - if id == signer.NodeID { - found = true - break - } - } - - if !found { - return signer - } - } - - return nil -} From 6b7b56bf35889e2a17dbd4ea05f6e875d6bc9d38 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 30 Jun 2025 14:23:17 -0400 Subject: [PATCH 18/18] a few merge conflicts --- simplex/bls.go | 21 +++++-------- simplex/bls_test.go | 1 + simplex/quorum.go | 4 +-- simplex/util_test.go | 72 ++++++++++++++++++++++---------------------- 4 files changed, 46 insertions(+), 52 deletions(-) diff --git a/simplex/bls.go b/simplex/bls.go index ad679b8f56b1..9ad501175ebd 100644 --- a/simplex/bls.go +++ b/simplex/bls.go @@ -1,17 +1,3 @@ - - -var ( - errSignatureVerificationFailed = errors.New("signature verification failed") - errSignerNotFound = errors.New("signer not found in the membership set") - errFailedToParseSignature = errors.New("failed to parse signature") - errFailedToParseQC = errors.New("failed to parse quorum certificate") - errNotEnoughSigners = errors.New("not enough signers") - errSignatureAggregation = errors.New("signature aggregation failed") - errEncodingMessageToSign = errors.New("failed to encode message to sign") - simplexLabel = []byte("simplex") -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - package simplex import ( @@ -29,6 +15,13 @@ var ( errSignerNotFound = errors.New("signer not found in the membership set") errInvalidNodeID = errors.New("unable to parse node ID") errFailedToParseSignature = errors.New("failed to parse signature") + + // QC errors + errFailedToParseQC = errors.New("failed to parse quorum certificate") + errNotEnoughSigners = errors.New("not enough signers") + errSignatureAggregation = errors.New("signature aggregation failed") + errEncodingMessageToSign = errors.New("failed to encode message to sign") + simplexLabel = []byte("simplex") ) var _ simplex.Signer = (*BLSSigner)(nil) diff --git a/simplex/bls_test.go b/simplex/bls_test.go index 531bdb57632d..37ace583738e 100644 --- a/simplex/bls_test.go +++ b/simplex/bls_test.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/simplex" ) func TestBLSVerifier(t *testing.T) { diff --git a/simplex/quorum.go b/simplex/quorum.go index bfca9fc5a71a..300b8e355a10 100644 --- a/simplex/quorum.go +++ b/simplex/quorum.go @@ -46,7 +46,7 @@ func (qc *QC) Verify(msg []byte) error { return fmt.Errorf("%w: %x", errSignerNotFound, signer) } - pks = append(pks, &pk) + pks = append(pks, pk) } // aggregate the public keys @@ -55,7 +55,7 @@ func (qc *QC) Verify(msg []byte) error { return fmt.Errorf("%w: %w", errSignatureAggregation, err) } - message2Verify, err := encodeMessageToSign(msg, qc.verifier.chainID, qc.verifier.subnetID) + message2Verify, err := encodeMessageToSign(msg, qc.verifier.chainID, qc.verifier.networkID) if err != nil { return fmt.Errorf("%w: %w", errEncodingMessageToSign, err) } diff --git a/simplex/util_test.go b/simplex/util_test.go index 880da9fbf758..7221194bf746 100644 --- a/simplex/util_test.go +++ b/simplex/util_test.go @@ -36,42 +36,42 @@ func newTestValidators(allVds []*testSigner) map[ids.NodeID]*validators.GetValid return vds } -func newEngineConfig(t *testing.T, numNodes uint64) *testConfig { - if numNodes == 0 { - panic("numNodes must be greater than 0") - } - - ls, err := localsigner.New() - require.NoError(t, err) - - nodeID := ids.GenerateTestNodeID() - - simplexChainContext := SimplexChainContext{ - NodeID: nodeID, - ChainID: ids.GenerateTestID(), - SubnetID: ids.GenerateTestID(), - } - - nodeInfo := &testSigner{ - GetValidatorOutput: validators.GetValidatorOutput{ - NodeID: nodeID, - PublicKey: ls.PublicKey(), - }, - sign: ls.Sign, - } - - nodes := generateTestValidators(t, numNodes-1) - nodes = append([]*testSigner{nodeInfo}, nodes...) - - return &testConfig{ - Config: Config{ - Ctx: simplexChainContext, - Validators: newTestValidators(nodes), - SignBLS: ls.Sign, - }, - Nodes: nodes, - } -} +// func newEngineConfig(t *testing.T, numNodes uint64) *testConfig { +// if numNodes == 0 { +// panic("numNodes must be greater than 0") +// } + +// ls, err := localsigner.New() +// require.NoError(t, err) + +// nodeID := ids.GenerateTestNodeID() + +// simplexChainContext := SimplexChainContext{ +// NodeID: nodeID, +// ChainID: ids.GenerateTestID(), +// SubnetID: ids.GenerateTestID(), +// } + +// nodeInfo := &testSigner{ +// GetValidatorOutput: validators.GetValidatorOutput{ +// NodeID: nodeID, +// PublicKey: ls.PublicKey(), +// }, +// sign: ls.Sign, +// } + +// nodes := generateTestValidators(t, numNodes-1) +// nodes = append([]*testSigner{nodeInfo}, nodes...) + +// return &testConfig{ +// Config: Config{ +// Ctx: simplexChainContext, +// Validators: newTestValidators(nodes), +// SignBLS: ls.Sign, +// }, +// Nodes: nodes, +// } +// } func generateTestValidators(t *testing.T, num uint64) []*testSigner { vds := make([]*testSigner, num)