diff --git a/app/appmessage/rpc_get_mempool_entries.go b/app/appmessage/rpc_get_mempool_entries.go index 12036bdb7..3b1f5b7b2 100644 --- a/app/appmessage/rpc_get_mempool_entries.go +++ b/app/appmessage/rpc_get_mempool_entries.go @@ -4,6 +4,8 @@ package appmessage // its respective RPC message type GetMempoolEntriesRequestMessage struct { baseMessage + IncludeOrphanPool bool + FilterTransactionPool bool } // Command returns the protocol command string for the message @@ -12,8 +14,11 @@ func (msg *GetMempoolEntriesRequestMessage) Command() MessageCommand { } // NewGetMempoolEntriesRequestMessage returns a instance of the message -func NewGetMempoolEntriesRequestMessage() *GetMempoolEntriesRequestMessage { - return &GetMempoolEntriesRequestMessage{} +func NewGetMempoolEntriesRequestMessage(includeOrphanPool bool, filterTransactionPool bool) *GetMempoolEntriesRequestMessage { + return &GetMempoolEntriesRequestMessage{ + IncludeOrphanPool: includeOrphanPool, + FilterTransactionPool: filterTransactionPool, + } } // GetMempoolEntriesResponseMessage is an appmessage corresponding to diff --git a/app/appmessage/rpc_get_mempool_entries_by_addresses.go b/app/appmessage/rpc_get_mempool_entries_by_addresses.go index 3094c7ab0..234dcd245 100644 --- a/app/appmessage/rpc_get_mempool_entries_by_addresses.go +++ b/app/appmessage/rpc_get_mempool_entries_by_addresses.go @@ -11,7 +11,9 @@ type MempoolEntryByAddress struct { // its respective RPC message type GetMempoolEntriesByAddressesRequestMessage struct { baseMessage - Addresses []string + Addresses []string + IncludeOrphanPool bool + FilterTransactionPool bool } // Command returns the protocol command string for the message @@ -20,9 +22,11 @@ func (msg *GetMempoolEntriesByAddressesRequestMessage) Command() MessageCommand } // NewGetMempoolEntriesByAddressesRequestMessage returns a instance of the message -func NewGetMempoolEntriesByAddressesRequestMessage(addresses []string) *GetMempoolEntriesByAddressesRequestMessage { +func NewGetMempoolEntriesByAddressesRequestMessage(addresses []string, includeOrphanPool bool, filterTransactionPool bool) *GetMempoolEntriesByAddressesRequestMessage { return &GetMempoolEntriesByAddressesRequestMessage{ - Addresses: addresses, + Addresses: addresses, + IncludeOrphanPool: includeOrphanPool, + FilterTransactionPool: filterTransactionPool, } } diff --git a/app/appmessage/rpc_get_mempool_entry.go b/app/appmessage/rpc_get_mempool_entry.go index 7dcf82aba..5ac37d67b 100644 --- a/app/appmessage/rpc_get_mempool_entry.go +++ b/app/appmessage/rpc_get_mempool_entry.go @@ -4,7 +4,9 @@ package appmessage // its respective RPC message type GetMempoolEntryRequestMessage struct { baseMessage - TxID string + TxID string + IncludeOrphanPool bool + FilterTransactionPool bool } // Command returns the protocol command string for the message @@ -13,8 +15,12 @@ func (msg *GetMempoolEntryRequestMessage) Command() MessageCommand { } // NewGetMempoolEntryRequestMessage returns a instance of the message -func NewGetMempoolEntryRequestMessage(txID string) *GetMempoolEntryRequestMessage { - return &GetMempoolEntryRequestMessage{TxID: txID} +func NewGetMempoolEntryRequestMessage(txID string, includeOrphanPool bool, filterTransactionPool bool) *GetMempoolEntryRequestMessage { + return &GetMempoolEntryRequestMessage{ + TxID: txID, + IncludeOrphanPool: includeOrphanPool, + FilterTransactionPool: filterTransactionPool, + } } // GetMempoolEntryResponseMessage is an appmessage corresponding to @@ -30,6 +36,7 @@ type GetMempoolEntryResponseMessage struct { type MempoolEntry struct { Fee uint64 Transaction *RPCTransaction + IsOrphan bool } // Command returns the protocol command string for the message @@ -38,11 +45,12 @@ func (msg *GetMempoolEntryResponseMessage) Command() MessageCommand { } // NewGetMempoolEntryResponseMessage returns a instance of the message -func NewGetMempoolEntryResponseMessage(fee uint64, transaction *RPCTransaction) *GetMempoolEntryResponseMessage { +func NewGetMempoolEntryResponseMessage(fee uint64, transaction *RPCTransaction, isOrphan bool) *GetMempoolEntryResponseMessage { return &GetMempoolEntryResponseMessage{ Entry: &MempoolEntry{ Fee: fee, Transaction: transaction, + IsOrphan: isOrphan, }, } } diff --git a/app/protocol/flowcontext/blocks.go b/app/protocol/flowcontext/blocks.go index 68bca6cb5..8258f3355 100644 --- a/app/protocol/flowcontext/blocks.go +++ b/app/protocol/flowcontext/blocks.go @@ -107,7 +107,7 @@ func (f *FlowContext) AddBlock(block *externalapi.DomainBlock) error { return protocolerrors.Errorf(false, "cannot add header only block") } - _, err := f.Domain().Consensus().ValidateAndInsertBlock(block, true) + err := f.Domain().Consensus().ValidateAndInsertBlock(block, true) if err != nil { if errors.As(err, &ruleerrors.RuleError{}) { log.Warnf("Validation failed for block %s: %s", consensushashing.BlockHash(block), err) diff --git a/app/protocol/flowcontext/orphans.go b/app/protocol/flowcontext/orphans.go index 2087d6817..16c19bda9 100644 --- a/app/protocol/flowcontext/orphans.go +++ b/app/protocol/flowcontext/orphans.go @@ -141,7 +141,7 @@ func (f *FlowContext) unorphanBlock(orphanHash externalapi.DomainHash) (bool, er } delete(f.orphans, orphanHash) - _, err := f.domain.Consensus().ValidateAndInsertBlock(orphanBlock, true) + err := f.domain.Consensus().ValidateAndInsertBlock(orphanBlock, true) if err != nil { if errors.As(err, &ruleerrors.RuleError{}) { log.Warnf("Validation failed for orphan block %s: %s", orphanHash, err) diff --git a/app/protocol/flows/v5/blockrelay/handle_relay_invs.go b/app/protocol/flows/v5/blockrelay/handle_relay_invs.go index 5e47e7770..72736689f 100644 --- a/app/protocol/flows/v5/blockrelay/handle_relay_invs.go +++ b/app/protocol/flows/v5/blockrelay/handle_relay_invs.go @@ -321,7 +321,7 @@ func (flow *handleRelayInvsFlow) readMsgBlock() (msgBlock *appmessage.MsgBlock, func (flow *handleRelayInvsFlow) processBlock(block *externalapi.DomainBlock) ([]*externalapi.DomainHash, error) { blockHash := consensushashing.BlockHash(block) - _, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, true) + err := flow.Domain().Consensus().ValidateAndInsertBlock(block, true) if err != nil { if !errors.As(err, &ruleerrors.RuleError{}) { return nil, errors.Wrapf(err, "failed to process block %s", blockHash) diff --git a/app/protocol/flows/v5/blockrelay/ibd.go b/app/protocol/flows/v5/blockrelay/ibd.go index 2f989bc9f..e1e68e4d6 100644 --- a/app/protocol/flows/v5/blockrelay/ibd.go +++ b/app/protocol/flows/v5/blockrelay/ibd.go @@ -488,7 +488,7 @@ func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlo log.Debugf("Block header %s is already in the DAG. Skipping...", blockHash) return nil } - _, err = consensus.ValidateAndInsertBlock(block, false) + err = consensus.ValidateAndInsertBlock(block, false) if err != nil { if !errors.As(err, &ruleerrors.RuleError{}) { return errors.Wrapf(err, "failed to process header %s during IBD", blockHash) @@ -654,7 +654,7 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa return err } - _, err = flow.Domain().Consensus().ValidateAndInsertBlock(block, false) + err = flow.Domain().Consensus().ValidateAndInsertBlock(block, false) if err != nil { if errors.Is(err, ruleerrors.ErrDuplicateBlock) { log.Debugf("Skipping IBD Block %s as it has already been added to the DAG", blockHash) @@ -705,7 +705,7 @@ func (flow *handleIBDFlow) resolveVirtual(estimatedVirtualDAAScoreTarget uint64) } log.Infof("Resolving virtual. Estimated progress: %d%%", percents) } - _, isCompletelyResolved, err := flow.Domain().Consensus().ResolveVirtual() + isCompletelyResolved, err := flow.Domain().Consensus().ResolveVirtual() if err != nil { return err } diff --git a/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go b/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go index 707eb6284..b53589116 100644 --- a/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go +++ b/app/protocol/flows/v5/blockrelay/ibd_with_headers_proof.go @@ -280,7 +280,7 @@ func (flow *handleIBDFlow) processBlockWithTrustedData( blockWithTrustedData.GHOSTDAGData = append(blockWithTrustedData.GHOSTDAGData, appmessage.GHOSTDAGHashPairToDomainGHOSTDAGHashPair(data.GHOSTDAGData[index])) } - _, err := consensus.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false) + err := consensus.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false) return err } diff --git a/app/rpc/rpchandlers/get_mempool_entries.go b/app/rpc/rpchandlers/get_mempool_entries.go index 3cfdaf18f..e37d84922 100644 --- a/app/rpc/rpchandlers/get_mempool_entries.go +++ b/app/rpc/rpchandlers/get_mempool_entries.go @@ -7,7 +7,32 @@ import ( ) // HandleGetMempoolEntries handles the respectively named RPC command -func HandleGetMempoolEntries(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) { +func HandleGetMempoolEntries(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) { + getMempoolEntriesRequest := request.(*appmessage.GetMempoolEntriesRequestMessage) + + entries := make([]*appmessage.MempoolEntry, 0) + + if !getMempoolEntriesRequest.FilterTransactionPool { + transactionPoolEntries, err := getTransactionPoolMempoolEntries(context) + if err != nil { + return nil, err + } + + entries = append(entries, transactionPoolEntries...) + } + + if getMempoolEntriesRequest.IncludeOrphanPool { + orphanPoolEntries, err := getOrphanPoolMempoolEntries(context) + if err != nil { + return nil, err + } + entries = append(entries, orphanPoolEntries...) + } + + return appmessage.NewGetMempoolEntriesResponseMessage(entries), nil +} + +func getTransactionPoolMempoolEntries(context *rpccontext.Context) ([]*appmessage.MempoolEntry, error) { transactions := context.Domain.MiningManager().AllTransactions() entries := make([]*appmessage.MempoolEntry, 0, len(transactions)) for _, transaction := range transactions { @@ -19,8 +44,26 @@ func HandleGetMempoolEntries(context *rpccontext.Context, _ *router.Router, _ ap entries = append(entries, &appmessage.MempoolEntry{ Fee: transaction.Fee, Transaction: rpcTransaction, + IsOrphan: false, }) } - - return appmessage.NewGetMempoolEntriesResponseMessage(entries), nil + return entries, nil +} + +func getOrphanPoolMempoolEntries(context *rpccontext.Context) ([]*appmessage.MempoolEntry, error) { + orphanTransactions := context.Domain.MiningManager().AllOrphanTransactions() + entries := make([]*appmessage.MempoolEntry, 0, len(orphanTransactions)) + for _, orphanTransaction := range orphanTransactions { + rpcTransaction := appmessage.DomainTransactionToRPCTransaction(orphanTransaction) + err := context.PopulateTransactionWithVerboseData(rpcTransaction, nil) + if err != nil { + return nil, err + } + entries = append(entries, &appmessage.MempoolEntry{ + Fee: orphanTransaction.Fee, + Transaction: rpcTransaction, + IsOrphan: true, + }) + } + return entries, nil } diff --git a/app/rpc/rpchandlers/get_mempool_entries_by_addresses.go b/app/rpc/rpchandlers/get_mempool_entries_by_addresses.go index 29005ca72..d40d42332 100644 --- a/app/rpc/rpchandlers/get_mempool_entries_by_addresses.go +++ b/app/rpc/rpchandlers/get_mempool_entries_by_addresses.go @@ -1,8 +1,12 @@ package rpchandlers import ( + "errors" + "github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/rpc/rpccontext" + + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/txscript" "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" @@ -12,17 +16,62 @@ import ( // HandleGetMempoolEntriesByAddresses handles the respectively named RPC command func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) { - transactions := context.Domain.MiningManager().AllTransactions() getMempoolEntriesByAddressesRequest := request.(*appmessage.GetMempoolEntriesByAddressesRequestMessage) + mempoolEntriesByAddresses := make([]*appmessage.MempoolEntryByAddress, 0) - for _, addressString := range getMempoolEntriesByAddressesRequest.Addresses { + if !getMempoolEntriesByAddressesRequest.FilterTransactionPool { + transactionPoolTransactions := context.Domain.MiningManager().AllTransactions() + transactionPoolEntriesByAddresses, err := extractMempoolEntriesByAddressesFromTransactions( + context, + getMempoolEntriesByAddressesRequest.Addresses, + transactionPoolTransactions, + false, + ) + if err != nil { + rpcError := &appmessage.RPCError{} + if !errors.As(err, &rpcError) { + return nil, err + } + errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{} + errorMessage.Error = rpcError + return errorMessage, nil + } + mempoolEntriesByAddresses = append(mempoolEntriesByAddresses, transactionPoolEntriesByAddresses...) + } + if getMempoolEntriesByAddressesRequest.IncludeOrphanPool { + + orphanPoolTransactions := context.Domain.MiningManager().AllOrphanTransactions() + orphanPoolEntriesByAddresse, err := extractMempoolEntriesByAddressesFromTransactions( + context, + getMempoolEntriesByAddressesRequest.Addresses, + orphanPoolTransactions, + true, + ) + if err != nil { + rpcError := &appmessage.RPCError{} + if !errors.As(err, &rpcError) { + return nil, err + } + errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{} + errorMessage.Error = rpcError + return errorMessage, nil + } + + mempoolEntriesByAddresses = append(mempoolEntriesByAddresses, orphanPoolEntriesByAddresse...) + } + + return appmessage.NewGetMempoolEntriesByAddressesResponseMessage(mempoolEntriesByAddresses), nil +} + +//TO DO: optimize extractMempoolEntriesByAddressesFromTransactions +func extractMempoolEntriesByAddressesFromTransactions(context *rpccontext.Context, addresses []string, transactions []*externalapi.DomainTransaction, areOrphans bool) ([]*appmessage.MempoolEntryByAddress, error) { + mempoolEntriesByAddresses := make([]*appmessage.MempoolEntryByAddress, 0) + for _, addressString := range addresses { _, err := util.DecodeAddress(addressString, context.Config.ActiveNetParams.Prefix) if err != nil { - errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{} - errorMessage.Error = appmessage.RPCErrorf("Could not decode address '%s': %s", addressString, err) - return errorMessage, nil + return nil, appmessage.RPCErrorf("Could not decode address '%s': %s", addressString, err) } sending := make([]*appmessage.MempoolEntry, 0) @@ -50,6 +99,7 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R &appmessage.MempoolEntry{ Fee: transaction.Fee, Transaction: rpcTransaction, + IsOrphan: areOrphans, }, ) break //one input is enough @@ -71,6 +121,7 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R &appmessage.MempoolEntry{ Fee: transaction.Fee, Transaction: rpcTransaction, + IsOrphan: areOrphans, }, ) break //one output is enough @@ -89,9 +140,8 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R }, ) } - } - } - return appmessage.NewGetMempoolEntriesByAddressesResponseMessage(mempoolEntriesByAddresses), nil + } + return mempoolEntriesByAddresses, nil } diff --git a/app/rpc/rpchandlers/get_mempool_entry.go b/app/rpc/rpchandlers/get_mempool_entry.go index 115e0b7f0..5bc8938ef 100644 --- a/app/rpc/rpchandlers/get_mempool_entry.go +++ b/app/rpc/rpchandlers/get_mempool_entry.go @@ -3,12 +3,18 @@ package rpchandlers import ( "github.com/kaspanet/kaspad/app/appmessage" "github.com/kaspanet/kaspad/app/rpc/rpccontext" + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/utils/transactionid" "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router" ) // HandleGetMempoolEntry handles the respectively named RPC command func HandleGetMempoolEntry(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) { + + transaction := &externalapi.DomainTransaction{} + var found bool + var isOrphan bool + getMempoolEntryRequest := request.(*appmessage.GetMempoolEntryRequestMessage) transactionID, err := transactionid.FromString(getMempoolEntryRequest.TxID) @@ -18,17 +24,25 @@ func HandleGetMempoolEntry(context *rpccontext.Context, _ *router.Router, reques return errorMessage, nil } - transaction, ok := context.Domain.MiningManager().GetTransaction(transactionID) - if !ok { + if !getMempoolEntryRequest.FilterTransactionPool { + transaction, found = context.Domain.MiningManager().GetTransaction(transactionID) + } + + if getMempoolEntryRequest.IncludeOrphanPool && !found { + transaction, found = context.Domain.MiningManager().GetOrphanTransaction(transactionID) + isOrphan = true + } + + if !found { errorMessage := &appmessage.GetMempoolEntryResponseMessage{} errorMessage.Error = appmessage.RPCErrorf("Transaction %s was not found", transactionID) return errorMessage, nil } + rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction) err = context.PopulateTransactionWithVerboseData(rpcTransaction, nil) if err != nil { return nil, err } - - return appmessage.NewGetMempoolEntryResponseMessage(transaction.Fee, rpcTransaction), nil + return appmessage.NewGetMempoolEntryResponseMessage(transaction.Fee, rpcTransaction, isOrphan), nil } diff --git a/changelog.txt b/changelog.txt index 2d051d2df..935439d42 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,23 @@ +Kaspad v0.12.2 - 2022-06-17 +=========================== + +* Clarify wallet message concerning a wallet daemon sync state (#2045) +* Change the way the miner executable reports execution errors (closes issue #1677) (#2048) +* Fix kaspawallet help messages, clarify sweep command help string (#2067) +* Wallet parse/send/create commands improvement (#2024) +* Use chunks for `GetBlocksAcceptanceData` calls in order to avoid blocking consensus for too long (#2075) +* Unite multiple `GetBlockAcceptanceData` consensus calls to one (#2074) +* Update many-small-chains-and-one-big-chain DAG to not fail merge depth limit (#2072) + +RPC API Changes: +* RPC: include orphans into mempool entries (#2046) +* RPC & UtxoIndex: keep track of, query and test circulating supply. (#2070) + +Bug Fixes: +* Fix RPC connections counting (#2026) +* Fix UTXO diff child error (#2084) +* Fix `not in selected chain` crash (#2082) + Kaspad v0.12.1 - 2022-05-31 =========================== diff --git a/cmd/kaspaminer/main.go b/cmd/kaspaminer/main.go index 00300ef10..d94efaec1 100644 --- a/cmd/kaspaminer/main.go +++ b/cmd/kaspaminer/main.go @@ -23,8 +23,7 @@ func main() { cfg, err := parseConfig() if err != nil { - fmt.Fprintf(os.Stderr, "Error parsing command-line arguments: %s\n", err) - os.Exit(1) + printErrorAndExit(errors.Errorf("Error parsing command-line arguments: %s", err)) } defer backendLog.Close() @@ -44,7 +43,7 @@ func main() { miningAddr, err := util.DecodeAddress(cfg.MiningAddr, cfg.ActiveNetParams.Prefix) if err != nil { - panic(errors.Wrap(err, "error decoding mining address")) + printErrorAndExit(errors.Errorf("Error decoding mining address: %s", err)) } doneChan := make(chan struct{}) @@ -61,3 +60,8 @@ func main() { case <-interrupt: } } + +func printErrorAndExit(err error) { + fmt.Fprintf(os.Stderr, "%+v\n", err) + os.Exit(1) +} diff --git a/cmd/kaspawallet/daemon/server/address.go b/cmd/kaspawallet/daemon/server/address.go index 188ba896b..fa49149b2 100644 --- a/cmd/kaspawallet/daemon/server/address.go +++ b/cmd/kaspawallet/daemon/server/address.go @@ -39,10 +39,10 @@ func (s *server) ShowAddresses(_ context.Context, request *pb.ShowAddressesReque defer s.lock.Unlock() if !s.isSynced() { - return nil, errors.New("server is not synced") + return nil, errors.Errorf("wallet daemon is not synced yet, %s", s.formatSyncStateReport()) } - addresses := make([]string, 0) + addresses := make([]string, s.keysFile.LastUsedExternalIndex()) for i := uint32(1); i <= s.keysFile.LastUsedExternalIndex(); i++ { walletAddr := &walletAddress{ index: i, @@ -54,7 +54,7 @@ func (s *server) ShowAddresses(_ context.Context, request *pb.ShowAddressesReque if err != nil { return nil, err } - addresses = append(addresses, address.String()) + addresses[i-1] = address.String() } return &pb.ShowAddressesResponse{Address: addresses}, nil @@ -65,7 +65,7 @@ func (s *server) NewAddress(_ context.Context, request *pb.NewAddressRequest) (* defer s.lock.Unlock() if !s.isSynced() { - return nil, errors.New("server is not synced") + return nil, errors.Errorf("wallet daemon is not synced yet, %s", s.formatSyncStateReport()) } err := s.keysFile.SetLastUsedExternalIndex(s.keysFile.LastUsedExternalIndex() + 1) diff --git a/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go b/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go index b8eff58f1..265780c4a 100644 --- a/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go +++ b/cmd/kaspawallet/daemon/server/create_unsigned_transaction.go @@ -30,7 +30,7 @@ func (s *server) CreateUnsignedTransactions(_ context.Context, request *pb.Creat func (s *server) createUnsignedTransactions(address string, amount uint64, fromAddressesString []string) ([][]byte, error) { if !s.isSynced() { - return nil, errors.New("server is not synced") + return nil, errors.Errorf("wallet daemon is not synced yet, %s", s.formatSyncStateReport()) } err := s.refreshUTXOs() diff --git a/cmd/kaspawallet/daemon/server/external_spendable_utxos.go b/cmd/kaspawallet/daemon/server/external_spendable_utxos.go index 2d0fe597a..15d94cd06 100644 --- a/cmd/kaspawallet/daemon/server/external_spendable_utxos.go +++ b/cmd/kaspawallet/daemon/server/external_spendable_utxos.go @@ -31,7 +31,6 @@ func (s *server) GetExternalSpendableUTXOs(_ context.Context, request *pb.GetExt } func (s *server) selectExternalSpendableUTXOs(externalUTXOs *appmessage.GetUTXOsByAddressesResponseMessage, address string) ([]*pb.UtxosByAddressesEntry, error) { - dagInfo, err := s.rpcClient.GetBlockDAGInfo() if err != nil { return nil, err diff --git a/cmd/kaspawallet/daemon/server/sync.go b/cmd/kaspawallet/daemon/server/sync.go index b5a6d062b..0bfa62229 100644 --- a/cmd/kaspawallet/daemon/server/sync.go +++ b/cmd/kaspawallet/daemon/server/sync.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "sort" "time" @@ -101,10 +102,14 @@ func (s *server) collectFarAddresses() error { return nil } -func (s *server) maxUsedIndex() uint32 { +func (s *server) maxUsedIndexWithLock() uint32 { s.lock.RLock() defer s.lock.RUnlock() + return s.maxUsedIndex() +} + +func (s *server) maxUsedIndex() uint32 { maxUsedIndex := s.keysFile.LastUsedExternalIndex() if s.keysFile.LastUsedInternalIndex() > maxUsedIndex { maxUsedIndex = s.keysFile.LastUsedInternalIndex() @@ -122,10 +127,11 @@ func (s *server) collectRecentAddresses() error { maxUsedIndex := uint32(0) for ; index < maxUsedIndex+numIndexesToQueryForRecentAddresses; index += numIndexesToQueryForRecentAddresses { err := s.collectAddressesWithLock(index, index+numIndexesToQueryForRecentAddresses) + if err != nil { return err } - maxUsedIndex = s.maxUsedIndex() + maxUsedIndex = s.maxUsedIndexWithLock() s.updateSyncingProgressLog(index, maxUsedIndex) } @@ -261,7 +267,7 @@ func (s *server) refreshUTXOs() error { // and not in consensus, and between the calls its spending transaction will be // added to consensus and removed from the mempool, so `getUTXOsByAddressesResponse` // will include an obsolete output. - mempoolEntriesByAddresses, err := s.rpcClient.GetMempoolEntriesByAddresses(s.addressSet.strings()) + mempoolEntriesByAddresses, err := s.rpcClient.GetMempoolEntriesByAddresses(s.addressSet.strings(), true, true) if err != nil { return err } @@ -275,7 +281,18 @@ func (s *server) refreshUTXOs() error { } func (s *server) isSynced() bool { - return s.nextSyncStartIndex > s.keysFile.LastUsedInternalIndex() && s.nextSyncStartIndex > s.keysFile.LastUsedExternalIndex() + return s.nextSyncStartIndex > s.maxUsedIndex() +} + +func (s *server) formatSyncStateReport() string { + maxUsedIndex := s.maxUsedIndex() + + if s.nextSyncStartIndex > maxUsedIndex { + maxUsedIndex = s.nextSyncStartIndex + } + + return fmt.Sprintf("scanned %d out of %d addresses (%.2f%%)", + s.nextSyncStartIndex, maxUsedIndex, float64(s.nextSyncStartIndex)*100.0/float64(maxUsedIndex)) } func (s *server) updateSyncingProgressLog(currProcessedAddresses, currMaxUsedAddresses uint32) { diff --git a/domain/consensus/consensus.go b/domain/consensus/consensus.go index 154d05110..aaddf88e5 100644 --- a/domain/consensus/consensus.go +++ b/domain/consensus/consensus.go @@ -61,17 +61,18 @@ type consensus struct { blocksWithTrustedDataDAAWindowStore model.BlocksWithTrustedDataDAAWindowStore consensusEventsChan chan externalapi.ConsensusEvent + virtualNotUpdated bool } -func (s *consensus) ValidateAndInsertBlockWithTrustedData(block *externalapi.BlockWithTrustedData, validateUTXO bool) (*externalapi.VirtualChangeSet, error) { +func (s *consensus) ValidateAndInsertBlockWithTrustedData(block *externalapi.BlockWithTrustedData, validateUTXO bool) error { s.lock.Lock() defer s.lock.Unlock() - virtualChangeSet, _, err := s.blockProcessor.ValidateAndInsertBlockWithTrustedData(block, validateUTXO) + _, _, err := s.blockProcessor.ValidateAndInsertBlockWithTrustedData(block, validateUTXO) if err != nil { - return nil, err + return err } - return virtualChangeSet, nil + return nil } // Init initializes consensus @@ -193,21 +194,47 @@ func (s *consensus) BuildBlockTemplate(coinbaseData *externalapi.DomainCoinbaseD // ValidateAndInsertBlock validates the given block and, if valid, applies it // to the current state -func (s *consensus) ValidateAndInsertBlock(block *externalapi.DomainBlock, shouldValidateAgainstUTXO bool) (*externalapi.VirtualChangeSet, error) { +func (s *consensus) ValidateAndInsertBlock(block *externalapi.DomainBlock, shouldValidateAgainstUTXO bool) error { s.lock.Lock() defer s.lock.Unlock() - virtualChangeSet, blockStatus, err := s.blockProcessor.ValidateAndInsertBlock(block, shouldValidateAgainstUTXO) + _, err := s.validateAndInsertBlockNoLock(block, shouldValidateAgainstUTXO) + if err != nil { + return err + } + return nil +} + +func (s *consensus) validateAndInsertBlockNoLock(block *externalapi.DomainBlock, updateVirtual bool) (*externalapi.VirtualChangeSet, error) { + // If virtual is in non-updated state, and the caller requests updating virtual -- then we must first + // resolve virtual so that the new block can be fully processed properly + if updateVirtual && s.virtualNotUpdated { + for s.virtualNotUpdated { + // We use 10000 << finality interval. See comment in `ResolveVirtual`. + // We give up responsiveness of consensus in this rare case. + _, err := s.resolveVirtualNoLock(10000) // Note `s.virtualNotUpdated` is updated within the call + if err != nil { + return nil, err + } + } + } + + virtualChangeSet, blockStatus, err := s.blockProcessor.ValidateAndInsertBlock(block, updateVirtual) if err != nil { return nil, err } + // If block has a body, and yet virtual was not updated -- signify that virtual is in non-updated state + if !updateVirtual && blockStatus != externalapi.StatusHeaderOnly { + s.virtualNotUpdated = true + } + err = s.sendBlockAddedEvent(block, blockStatus) if err != nil { return nil, err } - err = s.sendVirtualChangedEvent(virtualChangeSet, shouldValidateAgainstUTXO) + err = s.sendVirtualChangedEvent(virtualChangeSet, updateVirtual) if err != nil { return nil, err } @@ -861,7 +888,7 @@ func (s *consensus) PopulateMass(transaction *externalapi.DomainTransaction) { s.transactionValidator.PopulateMass(transaction) } -func (s *consensus) ResolveVirtual() (*externalapi.VirtualChangeSet, bool, error) { +func (s *consensus) ResolveVirtual() (bool, error) { s.lock.Lock() defer s.lock.Unlock() @@ -869,28 +896,33 @@ func (s *consensus) ResolveVirtual() (*externalapi.VirtualChangeSet, bool, error // release the lock each time resolve 100 blocks. // Note: maxBlocksToResolve should be smaller than finality interval in order to avoid a situation // where UpdatePruningPointByVirtual skips a pruning point. - virtualChangeSet, isCompletelyResolved, err := s.consensusStateManager.ResolveVirtual(100) + return s.resolveVirtualNoLock(100) +} + +func (s *consensus) resolveVirtualNoLock(maxBlocksToResolve uint64) (bool, error) { + virtualChangeSet, isCompletelyResolved, err := s.consensusStateManager.ResolveVirtual(maxBlocksToResolve) if err != nil { - return nil, false, err + return false, err } + s.virtualNotUpdated = !isCompletelyResolved stagingArea := model.NewStagingArea() err = s.pruningManager.UpdatePruningPointByVirtual(stagingArea) if err != nil { - return nil, false, err + return false, err } err = staging.CommitAllChanges(s.databaseContext, stagingArea) if err != nil { - return nil, false, err + return false, err } err = s.sendVirtualChangedEvent(virtualChangeSet, true) if err != nil { - return nil, false, err + return false, err } - return virtualChangeSet, isCompletelyResolved, nil + return isCompletelyResolved, nil } func (s *consensus) BuildPruningPointProof() (*externalapi.PruningPointProof, error) { diff --git a/domain/consensus/consensus_test.go b/domain/consensus/consensus_test.go index 1de2f97fc..01a8a5220 100644 --- a/domain/consensus/consensus_test.go +++ b/domain/consensus/consensus_test.go @@ -27,7 +27,7 @@ func TestConsensus_GetBlockInfo(t *testing.T) { newHeader := invalidBlock.Header.ToMutable() newHeader.SetTimeInMilliseconds(0) invalidBlock.Header = newHeader.ToImmutable() - _, err = consensus.ValidateAndInsertBlock(invalidBlock, true) + err = consensus.ValidateAndInsertBlock(invalidBlock, true) if !errors.Is(err, ruleerrors.ErrTimeTooOld) { t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrTimeTooOld, err) } @@ -55,7 +55,7 @@ func TestConsensus_GetBlockInfo(t *testing.T) { t.Fatalf("consensus.BuildBlock with an empty coinbase shouldn't fail: %v", err) } - _, err = consensus.ValidateAndInsertBlock(validBlock, true) + err = consensus.ValidateAndInsertBlock(validBlock, true) if err != nil { t.Fatalf("consensus.ValidateAndInsertBlock with a block straight from consensus.BuildBlock should not fail: %v", err) } diff --git a/domain/consensus/finality_test.go b/domain/consensus/finality_test.go index c18827a26..5e4e9824b 100644 --- a/domain/consensus/finality_test.go +++ b/domain/consensus/finality_test.go @@ -33,7 +33,7 @@ func TestFinality(t *testing.T) { return nil, err } - _, err = consensus.ValidateAndInsertBlock(block, true) + err = consensus.ValidateAndInsertBlock(block, true) if err != nil { return nil, err } @@ -201,7 +201,7 @@ func TestBoundedMergeDepth(t *testing.T) { return nil, false // fo some reason go doesn't recognize that t.Fatalf never returns } - _, err = consensus.ValidateAndInsertBlock(block, true) + err = consensus.ValidateAndInsertBlock(block, true) if err == nil { return block, false } else if errors.Is(err, ruleerrors.ErrViolatingBoundedMergeDepth) { @@ -213,7 +213,7 @@ func TestBoundedMergeDepth(t *testing.T) { } processBlock := func(consensus testapi.TestConsensus, block *externalapi.DomainBlock, name string) { - _, err := consensus.ValidateAndInsertBlock(block, true) + err := consensus.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("TestBoundedMergeDepth: %s got unexpected error from ProcessBlock: %+v", name, err) @@ -225,7 +225,7 @@ func TestBoundedMergeDepth(t *testing.T) { if err != nil { t.Fatalf("TestBoundedMergeDepth: Failed building block: %+v", err) } - _, err = consensus.ValidateAndInsertBlock(block, true) + err = consensus.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("TestBoundedMergeDepth: Failed Inserting block to consensus: %v", err) } @@ -268,7 +268,7 @@ func TestBoundedMergeDepth(t *testing.T) { t.Fatalf("GetBlockHeader: %+v", err) } - _, err = tcSyncee.ValidateAndInsertBlock(block, true) + err = tcSyncee.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock %d: %+v", i, err) } @@ -556,7 +556,7 @@ func TestFinalityResolveVirtual(t *testing.T) { block.Header = mutableHeader.ToImmutable() } - _, err = tcAttacker.ValidateAndInsertBlock(block, true) + err = tcAttacker.ValidateAndInsertBlock(block, true) if err != nil { panic(err) } @@ -583,14 +583,14 @@ func TestFinalityResolveVirtual(t *testing.T) { t.Logf("Side chain tip (%s) blue score %d", sideChainTipHash, sideChainTipGHOSTDAGData.BlueScore()) for _, block := range sideChain { - _, err := tc.ValidateAndInsertBlock(block, false) + err := tc.ValidateAndInsertBlock(block, false) if err != nil { panic(err) } } for i := 0; ; i++ { - _, isCompletelyResolved, err := tc.ResolveVirtual() + isCompletelyResolved, err := tc.ResolveVirtual() if err != nil { panic(err) } diff --git a/domain/consensus/model/externalapi/consensus.go b/domain/consensus/model/externalapi/consensus.go index def2a2bc5..adaa81bc4 100644 --- a/domain/consensus/model/externalapi/consensus.go +++ b/domain/consensus/model/externalapi/consensus.go @@ -5,8 +5,8 @@ type Consensus interface { Init(skipAddingGenesis bool) error BuildBlock(coinbaseData *DomainCoinbaseData, transactions []*DomainTransaction) (*DomainBlock, error) BuildBlockTemplate(coinbaseData *DomainCoinbaseData, transactions []*DomainTransaction) (*DomainBlockTemplate, error) - ValidateAndInsertBlock(block *DomainBlock, shouldValidateAgainstUTXO bool) (*VirtualChangeSet, error) - ValidateAndInsertBlockWithTrustedData(block *BlockWithTrustedData, validateUTXO bool) (*VirtualChangeSet, error) + ValidateAndInsertBlock(block *DomainBlock, shouldValidateAgainstUTXO bool) error + ValidateAndInsertBlockWithTrustedData(block *BlockWithTrustedData, validateUTXO bool) error ValidateTransactionAndPopulateWithConsensusData(transaction *DomainTransaction) error ImportPruningPoints(pruningPoints []BlockHeader) error BuildPruningPointProof() (*PruningPointProof, error) @@ -48,7 +48,7 @@ type Consensus interface { Anticone(blockHash *DomainHash) ([]*DomainHash, error) EstimateNetworkHashesPerSecond(startHash *DomainHash, windowSize int) (uint64, error) PopulateMass(transaction *DomainTransaction) - ResolveVirtual() (*VirtualChangeSet, bool, error) + ResolveVirtual() (bool, error) BlockDAAWindowHashes(blockHash *DomainHash) ([]*DomainHash, error) TrustedDataDataDAAHeader(trustedBlockHash, daaBlockHash *DomainHash, daaBlockWindowIndex uint64) (*TrustedDataDataDAAHeader, error) TrustedBlockAssociatedGHOSTDAGDataBlockHashes(blockHash *DomainHash) ([]*DomainHash, error) diff --git a/domain/consensus/model/testapi/test_consensus.go b/domain/consensus/model/testapi/test_consensus.go index c11ec7fca..828cabd1a 100644 --- a/domain/consensus/model/testapi/test_consensus.go +++ b/domain/consensus/model/testapi/test_consensus.go @@ -47,6 +47,9 @@ type TestConsensus interface { AddUTXOInvalidBlock(parentHashes []*externalapi.DomainHash) (*externalapi.DomainHash, *externalapi.VirtualChangeSet, error) + UpdatePruningPointByVirtual() error + + ResolveVirtualWithMaxParam(maxBlocksToResolve uint64) (bool, error) MineJSON(r io.Reader, blockType MineJSONBlockType) (tips []*externalapi.DomainHash, err error) ToJSON(w io.Writer) error diff --git a/domain/consensus/processes/blockprocessor/validate_and_insert_block.go b/domain/consensus/processes/blockprocessor/validate_and_insert_block.go index 9547cc698..5d71d60e0 100644 --- a/domain/consensus/processes/blockprocessor/validate_and_insert_block.go +++ b/domain/consensus/processes/blockprocessor/validate_and_insert_block.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/processes/consensusstatemanager" "github.com/kaspanet/kaspad/domain/consensus/ruleerrors" "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" "github.com/kaspanet/kaspad/domain/consensus/utils/multiset" @@ -165,12 +164,7 @@ func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea, if reversalData != nil { err = bp.consensusStateManager.ReverseUTXODiffs(blockHash, reversalData) - // It's still not known what causes this error, but we can ignore it and not reverse the UTXO diffs - // and harm performance in some cases. - // TODO: Investigate why this error happens in the first place, and remove the workaround. - if errors.Is(err, consensusstatemanager.ErrReverseUTXODiffsUTXODiffChildNotFound) { - log.Errorf("Could not reverse UTXO diffs while resolving virtual: %s", err) - } else if err != nil { + if err != nil { return nil, externalapi.StatusInvalid, err } } diff --git a/domain/consensus/processes/blockprocessor/validate_and_insert_block_test.go b/domain/consensus/processes/blockprocessor/validate_and_insert_block_test.go index 54b1d6dca..3f4000a6d 100644 --- a/domain/consensus/processes/blockprocessor/validate_and_insert_block_test.go +++ b/domain/consensus/processes/blockprocessor/validate_and_insert_block_test.go @@ -79,7 +79,7 @@ func TestBlockStatus(t *testing.T) { disqualifiedBlock.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(disqualifiedBlock, true) + err = tc.ValidateAndInsertBlock(disqualifiedBlock, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -106,7 +106,7 @@ func TestBlockStatus(t *testing.T) { disqualifiedBlock.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(invalidBlock, true) + err = tc.ValidateAndInsertBlock(invalidBlock, true) if err == nil { t.Fatalf("block is expected to be invalid") } @@ -139,11 +139,11 @@ func TestValidateAndInsertErrors(t *testing.T) { if err != nil { t.Fatalf("AddBlock: %+v", err) } - _, err = tc.ValidateAndInsertBlock(blockWithStatusInvalid, true) + err = tc.ValidateAndInsertBlock(blockWithStatusInvalid, true) if err == nil { t.Fatalf("Test ValidateAndInsertBlock: Expected an error, because the block is invalid.") } - _, err = tc.ValidateAndInsertBlock(blockWithStatusInvalid, true) + err = tc.ValidateAndInsertBlock(blockWithStatusInvalid, true) if err == nil || !errors.Is(err, ruleerrors.ErrKnownInvalid) { t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrKnownInvalid, err) } @@ -155,12 +155,12 @@ func TestValidateAndInsertErrors(t *testing.T) { if err != nil { t.Fatalf("AddBlock: %+v", err) } - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } // resend the same block. - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err == nil || !errors.Is(err, ruleerrors.ErrDuplicateBlock) { t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrDuplicateBlock, err) } @@ -173,12 +173,12 @@ func TestValidateAndInsertErrors(t *testing.T) { t.Fatalf("AddBlock: %+v", err) } onlyHeader.Transactions = []*externalapi.DomainTransaction{} - _, err = tc.ValidateAndInsertBlock(onlyHeader, true) + err = tc.ValidateAndInsertBlock(onlyHeader, true) if err != nil { t.Fatalf("AddBlock: %+v", err) } // resend the same header. - _, err = tc.ValidateAndInsertBlock(onlyHeader, true) + err = tc.ValidateAndInsertBlock(onlyHeader, true) if err == nil || !errors.Is(err, ruleerrors.ErrDuplicateBlock) { t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrDuplicateBlock, err) } diff --git a/domain/consensus/processes/blockprocessor/validate_and_insert_imported_pruning_point_test.go b/domain/consensus/processes/blockprocessor/validate_and_insert_imported_pruning_point_test.go index 614559b76..f86112baf 100644 --- a/domain/consensus/processes/blockprocessor/validate_and_insert_imported_pruning_point_test.go +++ b/domain/consensus/processes/blockprocessor/validate_and_insert_imported_pruning_point_test.go @@ -26,7 +26,7 @@ func addBlock(tc testapi.TestConsensus, parentHashes []*externalapi.DomainHash, } blockHash := consensushashing.BlockHash(block) - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -44,7 +44,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { consensusConfig.K = 0 consensusConfig.PruningProofM = 1 - syncConsensuses := func(tcSyncerRef, tcSynceeRef *testapi.TestConsensus) { + syncConsensuses := func(tcSyncerRef, tcSynceeRef *testapi.TestConsensus, updatePruningPointJustAfterImportingPruningPoint bool) { tcSyncer, tcSyncee := *tcSyncerRef, *tcSynceeRef pruningPointProof, err := tcSyncer.BuildPruningPointProof() if err != nil { @@ -133,7 +133,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { }) } - _, err = synceeStaging.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false) + err = synceeStaging.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false) if err != nil { t.Fatalf("ValidateAndInsertBlockWithTrustedData: %+v", err) } @@ -169,7 +169,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { t.Fatalf("GetBlockHeader: %+v", err) } - _, err = synceeStaging.ValidateAndInsertBlock(&externalapi.DomainBlock{Header: header}, false) + err = synceeStaging.ValidateAndInsertBlock(&externalapi.DomainBlock{Header: header}, false) if err != nil { t.Fatalf("ValidateAndInsertBlock %d: %+v", i, err) } @@ -236,6 +236,13 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { t.Fatalf("ValidateAndInsertImportedPruningPoint: %+v", err) } + if updatePruningPointJustAfterImportingPruningPoint { + err = synceeStaging.UpdatePruningPointByVirtual() + if err != nil { + t.Fatal(err) + } + } + emptyCoinbase := &externalapi.DomainCoinbaseData{ ScriptPublicKey: &externalapi.ScriptPublicKey{ Script: nil, @@ -266,7 +273,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { t.Fatalf("GetBlock: %+v", err) } - _, err = synceeStaging.ValidateAndInsertBlock(block, true) + err = synceeStaging.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -292,7 +299,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { t.Fatalf("GetBlock: %+v", err) } - _, err = synceeStaging.ValidateAndInsertBlock(tip, true) + err = synceeStaging.ValidateAndInsertBlock(tip, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -339,7 +346,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { t.Fatalf("GetBlock: %+v", err) } - _, err = tcSyncee1.ValidateAndInsertBlock(block, true) + err = tcSyncee1.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -386,7 +393,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { } tcSyncee1Ref := &tcSyncee1 - syncConsensuses(&tcSyncer, tcSyncee1Ref) + syncConsensuses(&tcSyncer, tcSyncee1Ref, false) // Test a situation where a consensus with pruned headers syncs another fresh consensus. tcSyncee2, teardownSyncee2, err := factory.NewTestConsensus(consensusConfig, "TestValidateAndInsertPruningPointSyncee2") @@ -395,7 +402,17 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) { } defer teardownSyncee2(false) - syncConsensuses(tcSyncee1Ref, &tcSyncee2) + syncConsensuses(tcSyncee1Ref, &tcSyncee2, false) + + // Check the regular sync but try to update the pruning point after the pruning point was imported. It tests a situation where the node + // was restarted before the virtual was resolved and then it calls UpdatePruningPointByVirtual on init. + tcSyncee3, teardownSyncee3, err := factory.NewTestConsensus(consensusConfig, "TestValidateAndInsertPruningPointSyncee3") + if err != nil { + t.Fatalf("Error setting up tcSyncee1: %+v", err) + } + defer teardownSyncee3(false) + + syncConsensuses(&tcSyncer, &tcSyncee3, true) }) } @@ -461,7 +478,7 @@ func TestGetPruningPointUTXOs(t *testing.T) { if err != nil { t.Fatalf("Error building block above genesis: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(blockAboveGenesis, true) + err = testConsensus.ValidateAndInsertBlock(blockAboveGenesis, true) if err != nil { t.Fatalf("Error validating and inserting block above genesis: %+v", err) } @@ -473,7 +490,7 @@ func TestGetPruningPointUTXOs(t *testing.T) { if err != nil { t.Fatalf("Error building block with spendable coinbase: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(blockWithSpendableCoinbase, true) + err = testConsensus.ValidateAndInsertBlock(blockWithSpendableCoinbase, true) if err != nil { t.Fatalf("Error validating and inserting block with spendable coinbase: %+v", err) } @@ -512,7 +529,7 @@ func TestGetPruningPointUTXOs(t *testing.T) { if err != nil { t.Fatalf("Error building including block: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(includingBlock, true) + err = testConsensus.ValidateAndInsertBlock(includingBlock, true) if err != nil { t.Fatalf("Error validating and inserting including block: %+v", err) } @@ -523,7 +540,7 @@ func TestGetPruningPointUTXOs(t *testing.T) { if err != nil { t.Fatalf("Error building block: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(block, true) + err = testConsensus.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("Error validating and inserting block: %+v", err) } @@ -619,7 +636,7 @@ func BenchmarkGetPruningPointUTXOs(b *testing.B) { if err != nil { b.Fatalf("Error building block with spendable coinbase: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(blockWithSpendableCoinbase, true) + err = testConsensus.ValidateAndInsertBlock(blockWithSpendableCoinbase, true) if err != nil { b.Fatalf("Error validating and inserting block with spendable coinbase: %+v", err) } @@ -657,7 +674,7 @@ func BenchmarkGetPruningPointUTXOs(b *testing.B) { if err != nil { b.Fatalf("Error building block: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(block, true) + err = testConsensus.ValidateAndInsertBlock(block, true) if err != nil { b.Fatalf("Error validating and inserting block: %+v", err) } @@ -677,7 +694,7 @@ func BenchmarkGetPruningPointUTXOs(b *testing.B) { if err != nil { b.Fatalf("Error building block: %+v", err) } - _, err = testConsensus.ValidateAndInsertBlock(block, true) + err = testConsensus.ValidateAndInsertBlock(block, true) if err != nil { b.Fatalf("Error validating and inserting block: %+v", err) } diff --git a/domain/consensus/processes/blockvalidator/block_body_in_context_test.go b/domain/consensus/processes/blockvalidator/block_body_in_context_test.go index 8b2ffc5e1..ff8c71bb0 100644 --- a/domain/consensus/processes/blockvalidator/block_body_in_context_test.go +++ b/domain/consensus/processes/blockvalidator/block_body_in_context_test.go @@ -62,7 +62,7 @@ func TestCheckBlockIsNotPruned(t *testing.T) { } } - _, err = tc.ValidateAndInsertBlock(beforePruningBlock, true) + err = tc.ValidateAndInsertBlock(beforePruningBlock, true) if !errors.Is(err, ruleerrors.ErrPrunedBlock) { t.Fatalf("Unexpected error: %+v", err) } @@ -117,7 +117,7 @@ func TestCheckParentBlockBodiesExist(t *testing.T) { } // Add only the header of anticonePruningBlock - _, err = tc.ValidateAndInsertBlock(&externalapi.DomainBlock{ + err = tc.ValidateAndInsertBlock(&externalapi.DomainBlock{ Header: anticonePruningBlock.Header, Transactions: nil, }, true) @@ -143,7 +143,7 @@ func TestCheckParentBlockBodiesExist(t *testing.T) { // Add anticonePruningBlock's body and check that it's valid to point to // a header only block in the past of the pruning point. - _, err = tc.ValidateAndInsertBlock(anticonePruningBlock, true) + err = tc.ValidateAndInsertBlock(anticonePruningBlock, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -189,7 +189,7 @@ func TestIsFinalizedTransaction(t *testing.T) { if err != nil { t.Fatalf("Error getting block: %+v", err) } - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("Error Inserting block: %+v", err) } diff --git a/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go b/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go index 78befde5d..56394a0b0 100644 --- a/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go +++ b/domain/consensus/processes/blockvalidator/block_body_in_isolation_test.go @@ -1052,14 +1052,14 @@ func CheckBlockHashMerkleRoot(t *testing.T, tc testapi.TestConsensus, consensusC blockWithInvalidMerkleRoot := block.Clone() blockWithInvalidMerkleRoot.Transactions[0].Version += 1 - _, err = tc.ValidateAndInsertBlock(blockWithInvalidMerkleRoot, true) + err = tc.ValidateAndInsertBlock(blockWithInvalidMerkleRoot, true) if !errors.Is(err, ruleerrors.ErrBadMerkleRoot) { t.Fatalf("Unexpected error: %+v", err) } // Check that a block with invalid merkle root is not marked as invalid // and can be re-added with the right transactions. - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } diff --git a/domain/consensus/processes/blockvalidator/block_header_in_context_test.go b/domain/consensus/processes/blockvalidator/block_header_in_context_test.go index c81130a94..e26c3a3c7 100644 --- a/domain/consensus/processes/blockvalidator/block_header_in_context_test.go +++ b/domain/consensus/processes/blockvalidator/block_header_in_context_test.go @@ -34,7 +34,7 @@ func TestValidateMedianTime(t *testing.T) { newHeader := block.Header.ToMutable() newHeader.SetTimeInMilliseconds(blockTime) block.Header = newHeader.ToImmutable() - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if !errors.Is(err, expectedErr) { t.Fatalf("expected error %s but got %+v", expectedErr, err) } @@ -127,7 +127,7 @@ func TestCheckParentsIncest(t *testing.T) { Transactions: nil, } - _, err = tc.ValidateAndInsertBlock(directParentsRelationBlock, true) + err = tc.ValidateAndInsertBlock(directParentsRelationBlock, true) if !errors.Is(err, ruleerrors.ErrInvalidParentsRelation) { t.Fatalf("unexpected error %+v", err) } @@ -150,7 +150,7 @@ func TestCheckParentsIncest(t *testing.T) { Transactions: nil, } - _, err = tc.ValidateAndInsertBlock(indirectParentsRelationBlock, true) + err = tc.ValidateAndInsertBlock(indirectParentsRelationBlock, true) if !errors.Is(err, ruleerrors.ErrInvalidParentsRelation) { t.Fatalf("unexpected error %+v", err) } diff --git a/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go b/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go index d78538e7b..43d6c48ea 100644 --- a/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go +++ b/domain/consensus/processes/blockvalidator/block_header_in_isolation_test.go @@ -78,7 +78,7 @@ func CheckBlockVersion(t *testing.T, tc testapi.TestConsensus, consensusConfig * block.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if !errors.Is(err, ruleerrors.ErrWrongBlockVersion) { t.Fatalf("Unexpected error: %+v", err) } @@ -118,7 +118,7 @@ func CheckBlockTimestampInIsolation(t *testing.T, tc testapi.TestConsensus, cfg block.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if !errors.Is(err, ruleerrors.ErrTimeTooMuchInTheFuture) { t.Fatalf("Unexpected error: %+v", err) } diff --git a/domain/consensus/processes/blockvalidator/pruning_violation_proof_of_work_and_difficulty_test.go b/domain/consensus/processes/blockvalidator/pruning_violation_proof_of_work_and_difficulty_test.go index e50a6539a..4ca2ff479 100644 --- a/domain/consensus/processes/blockvalidator/pruning_violation_proof_of_work_and_difficulty_test.go +++ b/domain/consensus/processes/blockvalidator/pruning_violation_proof_of_work_and_difficulty_test.go @@ -39,7 +39,7 @@ func TestPOW(t *testing.T) { t.Fatal(err) } invalidBlockWrongPOW = solveBlockWithWrongPOW(invalidBlockWrongPOW) - _, err = tc.ValidateAndInsertBlock(invalidBlockWrongPOW, true) + err = tc.ValidateAndInsertBlock(invalidBlockWrongPOW, true) if !errors.Is(err, ruleerrors.ErrInvalidPoW) { t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrInvalidPoW, err) } @@ -65,7 +65,7 @@ func TestPOW(t *testing.T) { abovePowMaxBlock.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(abovePowMaxBlock, true) + err = tc.ValidateAndInsertBlock(abovePowMaxBlock, true) if !errors.Is(err, ruleerrors.ErrTargetTooHigh) { t.Fatalf("Unexpected error: %+v", err) } @@ -90,7 +90,7 @@ func TestPOW(t *testing.T) { negativeTargetBlock.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(negativeTargetBlock, true) + err = tc.ValidateAndInsertBlock(negativeTargetBlock, true) if !errors.Is(err, ruleerrors.ErrNegativeTarget) { t.Fatalf("Unexpected error: %+v", err) } @@ -104,7 +104,7 @@ func TestPOW(t *testing.T) { // Difficulty is too high on mainnet to actually mine. if consensusConfig.Name != "kaspa-mainnet" { mining.SolveBlock(validBlock, random) - _, err = tc.ValidateAndInsertBlock(validBlock, true) + err = tc.ValidateAndInsertBlock(validBlock, true) if err != nil { t.Fatal(err) } @@ -161,7 +161,7 @@ func TestCheckParentHeadersExist(t *testing.T) { orphanBlock.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(orphanBlock, true) + err = tc.ValidateAndInsertBlock(orphanBlock, true) errMissingParents := &ruleerrors.ErrMissingParents{} if !errors.As(err, errMissingParents) { t.Fatalf("Unexpected error: %+v", err) @@ -193,7 +193,7 @@ func TestCheckParentHeadersExist(t *testing.T) { orphanBlock.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(invalidBlock, true) + err = tc.ValidateAndInsertBlock(invalidBlock, true) if !errors.Is(err, ruleerrors.ErrTransactionVersionIsUnknown) { t.Fatalf("Unexpected error: %+v", err) } @@ -220,7 +220,7 @@ func TestCheckParentHeadersExist(t *testing.T) { invalidBlockChild.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(invalidBlockChild, true) + err = tc.ValidateAndInsertBlock(invalidBlockChild, true) if !errors.Is(err, ruleerrors.ErrInvalidAncestorBlock) { t.Fatalf("Unexpected error: %+v", err) } @@ -284,7 +284,7 @@ func TestCheckPruningPointViolation(t *testing.T) { blockWithPruningViolation.Header.PruningPoint(), ) - _, err = tc.ValidateAndInsertBlock(blockWithPruningViolation, true) + err = tc.ValidateAndInsertBlock(blockWithPruningViolation, true) if !errors.Is(err, ruleerrors.ErrPruningPointViolation) { t.Fatalf("Unexpected error: %+v", err) } diff --git a/domain/consensus/processes/consensusstatemanager/resolve.go b/domain/consensus/processes/consensusstatemanager/resolve.go index 77bc98e92..3a3624881 100644 --- a/domain/consensus/processes/consensusstatemanager/resolve.go +++ b/domain/consensus/processes/consensusstatemanager/resolve.go @@ -5,7 +5,6 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/infrastructure/logger" "github.com/kaspanet/kaspad/util/staging" - "github.com/pkg/errors" "sort" ) @@ -79,12 +78,7 @@ func (csm *consensusStateManager) ResolveVirtual(maxBlocksToResolve uint64) (*ex if reversalData != nil { err = csm.ReverseUTXODiffs(resolveTip, reversalData) - // It's still not known what causes this error, but we can ignore it and not reverse the UTXO diffs - // and harm performance in some cases. - // TODO: Investigate why this error happens in the first place, and remove the workaround. - if errors.Is(err, ErrReverseUTXODiffsUTXODiffChildNotFound) { - log.Errorf("Could not reverse UTXO diffs while resolving virtual: %s", err) - } else if err != nil { + if err != nil { return nil, false, err } } diff --git a/domain/consensus/processes/consensusstatemanager/resolve_virtual_test.go b/domain/consensus/processes/consensusstatemanager/resolve_virtual_test.go new file mode 100644 index 000000000..4af0c337c --- /dev/null +++ b/domain/consensus/processes/consensusstatemanager/resolve_virtual_test.go @@ -0,0 +1,214 @@ +package consensusstatemanager_test + +import ( + "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" + "testing" + + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + + "github.com/kaspanet/kaspad/domain/consensus" + "github.com/kaspanet/kaspad/domain/consensus/utils/testutils" +) + +func TestAddBlockBetweenResolveVirtualCalls(t *testing.T) { + + testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { + factory := consensus.NewFactory() + + tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestAddBlockBetweenResolveVirtualCalls") + if err != nil { + t.Fatalf("Error setting up consensus: %+v", err) + } + defer teardown(false) + + // Create a chain of blocks + const initialChainLength = 10 + previousBlockHash := consensusConfig.GenesisHash + for i := 0; i < initialChainLength; i++ { + previousBlockHash, _, err = tc.AddBlock([]*externalapi.DomainHash{previousBlockHash}, nil, nil) + if err != nil { + t.Fatalf("Error mining block no. %d in initial chain: %+v", i, err) + } + } + + // Mine a chain with more blocks, to re-organize the DAG + const reorgChainLength = initialChainLength + 1 + previousBlockHash = consensusConfig.GenesisHash + for i := 0; i < reorgChainLength; i++ { + previousBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{previousBlockHash}, nil, nil) + if err != nil { + t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err) + } + previousBlockHash = consensushashing.BlockHash(previousBlock) + + // Do not UTXO validate in order to resolve virtual later + err = tc.ValidateAndInsertBlock(previousBlock, false) + if err != nil { + t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err) + } + } + + // Resolve one step + _, err = tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + + emptyCoinbase := &externalapi.DomainCoinbaseData{ + ScriptPublicKey: &externalapi.ScriptPublicKey{ + Script: nil, + Version: 0, + }, + } + + // Get template based on current resolve state + blockTemplate, err := tc.BuildBlockTemplate(emptyCoinbase, nil) + if err != nil { + t.Fatalf("Error building block template during virtual resolution of reorg: %+v", err) + } + + // Resolve one more step + isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + + // Add the mined block (now virtual was modified) + err = tc.ValidateAndInsertBlock(blockTemplate.Block, true) + if err != nil { + t.Fatalf("Error mining block during virtual resolution of reorg: %+v", err) + } + + // Complete resolving virtual + for !isCompletelyResolved { + isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + } + }) +} + +func TestAddGenesisChildAfterOneResolveVirtualCall(t *testing.T) { + + testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { + factory := consensus.NewFactory() + + tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestAddGenesisChildAfterOneResolveVirtualCall") + if err != nil { + t.Fatalf("Error setting up consensus: %+v", err) + } + defer teardown(false) + + // Create a chain of blocks + const initialChainLength = 6 + previousBlockHash := consensusConfig.GenesisHash + for i := 0; i < initialChainLength; i++ { + previousBlockHash, _, err = tc.AddBlock([]*externalapi.DomainHash{previousBlockHash}, nil, nil) + if err != nil { + t.Fatalf("Error mining block no. %d in initial chain: %+v", i, err) + } + } + + // Mine a chain with more blocks, to re-organize the DAG + const reorgChainLength = initialChainLength + 1 + previousBlockHash = consensusConfig.GenesisHash + for i := 0; i < reorgChainLength; i++ { + previousBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{previousBlockHash}, nil, nil) + if err != nil { + t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err) + } + previousBlockHash = consensushashing.BlockHash(previousBlock) + + // Do not UTXO validate in order to resolve virtual later + err = tc.ValidateAndInsertBlock(previousBlock, false) + if err != nil { + t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err) + } + } + + // Resolve one step + isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + + _, _, err = tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil) + if err != nil { + t.Fatalf("Error adding block during virtual resolution of reorg: %+v", err) + } + + // Complete resolving virtual + for !isCompletelyResolved { + isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + } + }) +} + +func TestAddGenesisChildAfterTwoResolveVirtualCalls(t *testing.T) { + + testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) { + factory := consensus.NewFactory() + + tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestAddGenesisChildAfterTwoResolveVirtualCalls") + if err != nil { + t.Fatalf("Error setting up consensus: %+v", err) + } + defer teardown(false) + + // Create a chain of blocks + const initialChainLength = 6 + previousBlockHash := consensusConfig.GenesisHash + for i := 0; i < initialChainLength; i++ { + previousBlockHash, _, err = tc.AddBlock([]*externalapi.DomainHash{previousBlockHash}, nil, nil) + if err != nil { + t.Fatalf("Error mining block no. %d in initial chain: %+v", i, err) + } + } + + // Mine a chain with more blocks, to re-organize the DAG + const reorgChainLength = initialChainLength + 1 + previousBlockHash = consensusConfig.GenesisHash + for i := 0; i < reorgChainLength; i++ { + previousBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{previousBlockHash}, nil, nil) + if err != nil { + t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err) + } + previousBlockHash = consensushashing.BlockHash(previousBlock) + + // Do not UTXO validate in order to resolve virtual later + err = tc.ValidateAndInsertBlock(previousBlock, false) + if err != nil { + t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err) + } + } + + // Resolve one step + _, err = tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + + // Resolve one more step + isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + + _, _, err = tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil) + if err != nil { + t.Fatalf("Error adding block during virtual resolution of reorg: %+v", err) + } + + // Complete resolving virtual + for !isCompletelyResolved { + isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2) + if err != nil { + t.Fatalf("Error resolving virtual in re-org chain: %+v", err) + } + } + }) +} diff --git a/domain/consensus/processes/consensusstatemanager/reverse_utxo_diffs.go b/domain/consensus/processes/consensusstatemanager/reverse_utxo_diffs.go index 72635a23f..b8f388d20 100644 --- a/domain/consensus/processes/consensusstatemanager/reverse_utxo_diffs.go +++ b/domain/consensus/processes/consensusstatemanager/reverse_utxo_diffs.go @@ -3,18 +3,10 @@ package consensusstatemanager import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/infrastructure/db/database" "github.com/kaspanet/kaspad/infrastructure/logger" "github.com/kaspanet/kaspad/util/staging" - "github.com/pkg/errors" ) -// ErrReverseUTXODiffsUTXODiffChildNotFound indicates a UTXO diff child was not found while calling ReverseUTXODiffs. -// It's still not known what causes this error, but we can ignore it and not reverse the UTXO diffs -// and harm performance in some cases. -// TODO: Investigate why this error happens in the first place, and remove the workaround. -var ErrReverseUTXODiffsUTXODiffChildNotFound = errors.New("ErrReverseUTXODiffsUTXODiffChildNotFound") - func (csm *consensusStateManager) ReverseUTXODiffs(tipHash *externalapi.DomainHash, reversalData *model.UTXODiffReversalData) error { @@ -57,9 +49,6 @@ func (csm *consensusStateManager) ReverseUTXODiffs(tipHash *externalapi.DomainHa currentBlockUTXODiffChild, err := csm.utxoDiffStore.UTXODiffChild(csm.databaseContext, readStagingArea, currentBlock) if err != nil { - if database.IsNotFoundError(err) { - return errors.Wrapf(ErrReverseUTXODiffsUTXODiffChildNotFound, "UTXO diff child was not found for block %s", currentBlock) - } return err } currentBlockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, readStagingArea, currentBlock, false) diff --git a/domain/consensus/processes/consensusstatemanager/virtual_parents_test.go b/domain/consensus/processes/consensusstatemanager/virtual_parents_test.go index e48fd4b26..940e03ef2 100644 --- a/domain/consensus/processes/consensusstatemanager/virtual_parents_test.go +++ b/domain/consensus/processes/consensusstatemanager/virtual_parents_test.go @@ -84,7 +84,7 @@ func TestConsensusStateManager_pickVirtualParents(t *testing.T) { if err != nil { t.Fatalf("Failed building a block: %v", err) } - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("Failed Inserting block to tc: %v", err) } diff --git a/domain/consensus/processes/difficultymanager/difficultymanager_test.go b/domain/consensus/processes/difficultymanager/difficultymanager_test.go index 621d9e287..ad729c28a 100644 --- a/domain/consensus/processes/difficultymanager/difficultymanager_test.go +++ b/domain/consensus/processes/difficultymanager/difficultymanager_test.go @@ -65,7 +65,7 @@ func TestDifficulty(t *testing.T) { newHeader := block.Header.ToMutable() newHeader.SetTimeInMilliseconds(blockTime) block.Header = newHeader.ToImmutable() - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } diff --git a/domain/consensus/processes/pastmediantimemanager/pastmediantimemanager_test.go b/domain/consensus/processes/pastmediantimemanager/pastmediantimemanager_test.go index a02cf8105..549c9d3e0 100644 --- a/domain/consensus/processes/pastmediantimemanager/pastmediantimemanager_test.go +++ b/domain/consensus/processes/pastmediantimemanager/pastmediantimemanager_test.go @@ -34,7 +34,7 @@ func TestPastMedianTime(t *testing.T) { newHeader := block.Header.ToMutable() newHeader.SetTimeInMilliseconds(blockTime) block.Header = newHeader.ToImmutable() - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } diff --git a/domain/consensus/processes/pruningmanager/pruningmanager.go b/domain/consensus/processes/pruningmanager/pruningmanager.go index 2fc268048..dd5798afd 100644 --- a/domain/consensus/processes/pruningmanager/pruningmanager.go +++ b/domain/consensus/processes/pruningmanager/pruningmanager.go @@ -191,6 +191,46 @@ func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.Staging return nil } +type blockIteratorFromOneBlock struct { + done, isClosed bool + hash *externalapi.DomainHash +} + +func (b *blockIteratorFromOneBlock) First() bool { + if b.isClosed { + panic("Tried using a closed blockIteratorFromOneBlock") + } + + b.done = false + return true +} + +func (b *blockIteratorFromOneBlock) Next() bool { + if b.isClosed { + panic("Tried using a closed blockIteratorFromOneBlock") + } + + b.done = true + return false +} + +func (b *blockIteratorFromOneBlock) Get() (*externalapi.DomainHash, error) { + if b.isClosed { + panic("Tried using a closed blockIteratorFromOneBlock") + } + + return b.hash, nil +} + +func (b *blockIteratorFromOneBlock) Close() error { + if b.isClosed { + panic("Tried using a closed blockIteratorFromOneBlock") + } + + b.isClosed = true + return nil +} + func (pm *pruningManager) nextPruningPointAndCandidateByBlockHash(stagingArea *model.StagingArea, blockHash, suggestedLowHash *externalapi.DomainHash) (*externalapi.DomainHash, *externalapi.DomainHash, error) { @@ -222,12 +262,12 @@ func (pm *pruningManager) nextPruningPointAndCandidateByBlockHash(stagingArea *m } } - ghostdagData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, blockHash, false) + currentPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea) if err != nil { return nil, nil, err } - currentPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea) + ghostdagData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, blockHash, false) if err != nil { return nil, nil, err } @@ -240,9 +280,14 @@ func (pm *pruningManager) nextPruningPointAndCandidateByBlockHash(stagingArea *m // We iterate until the selected parent of the given block, in order to allow a situation where the given block hash // belongs to the virtual. This shouldn't change anything since the max blue score difference between a block and its // selected parent is K, and K << pm.pruningDepth. - iterator, err := pm.dagTraversalManager.SelectedChildIterator(stagingArea, ghostdagData.SelectedParent(), lowHash, true) - if err != nil { - return nil, nil, err + var iterator model.BlockIterator + if blockHash.Equal(lowHash) { + iterator = &blockIteratorFromOneBlock{hash: lowHash} + } else { + iterator, err = pm.dagTraversalManager.SelectedChildIterator(stagingArea, ghostdagData.SelectedParent(), lowHash, true) + if err != nil { + return nil, nil, err + } } defer iterator.Close() diff --git a/domain/consensus/test_consensus.go b/domain/consensus/test_consensus.go index 3b14cc8a4..0eda211c9 100644 --- a/domain/consensus/test_consensus.go +++ b/domain/consensus/test_consensus.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/utils/hashset" + "github.com/kaspanet/kaspad/util/staging" "io" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" @@ -60,7 +61,7 @@ func (tc *testConsensus) AddBlock(parentHashes []*externalapi.DomainHash, coinba return nil, nil, err } - virtualChangeSet, _, err := tc.blockProcessor.ValidateAndInsertBlock(block, true) + virtualChangeSet, err := tc.validateAndInsertBlockNoLock(block, true) if err != nil { return nil, nil, err } @@ -80,7 +81,7 @@ func (tc *testConsensus) AddUTXOInvalidHeader(parentHashes []*externalapi.Domain return nil, nil, err } - virtualChangeSet, _, err := tc.blockProcessor.ValidateAndInsertBlock(&externalapi.DomainBlock{ + virtualChangeSet, err := tc.validateAndInsertBlockNoLock(&externalapi.DomainBlock{ Header: header, Transactions: nil, }, true) @@ -103,7 +104,7 @@ func (tc *testConsensus) AddUTXOInvalidBlock(parentHashes []*externalapi.DomainH return nil, nil, err } - virtualChangeSet, _, err := tc.blockProcessor.ValidateAndInsertBlock(block, true) + virtualChangeSet, err := tc.validateAndInsertBlockNoLock(block, true) if err != nil { return nil, nil, err } @@ -111,6 +112,13 @@ func (tc *testConsensus) AddUTXOInvalidBlock(parentHashes []*externalapi.DomainH return consensushashing.BlockHash(block), virtualChangeSet, nil } +func (tc *testConsensus) ResolveVirtualWithMaxParam(maxBlocksToResolve uint64) (bool, error) { + tc.lock.Lock() + defer tc.lock.Unlock() + + return tc.resolveVirtualNoLock(maxBlocksToResolve) +} + // jsonBlock is a json representation of a block in mine format type jsonBlock struct { ID string `json:"id"` @@ -258,3 +266,16 @@ func (tc *testConsensus) BuildHeaderWithParents(parentHashes []*externalapi.Doma return tc.testBlockBuilder.BuildUTXOInvalidHeader(parentHashes) } + +func (tc *testConsensus) UpdatePruningPointByVirtual() error { + tc.lock.Lock() + defer tc.lock.Unlock() + + stagingArea := model.NewStagingArea() + err := tc.pruningManager.UpdatePruningPointByVirtual(stagingArea) + if err != nil { + return err + } + + return staging.CommitAllChanges(tc.databaseContext, stagingArea) +} diff --git a/domain/consensus/timelock_CLTV_test.go b/domain/consensus/timelock_CLTV_test.go index b1cef6fb8..215442390 100644 --- a/domain/consensus/timelock_CLTV_test.go +++ b/domain/consensus/timelock_CLTV_test.go @@ -318,7 +318,7 @@ func TestCheckLockTimeVerifyConditionedByAbsoluteTime(t *testing.T) { blockHeader := tipBlock.Header.ToMutable() blockHeader.SetTimeInMilliseconds(timeStampBlockE + i*1000) tipBlock.Header = blockHeader.ToImmutable() - _, err = testConsensus.ValidateAndInsertBlock(tipBlock, true) + err = testConsensus.ValidateAndInsertBlock(tipBlock, true) if err != nil { t.Fatalf("Error validating and inserting tip block: %v", err) } @@ -439,7 +439,7 @@ func TestCheckLockTimeVerifyConditionedByAbsoluteTimeWithWrongLockTime(t *testin blockHeader := tipBlock.Header.ToMutable() blockHeader.SetTimeInMilliseconds(timeStampBlockE + i*1000) tipBlock.Header = blockHeader.ToImmutable() - _, err = testConsensus.ValidateAndInsertBlock(tipBlock, true) + err = testConsensus.ValidateAndInsertBlock(tipBlock, true) if err != nil { t.Fatalf("Error validating and inserting tip block: %v", err) } diff --git a/domain/domain_test.go b/domain/domain_test.go index 0ec107be5..ad7489349 100644 --- a/domain/domain_test.go +++ b/domain/domain_test.go @@ -57,7 +57,7 @@ func TestCreateStagingConsensus(t *testing.T) { }, }, } - _, err = domainInstance.StagingConsensus().ValidateAndInsertBlockWithTrustedData(genesisWithTrustedData, true) + err = domainInstance.StagingConsensus().ValidateAndInsertBlockWithTrustedData(genesisWithTrustedData, true) if err != nil { t.Fatalf("ValidateAndInsertBlockWithTrustedData: %+v", err) } @@ -74,7 +74,7 @@ func TestCreateStagingConsensus(t *testing.T) { t.Fatalf("BuildBlock: %+v", err) } - _, err = domainInstance.StagingConsensus().ValidateAndInsertBlock(block, true) + err = domainInstance.StagingConsensus().ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -120,7 +120,7 @@ func TestCreateStagingConsensus(t *testing.T) { } addGenesisToStagingConsensus() - _, err = domainInstance.StagingConsensus().ValidateAndInsertBlock(block, true) + err = domainInstance.StagingConsensus().ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } diff --git a/domain/migrate.go b/domain/migrate.go index eee3bb4d7..c1804862e 100644 --- a/domain/migrate.go +++ b/domain/migrate.go @@ -106,7 +106,7 @@ func syncConsensuses(syncer, syncee externalapi.Consensus) error { }) } - _, err = syncee.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false) + err = syncee.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false) if err != nil { return err } @@ -161,7 +161,7 @@ func syncConsensuses(syncer, syncee externalapi.Consensus) error { return err } - _, err = syncee.ValidateAndInsertBlock(block, false) + err = syncee.ValidateAndInsertBlock(block, false) if err != nil { return err } @@ -232,7 +232,7 @@ func syncConsensuses(syncer, syncee externalapi.Consensus) error { log.Infof("Resolving virtual. Estimated progress: %d%%", percents) } } - _, isCompletelyResolved, err := syncee.ResolveVirtual() + isCompletelyResolved, err := syncee.ResolveVirtual() if err != nil { return err } diff --git a/domain/miningmanager/mempool/mempool.go b/domain/miningmanager/mempool/mempool.go index 0dde96101..c6eb41fe4 100644 --- a/domain/miningmanager/mempool/mempool.go +++ b/domain/miningmanager/mempool/mempool.go @@ -56,6 +56,20 @@ func (mp *mempool) AllTransactions() []*externalapi.DomainTransaction { return mp.transactionsPool.getAllTransactions() } +func (mp *mempool) GetOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) { + mp.mtx.RLock() + defer mp.mtx.RUnlock() + + return mp.orphansPool.getOrphanTransaction(transactionID) +} + +func (mp *mempool) AllOrphanTransactions() []*externalapi.DomainTransaction { + mp.mtx.RLock() + defer mp.mtx.RUnlock() + + return mp.orphansPool.getAllOrphanTransactions() +} + func (mp *mempool) TransactionCount() int { mp.mtx.RLock() defer mp.mtx.RUnlock() diff --git a/domain/miningmanager/mempool/orphan_pool.go b/domain/miningmanager/mempool/orphan_pool.go index ce7d77774..d053ecd28 100644 --- a/domain/miningmanager/mempool/orphan_pool.go +++ b/domain/miningmanager/mempool/orphan_pool.go @@ -328,3 +328,18 @@ func (op *orphansPool) randomNonHighPriorityOrphan() *model.OrphanTransaction { return nil } + +func (op *orphansPool) getOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) { + if orphanTransaction, ok := op.allOrphans[*transactionID]; ok { + return orphanTransaction.Transaction(), true + } + return nil, false +} + +func (op *orphansPool) getAllOrphanTransactions() []*externalapi.DomainTransaction { + allOrphanTransactions := make([]*externalapi.DomainTransaction, 0, len(op.allOrphans)) + for _, mempoolTransaction := range op.allOrphans { + allOrphanTransactions = append(allOrphanTransactions, mempoolTransaction.Transaction()) + } + return allOrphanTransactions +} diff --git a/domain/miningmanager/miningmanager.go b/domain/miningmanager/miningmanager.go index 1555ff2e5..08e576f13 100644 --- a/domain/miningmanager/miningmanager.go +++ b/domain/miningmanager/miningmanager.go @@ -1,11 +1,12 @@ package miningmanager import ( + "sync" + "time" + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensusreference" miningmanagermodel "github.com/kaspanet/kaspad/domain/miningmanager/model" - "sync" - "time" ) // MiningManager creates block templates for mining as well as maintaining @@ -16,6 +17,8 @@ type MiningManager interface { GetBlockTemplateBuilder() miningmanagermodel.BlockTemplateBuilder GetTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) AllTransactions() []*externalapi.DomainTransaction + GetOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) + AllOrphanTransactions() []*externalapi.DomainTransaction TransactionCount() int HandleNewBlockTransactions(txs []*externalapi.DomainTransaction) ([]*externalapi.DomainTransaction, error) ValidateAndInsertTransaction(transaction *externalapi.DomainTransaction, isHighPriority bool, allowOrphan bool) ( @@ -115,6 +118,17 @@ func (mm *miningManager) AllTransactions() []*externalapi.DomainTransaction { return mm.mempool.AllTransactions() } +func (mm *miningManager) GetOrphanTransaction( + transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) { + + return mm.mempool.GetOrphanTransaction(transactionID) +} + +func (mm *miningManager) AllOrphanTransactions() []*externalapi.DomainTransaction { + + return mm.mempool.AllOrphanTransactions() +} + func (mm *miningManager) TransactionCount() int { return mm.mempool.TransactionCount() } diff --git a/domain/miningmanager/model/interface_mempool.go b/domain/miningmanager/model/interface_mempool.go index d2a383f7e..caf6b5968 100644 --- a/domain/miningmanager/model/interface_mempool.go +++ b/domain/miningmanager/model/interface_mempool.go @@ -14,6 +14,8 @@ type Mempool interface { RemoveTransactions(txs []*externalapi.DomainTransaction, removeRedeemers bool) error GetTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) AllTransactions() []*externalapi.DomainTransaction + GetOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) + AllOrphanTransactions() []*externalapi.DomainTransaction TransactionCount() int RevalidateHighPriorityTransactions() (validTransactions []*externalapi.DomainTransaction, err error) IsTransactionOutputDust(output *externalapi.DomainTransactionOutput) bool diff --git a/infrastructure/config/config.go b/infrastructure/config/config.go index c8c8fd024..bba91219b 100644 --- a/infrastructure/config/config.go +++ b/infrastructure/config/config.go @@ -38,8 +38,9 @@ const ( defaultBanDuration = time.Hour * 24 defaultBanThreshold = 100 //DefaultConnectTimeout is the default connection timeout when dialing - DefaultConnectTimeout = time.Second * 30 - defaultMaxRPCClients = 10 + DefaultConnectTimeout = time.Second * 30 + //DefaultMaxRPCClients is the default max number of RPC clients + DefaultMaxRPCClients = 128 defaultMaxRPCWebsockets = 25 defaultMaxRPCConcurrentReqs = 20 defaultBlockMaxMass = 10_000_000 @@ -178,7 +179,7 @@ func defaultFlags() *Flags { MaxInboundPeers: defaultMaxInboundPeers, BanDuration: defaultBanDuration, BanThreshold: defaultBanThreshold, - RPCMaxClients: defaultMaxRPCClients, + RPCMaxClients: DefaultMaxRPCClients, RPCMaxWebsockets: defaultMaxRPCWebsockets, RPCMaxConcurrentReqs: defaultMaxRPCConcurrentReqs, AppDir: defaultDataDir, diff --git a/infrastructure/network/netadapter/netadapter.go b/infrastructure/network/netadapter/netadapter.go index 33fe00df8..0f50c8deb 100644 --- a/infrastructure/network/netadapter/netadapter.go +++ b/infrastructure/network/netadapter/netadapter.go @@ -46,7 +46,7 @@ func NewNetAdapter(cfg *config.Config) (*NetAdapter, error) { if err != nil { return nil, err } - rpcServer, err := grpcserver.NewRPCServer(cfg.RPCListeners) + rpcServer, err := grpcserver.NewRPCServer(cfg.RPCListeners, cfg.RPCMaxClients) if err != nil { return nil, err } diff --git a/infrastructure/network/netadapter/server/grpcserver/grpc_server.go b/infrastructure/network/netadapter/server/grpcserver/grpc_server.go index c18a47357..8e84dfeda 100644 --- a/infrastructure/network/netadapter/server/grpcserver/grpc_server.go +++ b/infrastructure/network/netadapter/server/grpcserver/grpc_server.go @@ -94,10 +94,11 @@ func (s *gRPCServer) SetOnConnectedHandler(onConnectedHandler server.OnConnected } func (s *gRPCServer) handleInboundConnection(ctx context.Context, stream grpcStream) error { - err := s.incrementInboundConnectionCountAndLimitIfRequired() + connectionCount, err := s.incrementInboundConnectionCountAndLimitIfRequired() if err != nil { return err } + defer s.decrementInboundConnectionCount() peerInfo, ok := peer.FromContext(ctx) if !ok { @@ -115,23 +116,23 @@ func (s *gRPCServer) handleInboundConnection(ctx context.Context, stream grpcStr return err } - log.Infof("%s Incoming connection from %s", s.name, peerInfo.Addr) + log.Infof("%s Incoming connection from %s #%d", s.name, peerInfo.Addr, connectionCount) <-connection.stopChan - s.decrementInboundConnectionCount() return nil } -func (s *gRPCServer) incrementInboundConnectionCountAndLimitIfRequired() error { +func (s *gRPCServer) incrementInboundConnectionCountAndLimitIfRequired() (int, error) { s.inboundConnectionCountLock.Lock() defer s.inboundConnectionCountLock.Unlock() if s.maxInboundConnections > 0 && s.inboundConnectionCount == s.maxInboundConnections { - return errors.Errorf("limit of %d inbound connections has been exceeded", s.maxInboundConnections) + log.Warnf("Limit of %d %s inbound connections has been exceeded", s.maxInboundConnections, s.name) + return s.inboundConnectionCount, errors.Errorf("limit of %d %s inbound connections has been exceeded", s.maxInboundConnections, s.name) } s.inboundConnectionCount++ - return nil + return s.inboundConnectionCount, nil } func (s *gRPCServer) decrementInboundConnectionCount() { diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.md b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.md index 7bce86dee..12a22923c 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.md +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.md @@ -609,6 +609,8 @@ in the mempool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | txId | [string](#string) | | The transaction's TransactionID. | +| includeOrphanPool | [bool](#bool) | | | +| filterTransactionPool | [bool](#bool) | | | @@ -638,6 +640,12 @@ GetMempoolEntriesRequestMessage requests information about all the transactions currently in the mempool. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| includeOrphanPool | [bool](#bool) | | | +| filterTransactionPool | [bool](#bool) | | | + + @@ -668,6 +676,7 @@ currently in the mempool. | ----- | ---- | ----- | ----------- | | fee | [uint64](#uint64) | | | | transaction | [RpcTransaction](#protowire.RpcTransaction) | | | +| isOrphan | [bool](#bool) | | | @@ -1798,6 +1807,8 @@ See NotifyNewBlockTemplateRequestMessage | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | addresses | [string](#string) | repeated | | +| includeOrphanPool | [bool](#bool) | | | +| filterTransactionPool | [bool](#bool) | | | diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go index e8f37359d..a72e70fe4 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.pb.go @@ -1820,7 +1820,9 @@ type GetMempoolEntryRequestMessage struct { unknownFields protoimpl.UnknownFields // The transaction's TransactionID. - TxId string `protobuf:"bytes,1,opt,name=txId,proto3" json:"txId,omitempty"` + TxId string `protobuf:"bytes,1,opt,name=txId,proto3" json:"txId,omitempty"` + IncludeOrphanPool bool `protobuf:"varint,2,opt,name=includeOrphanPool,proto3" json:"includeOrphanPool,omitempty"` + FilterTransactionPool bool `protobuf:"varint,3,opt,name=filterTransactionPool,proto3" json:"filterTransactionPool,omitempty"` } func (x *GetMempoolEntryRequestMessage) Reset() { @@ -1862,6 +1864,20 @@ func (x *GetMempoolEntryRequestMessage) GetTxId() string { return "" } +func (x *GetMempoolEntryRequestMessage) GetIncludeOrphanPool() bool { + if x != nil { + return x.IncludeOrphanPool + } + return false +} + +func (x *GetMempoolEntryRequestMessage) GetFilterTransactionPool() bool { + if x != nil { + return x.FilterTransactionPool + } + return false +} + type GetMempoolEntryResponseMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1923,6 +1939,9 @@ type GetMempoolEntriesRequestMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + IncludeOrphanPool bool `protobuf:"varint,1,opt,name=includeOrphanPool,proto3" json:"includeOrphanPool,omitempty"` + FilterTransactionPool bool `protobuf:"varint,2,opt,name=filterTransactionPool,proto3" json:"filterTransactionPool,omitempty"` } func (x *GetMempoolEntriesRequestMessage) Reset() { @@ -1957,6 +1976,20 @@ func (*GetMempoolEntriesRequestMessage) Descriptor() ([]byte, []int) { return file_rpc_proto_rawDescGZIP(), []int{30} } +func (x *GetMempoolEntriesRequestMessage) GetIncludeOrphanPool() bool { + if x != nil { + return x.IncludeOrphanPool + } + return false +} + +func (x *GetMempoolEntriesRequestMessage) GetFilterTransactionPool() bool { + if x != nil { + return x.FilterTransactionPool + } + return false +} + type GetMempoolEntriesResponseMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2019,6 +2052,7 @@ type MempoolEntry struct { Fee uint64 `protobuf:"varint,1,opt,name=fee,proto3" json:"fee,omitempty"` Transaction *RpcTransaction `protobuf:"bytes,3,opt,name=transaction,proto3" json:"transaction,omitempty"` + IsOrphan bool `protobuf:"varint,4,opt,name=isOrphan,proto3" json:"isOrphan,omitempty"` } func (x *MempoolEntry) Reset() { @@ -2067,6 +2101,13 @@ func (x *MempoolEntry) GetTransaction() *RpcTransaction { return nil } +func (x *MempoolEntry) GetIsOrphan() bool { + if x != nil { + return x.IsOrphan + } + return false +} + // GetConnectedPeerInfoRequestMessage requests information about all the p2p peers // currently connected to this kaspad. type GetConnectedPeerInfoRequestMessage struct { @@ -5856,7 +5897,9 @@ type GetMempoolEntriesByAddressesRequestMessage struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"` + Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"` + IncludeOrphanPool bool `protobuf:"varint,2,opt,name=includeOrphanPool,proto3" json:"includeOrphanPool,omitempty"` + FilterTransactionPool bool `protobuf:"varint,3,opt,name=filterTransactionPool,proto3" json:"filterTransactionPool,omitempty"` } func (x *GetMempoolEntriesByAddressesRequestMessage) Reset() { @@ -5898,6 +5941,20 @@ func (x *GetMempoolEntriesByAddressesRequestMessage) GetAddresses() []string { return nil } +func (x *GetMempoolEntriesByAddressesRequestMessage) GetIncludeOrphanPool() bool { + if x != nil { + return x.IncludeOrphanPool + } + return false +} + +func (x *GetMempoolEntriesByAddressesRequestMessage) GetFilterTransactionPool() bool { + if x != nil { + return x.FilterTransactionPool + } + return false +} + type GetMempoolEntriesByAddressesResponseMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6312,534 +6369,555 @@ var file_rpc_proto_rawDesc = []byte{ 0x54, 0x69, 0x70, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0x33, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, - 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x22, 0x7b, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x21, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, - 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, - 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, - 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, - 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x5d, 0x0a, 0x0c, - 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x66, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x3b, - 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x24, 0x0a, 0x22, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3c, 0x0a, 0x05, 0x69, 0x6e, 0x66, - 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x05, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0xd3, 0x02, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2a, 0x0a, - 0x10, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, - 0x67, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x4f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, - 0x73, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x69, 0x6d, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, - 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, - 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, - 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x19, 0x61, 0x64, 0x76, 0x65, 0x72, - 0x74, 0x69, 0x73, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x19, 0x61, 0x64, 0x76, 0x65, - 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x69, - 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, - 0x73, 0x49, 0x62, 0x64, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x69, 0x73, 0x49, 0x62, 0x64, 0x50, 0x65, 0x65, 0x72, 0x22, 0x53, 0x0a, 0x15, 0x41, 0x64, 0x64, - 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, - 0x69, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0b, 0x69, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x22, 0x44, - 0x0a, 0x16, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x80, 0x01, 0x0a, 0x1f, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4f, 0x72, - 0x70, 0x68, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x22, 0x74, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, - 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7d, 0x0a, - 0x35, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x1d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0x64, 0x0a, 0x36, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x22, 0x81, 0x02, 0x0a, 0x34, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x72, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, - 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x61, 0x64, 0x64, 0x65, 0x64, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x61, 0x64, 0x64, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x59, 0x0a, 0x16, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x52, 0x16, - 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0x5e, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x68, 0x61, 0x73, 0x68, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x70, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x29, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2a, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x41, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x22, 0x66, 0x0a, 0x1c, 0x47, - 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, - 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, - 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0x9a, 0x01, 0x0a, 0x34, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, - 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x44, 0x0a, 0x1d, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x1d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, - 0x22, 0x80, 0x01, 0x0a, 0x16, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x69, - 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x36, 0x0a, 0x16, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x61, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x73, 0x22, 0xae, 0x02, 0x0a, 0x35, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, - 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, - 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x61, 0x64, 0x64, 0x65, 0x64, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x61, 0x64, 0x64, 0x65, 0x64, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x59, 0x0a, - 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, - 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x8b, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, 0x77, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x77, 0x48, 0x61, 0x73, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x72, 0x6f, 0x72, 0x22, 0x97, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, + 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x49, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x72, 0x70, + 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x34, 0x0a, 0x15, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x22, 0x7b, 0x0a, + 0x1e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, - 0x63, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2a, + 0x2d, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, + 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x1c, 0x47, 0x65, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x1f, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9e, 0x03, 0x0a, 0x1e, 0x47, 0x65, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, - 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, - 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, - 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x70, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x70, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x1e, - 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x01, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x12, 0x26, - 0x0a, 0x0e, 0x70, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x54, 0x69, 0x6d, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x64, 0x69, - 0x61, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, - 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x13, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x72, 0x75, 0x6e, - 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, - 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x76, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2a, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x25, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, - 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, - 0x68, 0x22, 0x54, 0x0a, 0x26, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x27, 0x0a, 0x25, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x54, 0x0a, 0x26, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x1f, 0x47, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, + 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x50, + 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x34, 0x0a, 0x15, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, + 0x6f, 0x6c, 0x22, 0x81, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, + 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x23, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, - 0x12, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, - 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x76, 0x69, 0x6f, 0x6c, 0x61, - 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0x5b, 0x0a, - 0x2b, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, - 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, - 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0x18, 0x0a, 0x16, 0x53, 0x68, - 0x75, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x45, 0x0a, 0x17, 0x53, 0x68, 0x75, 0x74, 0x44, 0x6f, 0x77, 0x6e, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x79, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, + 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x73, 0x4f, 0x72, 0x70, 0x68, 0x61, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4f, 0x72, 0x70, 0x68, 0x61, + 0x6e, 0x22, 0x24, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8f, 0x01, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x70, 0x0a, 0x18, 0x47, - 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, - 0x73, 0x41, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x69, 0x73, 0x41, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x61, 0x0a, - 0x19, 0x47, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, + 0x3c, 0x0a, 0x05, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xd3, 0x02, 0x0a, 0x1b, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6c, + 0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, + 0x1e, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, + 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, + 0x19, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x19, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x74, + 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x49, 0x62, 0x64, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x49, 0x62, 0x64, 0x50, 0x65, 0x65, 0x72, 0x22, + 0x53, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x61, + 0x6e, 0x65, 0x6e, 0x74, 0x22, 0x44, 0x0a, 0x16, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x80, 0x01, 0x0a, 0x1f, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, + 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, + 0x52, 0x70, 0x63, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x22, 0x74, 0x0a, + 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, + 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x22, 0x7d, 0x0a, 0x35, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, + 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x1d, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x1d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x73, 0x22, 0x64, 0x0a, 0x36, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, + 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x81, 0x02, 0x0a, 0x34, 0x56, 0x69, 0x72, + 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x38, 0x0a, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x61, + 0x64, 0x64, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x61, 0x64, 0x64, 0x65, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x12, 0x59, 0x0a, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x73, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0x5e, 0x0a, 0x16, + 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x70, 0x0a, 0x17, + 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, + 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, + 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x41, + 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, + 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, + 0x64, 0x22, 0x66, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x9a, 0x01, 0x0a, 0x34, 0x47, 0x65, + 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x44, 0x0a, 0x1d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x16, 0x41, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x61, + 0x63, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, + 0x68, 0x12, 0x36, 0x0a, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, 0xae, 0x02, 0x0a, 0x35, 0x47, 0x65, + 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x34, 0x0a, + 0x15, 0x61, 0x64, 0x64, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x61, 0x64, + 0x64, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x12, 0x59, 0x0a, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x2a, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x8b, 0x01, 0x0a, 0x17, 0x47, + 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x6f, 0x77, 0x48, 0x61, 0x73, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x77, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, + 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x40, 0x0a, 0x20, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x22, 0x4f, 0x0a, 0x21, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x74, 0x78, 0x6f, - 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0x95, 0x01, 0x0a, 0x1f, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, - 0x3a, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78, - 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0x9c, 0x01, 0x0a, 0x15, - 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x32, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, - 0x63, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x47, 0x0a, 0x27, 0x53, 0x74, - 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x22, 0x56, 0x0a, 0x28, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x41, 0x0a, 0x21, 0x47, - 0x65, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x8c, - 0x01, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, - 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, + 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x8c, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, + 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x1f, + 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x67, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x9e, 0x03, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x67, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x70, 0x48, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x70, 0x48, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, + 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, + 0x75, 0x6c, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x70, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x64, 0x69, + 0x61, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, + 0x73, 0x74, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, + 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x76, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x2a, + 0x0a, 0x10, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x61, + 0x73, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, + 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x0f, 0x76, 0x69, + 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, + 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, + 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0x55, 0x0a, 0x25, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0x54, 0x0a, 0x26, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, - 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3d, 0x0a, - 0x21, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x42, 0x79, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x6a, 0x0a, 0x22, - 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x44, 0x0a, 0x24, 0x47, 0x65, 0x74, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x78, - 0x0a, 0x16, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x25, 0x47, 0x65, 0x74, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, - 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x31, 0x0a, 0x2f, 0x47, - 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x7c, - 0x0a, 0x30, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, - 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, + 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x27, 0x0a, + 0x25, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x54, 0x0a, 0x26, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3b, 0x0a, 0x39, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, - 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x68, 0x0a, 0x3a, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, - 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0x82, 0x01, 0x0a, 0x38, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, - 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x46, 0x0a, 0x1e, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, - 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, - 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, - 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x2c, 0x0a, 0x2a, 0x4e, 0x6f, 0x74, 0x69, - 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x59, 0x0a, 0x2b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x23, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x12, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x61, 0x73, 0x68, 0x22, 0x5b, 0x0a, 0x2b, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x43, + 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, + 0x22, 0x18, 0x0a, 0x16, 0x53, 0x68, 0x75, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x45, 0x0a, 0x17, 0x53, 0x68, + 0x75, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, + 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x22, 0x70, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x41, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x41, 0x73, 0x63, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x22, 0x61, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x40, 0x0a, 0x20, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x4f, 0x0a, 0x21, 0x4e, 0x6f, 0x74, 0x69, + 0x66, 0x79, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x95, 0x01, 0x0a, 0x1f, 0x55, 0x74, + 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x36, 0x0a, + 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, + 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x3a, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, + 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x22, 0x9c, 0x01, 0x0a, 0x15, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, + 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, + 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x75, 0x74, 0x78, + 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x70, 0x63, 0x55, 0x74, 0x78, 0x6f, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x22, 0x47, 0x0a, 0x27, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, + 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x56, 0x0a, 0x28, 0x53, 0x74, 0x6f, + 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x55, 0x0a, 0x29, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, - 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, - 0x0a, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, - 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x31, 0x0a, 0x2f, 0x4e, 0x6f, 0x74, 0x69, - 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, - 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x5e, 0x0a, 0x30, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x30, 0x0a, 0x2e, 0x50, - 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, - 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x38, 0x0a, - 0x36, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, - 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, - 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, 0x37, 0x53, 0x74, 0x6f, 0x70, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, + 0x72, 0x22, 0x41, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x55, 0x74, 0x78, 0x6f, + 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x65, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x42, 0x79, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, + 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, + 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x22, 0x3d, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x22, 0x6a, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, - 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x23, - 0x0a, 0x11, 0x42, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x70, 0x22, 0x40, 0x0a, 0x12, 0x42, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x25, 0x0a, 0x13, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, 0x42, 0x0a, 0x14, - 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xe4, 0x01, 0x0a, 0x16, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x32, 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x32, 0x70, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x65, - 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0d, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x73, 0x55, 0x74, 0x78, - 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x73, 0x53, 0x79, - 0x6e, 0x63, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x53, 0x79, - 0x6e, 0x63, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, - 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x6c, 0x0a, 0x2c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x93, - 0x01, 0x0a, 0x2d, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x36, 0x0a, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, - 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0x26, 0x0a, 0x24, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4e, 0x65, - 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x53, 0x0a, 0x25, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4e, 0x65, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, + 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x44, + 0x0a, 0x24, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x22, 0x78, 0x0a, 0x16, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, + 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x90, + 0x01, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x79, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, + 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x22, 0x31, 0x0a, 0x2f, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, + 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x7c, 0x0a, 0x30, 0x47, 0x65, 0x74, 0x56, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, + 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, + 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x3b, 0x0a, 0x39, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, + 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x68, 0x0a, 0x3a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, + 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x82, 0x01, 0x0a, 0x38, 0x56, 0x69, + 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x1e, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, + 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, + 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, + 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x2c, + 0x0a, 0x2a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, + 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x59, 0x0a, 0x2b, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, + 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x29, 0x56, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, + 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x76, + 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x31, + 0x0a, 0x2f, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x5e, 0x0a, 0x30, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x50, 0x72, 0x75, 0x6e, 0x69, + 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x25, 0x0a, 0x23, 0x4e, 0x65, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9b, 0x01, 0x0a, 0x15, 0x4d, 0x65, 0x6d, - 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x31, 0x0a, 0x07, - 0x73, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, - 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, - 0x35, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, - 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x22, 0x4a, 0x0a, 0x2a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, - 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, - 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, - 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x79, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a, + 0x72, 0x22, 0x30, 0x0a, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x22, 0x38, 0x0a, 0x36, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, + 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, + 0x37, 0x53, 0x74, 0x6f, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x50, 0x72, + 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, + 0x74, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0x23, 0x0a, 0x11, 0x42, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x22, 0x40, 0x0a, 0x12, 0x42, 0x61, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x25, 0x0a, 0x13, 0x55, + 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x70, 0x22, 0x42, 0x0a, 0x14, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0xe4, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x32, + 0x70, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x32, 0x70, 0x49, 0x64, + 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x69, 0x73, 0x55, 0x74, + 0x78, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0d, 0x69, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x12, 0x1a, + 0x0a, 0x08, 0x69, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x69, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6c, 0x0a, 0x2c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, + 0x74, 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, + 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x53, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, + 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x48, 0x61, 0x73, 0x68, 0x22, 0x93, 0x01, 0x0a, 0x2d, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, + 0x65, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, + 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x48, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x1c, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, - 0x78, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, - 0x78, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c, - 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x6f, 0x6d, - 0x70, 0x69, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, - 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x26, - 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, - 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x26, 0x0a, 0x24, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x79, 0x4e, 0x65, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x65, 0x6d, 0x70, + 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0x53, 0x0a, 0x25, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4e, 0x65, 0x77, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x25, 0x0a, 0x23, 0x4e, 0x65, 0x77, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9b, + 0x01, 0x0a, 0x15, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, + 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x31, 0x0a, 0x07, 0x73, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, + 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x35, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x69, + 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x09, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x22, 0xae, 0x01, 0x0a, + 0x2a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x72, 0x70, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x72, 0x70, + 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x34, 0x0a, 0x15, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x22, 0x95, 0x01, + 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, + 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x70, 0x6f, + 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x53, 0x6f, 0x6d, 0x70, + 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x53, 0x6f, 0x6d, 0x70, + 0x69, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x69, 0x72, + 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x12, 0x2a, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, + 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, + 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto index c80826744..81919c954 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc.proto @@ -215,6 +215,8 @@ message GetSelectedTipHashResponseMessage{ message GetMempoolEntryRequestMessage{ // The transaction's TransactionID. string txId = 1; + bool includeOrphanPool = 2; + bool filterTransactionPool = 3; } message GetMempoolEntryResponseMessage{ @@ -226,6 +228,8 @@ message GetMempoolEntryResponseMessage{ // GetMempoolEntriesRequestMessage requests information about all the transactions // currently in the mempool. message GetMempoolEntriesRequestMessage{ + bool includeOrphanPool = 1; + bool filterTransactionPool = 2; } message GetMempoolEntriesResponseMessage{ @@ -237,6 +241,7 @@ message GetMempoolEntriesResponseMessage{ message MempoolEntry{ uint64 fee = 1; RpcTransaction transaction = 3; + bool isOrphan = 4; } // GetConnectedPeerInfoRequestMessage requests information about all the p2p peers @@ -697,6 +702,8 @@ message MempoolEntryByAddress{ message GetMempoolEntriesByAddressesRequestMessage{ repeated string addresses = 1; + bool includeOrphanPool = 2; + bool filterTransactionPool = 3; } message GetMempoolEntriesByAddressesResponseMessage{ diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries.go index ac5af03bc..8e0760f16 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries.go @@ -9,14 +9,27 @@ func (x *KaspadMessage_GetMempoolEntriesRequest) toAppMessage() (appmessage.Mess if x == nil { return nil, errors.Wrapf(errorNil, "KaspadMessage_GetMempoolEntriesRequest is nil") } - return &appmessage.GetMempoolEntriesRequestMessage{}, nil + return x.GetMempoolEntriesRequest.toAppMessage() } -func (x *KaspadMessage_GetMempoolEntriesRequest) fromAppMessage(_ *appmessage.GetMempoolEntriesRequestMessage) error { - x.GetMempoolEntriesRequest = &GetMempoolEntriesRequestMessage{} +func (x *KaspadMessage_GetMempoolEntriesRequest) fromAppMessage(message *appmessage.GetMempoolEntriesRequestMessage) error { + x.GetMempoolEntriesRequest = &GetMempoolEntriesRequestMessage{ + IncludeOrphanPool: message.IncludeOrphanPool, + FilterTransactionPool: message.FilterTransactionPool, + } return nil } +func (x *GetMempoolEntriesRequestMessage) toAppMessage() (appmessage.Message, error) { + if x == nil { + return nil, errors.Wrapf(errorNil, "GetMempoolEntryRequestMessage is nil") + } + return &appmessage.GetMempoolEntriesRequestMessage{ + IncludeOrphanPool: x.IncludeOrphanPool, + FilterTransactionPool: x.FilterTransactionPool, + }, nil +} + func (x *KaspadMessage_GetMempoolEntriesResponse) toAppMessage() (appmessage.Message, error) { if x == nil { return nil, errors.Wrapf(errorNil, "KaspadMessage_GetMempoolEntriesResponse is nil") diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries_by_addresses.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries_by_addresses.go index 35f03d30e..57d4c4e83 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries_by_addresses.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entries_by_addresses.go @@ -7,14 +7,16 @@ import ( func (x *KaspadMessage_GetMempoolEntriesByAddressesRequest) toAppMessage() (appmessage.Message, error) { if x == nil { - return nil, errors.Wrapf(errorNil, "KaspadMessage_GetMempoolEntriesRequest is nil") + return nil, errors.Wrapf(errorNil, "KaspadMessage_KaspadMessage_GetMempoolEntriesByAddressesRequest is nil") } return x.GetMempoolEntriesByAddressesRequest.toAppMessage() } func (x *KaspadMessage_GetMempoolEntriesByAddressesRequest) fromAppMessage(message *appmessage.GetMempoolEntriesByAddressesRequestMessage) error { x.GetMempoolEntriesByAddressesRequest = &GetMempoolEntriesByAddressesRequestMessage{ - Addresses: message.Addresses, + Addresses: message.Addresses, + IncludeOrphanPool: message.IncludeOrphanPool, + FilterTransactionPool: message.FilterTransactionPool, } return nil } @@ -24,7 +26,9 @@ func (x *GetMempoolEntriesByAddressesRequestMessage) toAppMessage() (appmessage. return nil, errors.Wrapf(errorNil, "KaspadMessage_GetMempoolEntriesRequest is nil") } return &appmessage.GetMempoolEntriesByAddressesRequestMessage{ - Addresses: x.Addresses, + Addresses: x.Addresses, + IncludeOrphanPool: x.IncludeOrphanPool, + FilterTransactionPool: x.FilterTransactionPool, }, nil } diff --git a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entry.go b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entry.go index 48168b161..7953fdfee 100644 --- a/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entry.go +++ b/infrastructure/network/netadapter/server/grpcserver/protowire/rpc_get_mempool_entry.go @@ -14,7 +14,9 @@ func (x *KaspadMessage_GetMempoolEntryRequest) toAppMessage() (appmessage.Messag func (x *KaspadMessage_GetMempoolEntryRequest) fromAppMessage(message *appmessage.GetMempoolEntryRequestMessage) error { x.GetMempoolEntryRequest = &GetMempoolEntryRequestMessage{ - TxId: message.TxID, + TxId: message.TxID, + IncludeOrphanPool: message.IncludeOrphanPool, + FilterTransactionPool: message.FilterTransactionPool, } return nil } @@ -24,7 +26,9 @@ func (x *GetMempoolEntryRequestMessage) toAppMessage() (appmessage.Message, erro return nil, errors.Wrapf(errorNil, "GetMempoolEntryRequestMessage is nil") } return &appmessage.GetMempoolEntryRequestMessage{ - TxID: x.TxId, + TxID: x.TxId, + IncludeOrphanPool: x.IncludeOrphanPool, + FilterTransactionPool: x.FilterTransactionPool, }, nil } @@ -91,6 +95,7 @@ func (x *MempoolEntry) toAppMessage() (*appmessage.MempoolEntry, error) { return &appmessage.MempoolEntry{ Fee: x.Fee, Transaction: transaction, + IsOrphan: x.IsOrphan, }, nil } @@ -103,6 +108,7 @@ func (x *MempoolEntry) fromAppMessage(message *appmessage.MempoolEntry) error { *x = MempoolEntry{ Fee: message.Fee, Transaction: transaction, + IsOrphan: message.IsOrphan, } return nil } diff --git a/infrastructure/network/netadapter/server/grpcserver/rpcserver.go b/infrastructure/network/netadapter/server/grpcserver/rpcserver.go index 516463956..c80a36c2d 100644 --- a/infrastructure/network/netadapter/server/grpcserver/rpcserver.go +++ b/infrastructure/network/netadapter/server/grpcserver/rpcserver.go @@ -14,12 +14,9 @@ type rpcServer struct { // RPCMaxMessageSize is the max message size for the RPC server to send and receive const RPCMaxMessageSize = 1024 * 1024 * 1024 // 1 GB -// RPCMaxInboundConnections is the max amount of inbound connections for the RPC server -const RPCMaxInboundConnections = 128 - // NewRPCServer creates a new RPCServer -func NewRPCServer(listeningAddresses []string) (server.Server, error) { - gRPCServer := newGRPCServer(listeningAddresses, RPCMaxMessageSize, RPCMaxInboundConnections, "RPC") +func NewRPCServer(listeningAddresses []string, rpcMaxInboundConnections int) (server.Server, error) { + gRPCServer := newGRPCServer(listeningAddresses, RPCMaxMessageSize, rpcMaxInboundConnections, "RPC") rpcServer := &rpcServer{gRPCServer: *gRPCServer} protowire.RegisterRPCServer(gRPCServer.server, rpcServer) return rpcServer, nil diff --git a/infrastructure/network/rpcclient/rpc_get_mempool_entries.go b/infrastructure/network/rpcclient/rpc_get_mempool_entries.go index 2e307264e..7c40d580c 100644 --- a/infrastructure/network/rpcclient/rpc_get_mempool_entries.go +++ b/infrastructure/network/rpcclient/rpc_get_mempool_entries.go @@ -3,8 +3,8 @@ package rpcclient import "github.com/kaspanet/kaspad/app/appmessage" // GetMempoolEntries sends an RPC request respective to the function's name and returns the RPC server's response -func (c *RPCClient) GetMempoolEntries() (*appmessage.GetMempoolEntriesResponseMessage, error) { - err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetMempoolEntriesRequestMessage()) +func (c *RPCClient) GetMempoolEntries(includeOrphanPool bool, filterTransactionPool bool) (*appmessage.GetMempoolEntriesResponseMessage, error) { + err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetMempoolEntriesRequestMessage(includeOrphanPool, filterTransactionPool)) if err != nil { return nil, err } diff --git a/infrastructure/network/rpcclient/rpc_get_mempool_entries_by_address.go b/infrastructure/network/rpcclient/rpc_get_mempool_entries_by_address.go index b3ec1fd11..8d04d9b55 100644 --- a/infrastructure/network/rpcclient/rpc_get_mempool_entries_by_address.go +++ b/infrastructure/network/rpcclient/rpc_get_mempool_entries_by_address.go @@ -3,8 +3,8 @@ package rpcclient import "github.com/kaspanet/kaspad/app/appmessage" // GetMempoolEntriesByAddresses sends an RPC request respective to the function's name and returns the RPC server's response -func (c *RPCClient) GetMempoolEntriesByAddresses(addresses []string) (*appmessage.GetMempoolEntriesByAddressesResponseMessage, error) { - err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetMempoolEntriesByAddressesRequestMessage(addresses)) +func (c *RPCClient) GetMempoolEntriesByAddresses(addresses []string, includeOrphanPool bool, filterTransactionPool bool) (*appmessage.GetMempoolEntriesByAddressesResponseMessage, error) { + err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetMempoolEntriesByAddressesRequestMessage(addresses, includeOrphanPool, filterTransactionPool)) if err != nil { return nil, err } diff --git a/infrastructure/network/rpcclient/rpc_get_mempool_entry.go b/infrastructure/network/rpcclient/rpc_get_mempool_entry.go index c3ba84a05..663e02148 100644 --- a/infrastructure/network/rpcclient/rpc_get_mempool_entry.go +++ b/infrastructure/network/rpcclient/rpc_get_mempool_entry.go @@ -3,8 +3,8 @@ package rpcclient import "github.com/kaspanet/kaspad/app/appmessage" // GetMempoolEntry sends an RPC request respective to the function's name and returns the RPC server's response -func (c *RPCClient) GetMempoolEntry(txID string) (*appmessage.GetMempoolEntryResponseMessage, error) { - err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetMempoolEntryRequestMessage(txID)) +func (c *RPCClient) GetMempoolEntry(txID string, includeOrphanPool bool, filterTransactionPool bool) (*appmessage.GetMempoolEntryResponseMessage, error) { + err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetMempoolEntryRequestMessage(txID, includeOrphanPool, filterTransactionPool)) if err != nil { return nil, err } diff --git a/stability-tests/common/mine/mine.go b/stability-tests/common/mine/mine.go index 54e34ddd6..bcc65b20d 100644 --- a/stability-tests/common/mine/mine.go +++ b/stability-tests/common/mine/mine.go @@ -122,7 +122,7 @@ func mineOrFetchBlock(blockData JSONBlock, mdb *miningDB, testConsensus testapi. SolveBlock(block) } - _, err = testConsensus.ValidateAndInsertBlock(block, true) + err = testConsensus.ValidateAndInsertBlock(block, true) if err != nil { return nil, errors.Wrap(err, "error in ValidateAndInsertBlock") } diff --git a/stability-tests/netsync/fast-pruning-ibd-test/generate_test.go b/stability-tests/netsync/fast-pruning-ibd-test/generate_test.go index 7efcdab74..58e6a2e77 100644 --- a/stability-tests/netsync/fast-pruning-ibd-test/generate_test.go +++ b/stability-tests/netsync/fast-pruning-ibd-test/generate_test.go @@ -57,7 +57,7 @@ func TestGenerateFastPruningIBDTest(t *testing.T) { } header.SetNonce(tip.Header.Nonce() + i) block := &externalapi.DomainBlock{Header: header.ToImmutable(), Transactions: tip.Transactions} - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -103,7 +103,7 @@ func TestGenerateFastPruningIBDTest(t *testing.T) { t.Fatal(err) } - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } @@ -124,7 +124,7 @@ func TestGenerateFastPruningIBDTest(t *testing.T) { t.Fatal(err) } - _, err = tc.ValidateAndInsertBlock(block, true) + err = tc.ValidateAndInsertBlock(block, true) if err != nil { t.Fatalf("ValidateAndInsertBlock: %+v", err) } diff --git a/stability-tests/orphans/prepare_blocks.go b/stability-tests/orphans/prepare_blocks.go index dd4929a3c..bc306e044 100644 --- a/stability-tests/orphans/prepare_blocks.go +++ b/stability-tests/orphans/prepare_blocks.go @@ -49,7 +49,7 @@ func prepareBlocks() (blocks []*externalapi.DomainBlock, topBlock *externalapi.D } mine.SolveBlock(block) - _, err = testConsensus.ValidateAndInsertBlock(block, true) + err = testConsensus.ValidateAndInsertBlock(block, true) if err != nil { return nil, nil, errors.Wrap(err, "error in ValidateAndInsertBlock") } diff --git a/stability-tests/reorg/reorg.go b/stability-tests/reorg/reorg.go index 2ec58d10b..e691dc9c4 100644 --- a/stability-tests/reorg/reorg.go +++ b/stability-tests/reorg/reorg.go @@ -86,7 +86,7 @@ func testReorg(cfg *configFlags) { block.Header = mutableHeader.ToImmutable() } - _, err = tcAttacker.ValidateAndInsertBlock(block, true) + err = tcAttacker.ValidateAndInsertBlock(block, true) if err != nil { panic(err) } @@ -122,7 +122,7 @@ func testReorg(cfg *configFlags) { if i%100 == 0 { log.Infof("Validated %d blocks from the attacker chain", i) } - _, err := tc.ValidateAndInsertBlock(block, true) + err := tc.ValidateAndInsertBlock(block, true) if err != nil { panic(err) } diff --git a/testing/integration/config_test.go b/testing/integration/config_test.go index e9d72bd86..6a975bd33 100644 --- a/testing/integration/config_test.go +++ b/testing/integration/config_test.go @@ -31,7 +31,7 @@ const ( miningAddress3 = "kaspasim:qqq754f2gdcjcnykwuwwr60c82rh5u6mxxe7yqxljnrxz9fu0h95kduq9ezng" miningAddress3PrivateKey = "f6c8f31fd359cbb97007034780bc4021f6ad01c6bc10499b79849efd4cc7ca39" - defaultTimeout = 10 * time.Second + defaultTimeout = 30 * time.Second ) func setConfig(t *testing.T, harness *appHarness, protocolVersion uint32) { diff --git a/testing/integration/rpc_test.go b/testing/integration/rpc_test.go index b0febc0a2..44fb1e40d 100644 --- a/testing/integration/rpc_test.go +++ b/testing/integration/rpc_test.go @@ -1,7 +1,7 @@ package integration import ( - "github.com/kaspanet/kaspad/infrastructure/network/netadapter/server/grpcserver" + "github.com/kaspanet/kaspad/infrastructure/config" "testing" "time" @@ -45,7 +45,7 @@ func TestRPCMaxInboundConnections(t *testing.T) { rpcClients := []*testRPCClient{} doneChan := make(chan error) go func() { - for i := 0; i < grpcserver.RPCMaxInboundConnections; i++ { + for i := 0; i < config.DefaultMaxRPCClients; i++ { rpcClient, err := newTestRPCClient(harness.rpcAddress) if err != nil { doneChan <- err @@ -60,7 +60,7 @@ func TestRPCMaxInboundConnections(t *testing.T) { t.Fatalf("newTestRPCClient: %s", err) } case <-time.After(time.Second * 5): - t.Fatalf("Timeout for connecting %d RPC connections elapsed", grpcserver.RPCMaxInboundConnections) + t.Fatalf("Timeout for connecting %d RPC connections elapsed", config.DefaultMaxRPCClients) } // Try to connect another client. We expect this to fail diff --git a/testing/integration/tx_relay_test.go b/testing/integration/tx_relay_test.go index 6fefae37c..b6863e7cc 100644 --- a/testing/integration/tx_relay_test.go +++ b/testing/integration/tx_relay_test.go @@ -69,7 +69,7 @@ func TestTxRelay(t *testing.T) { for range ticker.C { - _, err := payee.rpcClient.GetMempoolEntry(txID) + getMempoolEntryResponse, err := payee.rpcClient.GetMempoolEntry(txID, true, false) if err != nil { if strings.Contains(err.Error(), "not found") { continue @@ -77,12 +77,16 @@ func TestTxRelay(t *testing.T) { t.Fatalf("Error getting mempool entry: %+v", err) } + mempoolEntry := getMempoolEntryResponse.Entry + if mempoolEntry.IsOrphan { + t.Fatalf("transaction %s is an orphan, although it shouldn't be", mempoolEntry.Transaction.VerboseData.TransactionID) + } - mempoolEntriesByAddresses, err := payee.rpcClient.GetMempoolEntriesByAddresses(mempoolAddressQuery) + getMempoolEntriesByAddressesResponse, err := payee.rpcClient.GetMempoolEntriesByAddresses(mempoolAddressQuery, true, false) if err != nil { t.Fatalf("Error getting mempool entry: %+v", err) } - for _, mempoolEntryByAddress := range mempoolEntriesByAddresses.Entries { + for _, mempoolEntryByAddress := range getMempoolEntriesByAddressesResponse.Entries { if payee.miningAddress == mempoolEntryByAddress.Address { if len(mempoolEntryByAddress.Sending) > 1 { t.Fatal("Error payee is sending") @@ -99,7 +103,16 @@ func TestTxRelay(t *testing.T) { t.Fatal("Error payer is reciving") } } - continue + for _, mempoolEntry := range mempoolEntryByAddress.Receiving { + if mempoolEntry.IsOrphan { + t.Fatalf("transaction %s is an orphan, although it shouldn't be", mempoolEntry.Transaction.VerboseData.TransactionID) + } + } + for _, mempoolEntry := range mempoolEntryByAddress.Sending { + if mempoolEntry.IsOrphan { + t.Fatalf("transaction %s is an orphan, although it shouldn't be", mempoolEntry.Transaction.VerboseData.TransactionID) + } + } } close(txAddedToMempoolChan) diff --git a/util/difficulty/difficulty.go b/util/difficulty/difficulty.go index 27bf0d944..b247283ae 100644 --- a/util/difficulty/difficulty.go +++ b/util/difficulty/difficulty.go @@ -136,11 +136,11 @@ func CalcWork(bits uint32) *big.Int { func getHashrate(target *big.Int, TargetTimePerBlock time.Duration) *big.Int { // From: https://bitcoin.stackexchange.com/a/5557/40800 - // difficulty = hashrate / (2^256 / max_target / block_rate_in_seconds) - // hashrate = difficulty * (2^256 / max_target / block_rate_in_seconds) + // difficulty = hashrate / (2^256 / max_target / seconds_per_block) + // hashrate = difficulty * (2^256 / max_target / seconds_per_block) // difficulty = max_target / target - // hashrate = (max_target / target) * (2^256 / max_target / block_rate_in_seconds) - // hashrate = 2^256 / (target * block_rate_in_seconds) + // hashrate = (max_target / target) * (2^256 / max_target / seconds_per_block) + // hashrate = 2^256 / (target * seconds_per_block) tmp := new(big.Int) divisor := new(big.Int).Set(target) diff --git a/version/version.go b/version/version.go index 2edacab9c..1df34d5d6 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs const ( appMajor uint = 0 appMinor uint = 12 - appPatch uint = 1 + appPatch uint = 2 ) // appBuild is defined as a variable so it can be overridden during the build