From 45d5927d2c7c9b13e9ed751344428de2450ee92f Mon Sep 17 00:00:00 2001 From: Alok Date: Thu, 22 May 2025 19:48:36 +0530 Subject: [PATCH 01/14] feat: preconf flow tracking --- p2p/pkg/preconfirmation/store/store.go | 43 +++- p2p/pkg/preconfirmation/tracker/tracker.go | 233 +++++++++++++-------- 2 files changed, 188 insertions(+), 88 deletions(-) diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index 0b43e15c0..5207398de 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -52,10 +52,12 @@ type Store struct { st storage.Storage } -type EncryptedPreConfirmationWithDecrypted struct { +type Commitment struct { *preconfpb.EncryptedPreConfirmation *preconfpb.PreConfirmation TxnHash common.Hash + Nonce uint64 + Status string } type BlockWinner struct { @@ -74,7 +76,7 @@ func New(st storage.Storage) *Store { } } -func (s *Store) AddCommitment(commitment *EncryptedPreConfirmationWithDecrypted) (err error) { +func (s *Store) AddCommitment(commitment *Commitment) (err error) { s.mu.Lock() defer s.mu.Unlock() @@ -119,15 +121,44 @@ func (s *Store) AddCommitment(commitment *EncryptedPreConfirmationWithDecrypted) return writer.Put(cIndexKey, cIndexValueBuf) } -func (s *Store) GetCommitments(blockNum int64) ([]*EncryptedPreConfirmationWithDecrypted, error) { +func (s *Store) SetStatus(blockNumber int64, bidAmt string, cDigest []byte, status string) error { + s.mu.Lock() + defer s.mu.Unlock() + + key := commitmentKey(blockNumber, bidAmt, cDigest) + + cmtBuf, err := s.st.Get(key) + if err != nil { + if errors.Is(err, storage.ErrKeyNotFound) { + return nil + } + } + + commitment := new(Commitment) + err = msgpack.Unmarshal(cmtBuf, commitment) + if err != nil { + return err + } + + commitment.Status = status + + buf, err := msgpack.Marshal(commitment) + if err != nil { + return err + } + + return s.st.Put(key, buf) +} + +func (s *Store) GetCommitments(blockNum int64) ([]*Commitment, error) { s.mu.RLock() defer s.mu.RUnlock() blockCommitmentsKey := blockCommitmentPrefix(blockNum) - commitments := make([]*EncryptedPreConfirmationWithDecrypted, 0) + commitments := make([]*Commitment, 0) err := s.st.WalkPrefix(blockCommitmentsKey, func(key string, value []byte) bool { - commitment := new(EncryptedPreConfirmationWithDecrypted) + commitment := new(Commitment) err := msgpack.Unmarshal(value, commitment) if err != nil { return false @@ -188,7 +219,7 @@ func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) error { return err } - cmt := new(EncryptedPreConfirmationWithDecrypted) + cmt := new(Commitment) err = msgpack.Unmarshal(cmtBuf, cmt) if err != nil { return err diff --git a/p2p/pkg/preconfirmation/tracker/tracker.go b/p2p/pkg/preconfirmation/tracker/tracker.go index 0c639c56a..114fa652c 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker.go +++ b/p2p/pkg/preconfirmation/tracker/tracker.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" bidderregistry "github.com/primev/mev-commit/contracts-abi/clients/BidderRegistry" blocktracker "github.com/primev/mev-commit/contracts-abi/clients/BlockTracker" + oracle "github.com/primev/mev-commit/contracts-abi/clients/Oracle" preconfcommstore "github.com/primev/mev-commit/contracts-abi/clients/PreconfManager" "github.com/primev/mev-commit/p2p/pkg/crypto" "github.com/primev/mev-commit/p2p/pkg/p2p" @@ -41,9 +42,14 @@ type Tracker struct { providerNikeSK *fr.Element receiptGetter txmonitor.BatchReceiptGetter optsGetter OptsGetter + watcher Watcher newL1Blocks chan *blocktracker.BlocktrackerNewL1Block unopenedCmts chan *preconfcommstore.PreconfmanagerUnopenedCommitmentStored commitments chan *preconfcommstore.PreconfmanagerOpenedCommitmentStored + statusUpdate chan statusUpdateTask + processed chan *oracle.OracleCommitmentProcessed + rewards chan *bidderregistry.BidderregistryFundsRewarded + returns chan *bidderregistry.BidderregistryFundsRetrieved triggerOpen chan struct{} metrics *metrics logger *slog.Logger @@ -52,8 +58,8 @@ type Tracker struct { type OptsGetter func(context.Context) (*bind.TransactOpts, error) type CommitmentStore interface { - GetCommitments(blockNum int64) ([]*store.EncryptedPreConfirmationWithDecrypted, error) - AddCommitment(commitment *store.EncryptedPreConfirmationWithDecrypted) error + GetCommitments(blockNum int64) ([]*store.Commitment, error) + AddCommitment(commitment *store.Commitment) error ClearBlockNumber(blockNum int64) error DeleteCommitmentByDigest( blockNum int64, @@ -64,6 +70,12 @@ type CommitmentStore interface { commitmentDigest, commitmentIndex [32]byte, ) error + SetStatus( + blockNumber int64, + bidAmt string, + commitmentDigest []byte, + status string, + ) error ClearCommitmentIndexes(upto int64) error AddWinner(winner *store.BlockWinner) error BlockWinners() ([]*store.BlockWinner, error) @@ -76,6 +88,10 @@ type PreconfContract interface { ) (*types.Transaction, error) } +type Watcher interface { + WatchTx(txnHash common.Hash, nonce uint64) <-chan txmonitor.Result +} + func NewTracker( chainID *big.Int, peerType p2p.PeerType, @@ -115,68 +131,17 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { eg, egCtx := errgroup.WithContext(ctx) evts := []events.EventHandler{ - events.NewEventHandler( - "NewL1Block", - func(newL1Block *blocktracker.BlocktrackerNewL1Block) { - select { - case <-egCtx.Done(): - t.logger.Info("NewL1Block context done") - case t.newL1Blocks <- newL1Block: - } - }, - ), - events.NewEventHandler( - "UnopenedCommitmentStored", - func(ec *preconfcommstore.PreconfmanagerUnopenedCommitmentStored) { - select { - case <-egCtx.Done(): - t.logger.Info("UnopenedCommitmentStored context done") - case t.unopenedCmts <- ec: - } - }, - ), - events.NewEventHandler( - "FundsRewarded", - func(fr *bidderregistry.BidderregistryFundsRewarded) { - if fr.Bidder.Cmp(t.self) == 0 || fr.Provider.Cmp(t.self) == 0 { - t.logger.Info("funds settled for bid", - "commitmentDigest", common.BytesToHash(fr.CommitmentDigest[:]), - "window", fr.Window, - "amount", fr.Amount, - "bidder", fr.Bidder, - "provider", fr.Provider, - ) - } - }, - ), + events.NewChannelEventHandler(egCtx, "NewL1Block", t.newL1Blocks), + events.NewChannelEventHandler(egCtx, "UnopenedCommitmentStored", t.unopenedCmts), + events.NewChannelEventHandler(egCtx, "CommitmentProcessed", t.processed), + events.NewChannelEventHandler(egCtx, "FundsRewarded", t.rewards), } if t.peerType == p2p.PeerTypeBidder { evts = append( evts, - events.NewEventHandler( - "OpenedCommitmentStored", - func(cs *preconfcommstore.PreconfmanagerOpenedCommitmentStored) { - select { - case <-egCtx.Done(): - t.logger.Info("OpenedCommitmentStored context done") - case t.commitments <- cs: - } - }, - ), - events.NewEventHandler( - "FundsRetrieved", - func(fr *bidderregistry.BidderregistryFundsRetrieved) { - if fr.Bidder.Cmp(t.self) == 0 { - t.logger.Info("funds returned for bid", - "commitmentDigest", common.BytesToHash(fr.CommitmentDigest[:]), - "amount", fr.Amount, - "window", fr.Window, - "bidder", fr.Bidder, - ) - } - }, - ), + events.NewChannelEventHandler(egCtx, "OpenedCommitmentStored", t.commitments), + events.NewChannelEventHandler(egCtx, "FundsRetrieved", t.returns), ) } @@ -289,6 +254,34 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { } }) + eg.Go(func() error { + for { + select { + case <-egCtx.Done(): + t.logger.Info("handleCommitmentProcessed context done") + return nil + case err := <-sub.Err(): + return fmt.Errorf("event subscription error: %w", err) + case cp := <-t.processed: + // handle event + } + } + }) + + eg.Go(func() error { + for { + select { + case <-egCtx.Done(): + t.logger.Info("handleFundsRewarded context done") + return nil + case err := <-sub.Err(): + return fmt.Errorf("event subscription error: %w", err) + case fr := <-t.rewards: + // handle event + } + } + }) + eg.Go(func() error { return t.clearCommitments(egCtx) }) @@ -310,6 +303,19 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { } } }) + eg.Go(func() error { + for { + select { + case <-egCtx.Done(): + t.logger.Info("handleFundsRetrieved context done") + return nil + case err := <-sub.Err(): + return fmt.Errorf("event subscription error: %w", err) + case fr := <-t.returns: + // handle event + } + } + }) } go func() { @@ -324,9 +330,28 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { func (t *Tracker) TrackCommitment( ctx context.Context, - commitment *store.EncryptedPreConfirmationWithDecrypted, + commitment *store.Commitment, ) error { - return t.store.AddCommitment(commitment) + if err := t.store.AddCommitment(commitment); err != nil { + t.logger.Error("failed to add commitment", "error", err) + return err + } + + if commitment.TxnHash != (common.Hash{}) { + select { + case <-ctx.Done(): + return ctx.Err() + case t.statusUpdate <- statusUpdateTask{ + commitment: commitment, + txnHash: commitment.TxnHash, + nonce: commitment.Nonce, + onSuccess: "Unopened commitment stored", + onError: "Failed to store unopened commitment", + }: + } + } + + return nil } func (t *Tracker) Metrics() []prometheus.Collector { @@ -357,6 +382,55 @@ func (t *Tracker) handleNewL1Block( }) } +type statusUpdateTask struct { + commitment *store.Commitment + txnHash common.Hash + nonce uint64 + onSuccess string + onError string +} + +func (t *Tracker) statusUpdater( + ctx context.Context, + taskCh chan statusUpdateTask, +) error { + eg, ctx := errgroup.WithContext(ctx) + for { + select { + case <-ctx.Done(): + t.logger.Info("status updater context done") + return eg.Wait() + case task := <-taskCh: + eg.Go(func() error { + res := t.watcher.WatchTx(task.txnHash, task.nonce) + select { + case <-ctx.Done(): + t.logger.Info("watcher context done") + return ctx.Err() + case r := <-res: + var status string + if r.Err != nil { + status = fmt.Sprintf("%s: %s", task.onError, r.Err) + t.logger.Error("failed to update status", "error", r.Err) + } else { + status = task.onSuccess + t.logger.Debug("status updated on chain", "hash", task.txnHash, "status", r.Receipt.Status) + } + if err := t.store.SetStatus( + task.commitment.Bid.BlockNumber, + task.commitment.Bid.BidAmount, + task.commitment.Commitment, + status, + ); err != nil { + t.logger.Error("failed to set status", "error", err) + } + } + return nil + }) + } + } +} + func (t *Tracker) openCommitments( ctx context.Context, newL1Block *store.BlockWinner, @@ -369,14 +443,12 @@ func (t *Tracker) openCommitments( return err } - failedCommitments := make([]common.Hash, 0) settled := 0 + failed := 0 for _, commitment := range commitments { if commitment.CommitmentIndex == nil { t.logger.Debug("commitment index not found", "commitment", commitment) - if commitment.TxnHash != (common.Hash{}) { - failedCommitments = append(failedCommitments, commitment.TxnHash) - } + failed++ continue } if common.BytesToAddress(commitment.ProviderAddress).Cmp(newL1Block.Winner) != 0 { @@ -442,6 +514,18 @@ func (t *Tracker) openCommitments( "committer", common.Bytes2Hex(commitment.ProviderAddress), ) settled++ + select { + case <-ctx.Done(): + t.logger.Info("openCommitments context done") + return ctx.Err() + case t.statusUpdate <- statusUpdateTask{ + commitment: commitment, + txnHash: txn.Hash(), + nonce: txn.Nonce(), + onSuccess: "Opened commitment", + onError: "Failed to open commitment", + }: + } } err = t.store.ClearBlockNumber(newL1Block.BlockNumber) @@ -455,7 +539,7 @@ func (t *Tracker) openCommitments( "blockNumber", newL1Block.BlockNumber, "total", len(commitments), "settled", settled, - "failed", len(failedCommitments), + "failed", failed, "duration", openDuration, ) @@ -463,21 +547,6 @@ func (t *Tracker) openCommitments( t.metrics.totalOpenedCommitments.Add(float64(settled)) t.metrics.blockCommitmentProcessDuration.Set(float64(openDuration)) - if len(failedCommitments) > 0 { - t.logger.Info("processing failed commitments", "count", len(failedCommitments)) - receipts, err := t.receiptGetter.BatchReceipts(ctx, failedCommitments) - if err != nil { - t.logger.Warn("failed to get receipts for failed commitments", "error", err) - return nil - } - for i, receipt := range receipts { - t.logger.Debug("receipt for failed commitment", - "txHash", failedCommitments[i], - "error", receipt.Err, - ) - } - } - return nil } @@ -533,7 +602,7 @@ func (t *Tracker) handleOpenedCommitmentStored( } func (t *Tracker) generateZKProof( - commitment *store.EncryptedPreConfirmationWithDecrypted, + commitment *store.Commitment, ) ([]*big.Int, error) { pubB, err := crypto.BN254PublicKeyFromBytes(commitment.Bid.NikePublicKey) if err != nil { From acfb1a130f77dd79f8c1e185eaaea1e188248e0d Mon Sep 17 00:00:00 2001 From: Alok Date: Fri, 23 May 2025 14:02:55 +0530 Subject: [PATCH 02/14] feat: preconf flow tracking --- p2p/pkg/preconfirmation/store/store.go | 128 ++++++++++++++++++++- p2p/pkg/preconfirmation/tracker/tracker.go | 22 +++- 2 files changed, 144 insertions(+), 6 deletions(-) diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index 5207398de..86c9fe0d9 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -19,6 +19,8 @@ const ( blockWinnerNS = "bw/" cmtIndexNS = "ci/" + + indexToDigestNS = "id/" ) var ( @@ -45,6 +47,9 @@ var ( cmtIndexKey = func(cIndex []byte) string { return fmt.Sprintf("%s%s", cmtIndexNS, string(cIndex)) } + indexToDigestKey = func(cIndex []byte) string { + return fmt.Sprintf("%s%s", indexToDigestNS, string(cIndex)) + } ) type Store struct { @@ -58,6 +63,11 @@ type Commitment struct { TxnHash common.Hash Nonce uint64 Status string + Opened bool + Settled bool + IsSlash bool + Payment string + Refund string } type BlockWinner struct { @@ -191,7 +201,7 @@ func (s *Store) DeleteCommitmentByDigest(blockNum int64, bidAmt string, digest [ return s.st.Delete(commitmentKey(blockNum, bidAmt, digest[:])) } -func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) error { +func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) (retErr error) { s.mu.RLock() cIndexValueBuf, err := s.st.Get(cmtIndexKey(cDigest[:])) s.mu.RUnlock() @@ -231,7 +241,121 @@ func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) error { return err } - return s.st.Put(commitmentKey, buf) + var writer storage.Writer + if w, ok := s.st.(storage.Batcher); ok { + batch := w.Batch() + writer = batch + defer func() { + switch { + case retErr != nil: + batch.Reset() + case retErr == nil: + err = batch.Write() + } + }() + } else { + writer = s.st + } + if err := writer.Put(commitmentKey, buf); err != nil { + return err + } + + indexToDigest := indexToDigestKey(cmt.CommitmentIndex) + return writer.Put(indexToDigest, []byte(commitmentKey)) +} + +func (s *Store) UpdateSettlement(index []byte, isSlash bool) error { + s.mu.Lock() + defer s.mu.Unlock() + + key := indexToDigestKey(index) + commitmentKey, err := s.st.Get(key) + if err != nil { + if errors.Is(err, storage.ErrKeyNotFound) { + return nil + } + return err + } + + cmtBuf, err := s.st.Get(string(commitmentKey)) + if err != nil { + return err + } + + cmt := new(Commitment) + err = msgpack.Unmarshal(cmtBuf, cmt) + if err != nil { + return err + } + + cmt.Settled = true + cmt.IsSlash = isSlash + + buf, err := msgpack.Marshal(cmt) + if err != nil { + return err + } + + return s.st.Put(string(commitmentKey), buf) +} + +func (s *Store) UpdatePayment(digest []byte, payment, refund string) error { + s.mu.Lock() + defer s.mu.Unlock() + + cmt := new(Commitment) + err = msgpack.Unmarshal(cmtBuf, cmt) + if err != nil { + return err + } + + cmt.Payment = payment + cmt.Refund = refund + + buf, err := msgpack.Marshal(cmt) + if err != nil { + return err + } + + return s.st.Put(string(commitmentKey), buf) +} + +func (s *Store) GetCommitmentByIndex(index []byte) (*Commitment, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + key := indexToDigestKey(index) + commitmentKey, err := s.st.Get(key) + if err != nil { + return nil, err + } + + cmtBuf, err := s.st.Get(string(commitmentKey)) + if err != nil { + return nil, err + } + + cmt := new(Commitment) + err = msgpack.Unmarshal(cmtBuf, cmt) + if err != nil { + return nil, err + } + + return cmt, nil +} + +func (s *Store) UpdateCommitment(cmt *Commitment) error { + s.mu.Lock() + defer s.mu.Unlock() + + key := commitmentKey(cmt.Bid.BlockNumber, cmt.Bid.BidAmount, cmt.Commitment) + + buf, err := msgpack.Marshal(cmt) + if err != nil { + return err + } + + return s.st.Put(key, buf) } func (s *Store) ClearCommitmentIndexes(uptoBlock int64) error { diff --git a/p2p/pkg/preconfirmation/tracker/tracker.go b/p2p/pkg/preconfirmation/tracker/tracker.go index 114fa652c..022f31e4f 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker.go +++ b/p2p/pkg/preconfirmation/tracker/tracker.go @@ -76,6 +76,11 @@ type CommitmentStore interface { commitmentDigest []byte, status string, ) error + GetCommitmentByIndex(index []byte) (*store.Commitment, error) + GetCommitmentByDigest(digest []byte) (*store.Commitment, error) + UpdateCommitment(cmt *store.Commitment) error + UpdateSettlement(index []byte, isSlash bool) error + UpdatePayment(digest []byte, payment, refund string) error ClearCommitmentIndexes(upto int64) error AddWinner(winner *store.BlockWinner) error BlockWinners() ([]*store.BlockWinner, error) @@ -263,7 +268,10 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { case err := <-sub.Err(): return fmt.Errorf("event subscription error: %w", err) case cp := <-t.processed: - // handle event + if err := t.store.UpdateSettlement(cp.CommitmentIndex[:], cp.IsSlash); err != nil { + t.logger.Error("failed to update commitment index", "error", err) + continue + } } } }) @@ -277,7 +285,10 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { case err := <-sub.Err(): return fmt.Errorf("event subscription error: %w", err) case fr := <-t.rewards: - // handle event + if err := t.store.UpdatePayment(fr.CommitmentDigest[:], fr.Amount.String(), ""); err != nil { + t.logger.Error("failed to update payment", "error", err) + continue + } } } }) @@ -312,7 +323,10 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { case err := <-sub.Err(): return fmt.Errorf("event subscription error: %w", err) case fr := <-t.returns: - // handle event + if err := t.store.UpdatePayment(fr.CommitmentDigest[:], "", fr.Amount.String()); err != nil { + t.logger.Error("failed to update payment", "error", err) + continue + } } } }) @@ -411,7 +425,7 @@ func (t *Tracker) statusUpdater( var status string if r.Err != nil { status = fmt.Sprintf("%s: %s", task.onError, r.Err) - t.logger.Error("failed to update status", "error", r.Err) + t.logger.Error("txn failure on chain", "error", r.Err) } else { status = task.onSuccess t.logger.Debug("status updated on chain", "hash", task.txnHash, "status", r.Receipt.Status) From 9004bc01ab41167c56728280ec7a27505f9e0eed Mon Sep 17 00:00:00 2001 From: Alok Nerurkar Date: Sun, 25 May 2025 00:55:35 +0530 Subject: [PATCH 03/14] fix: store update with tests --- oracle/pkg/updater/updater.go | 27 +- oracle/pkg/updater/updater_test.go | 8 +- p2p/pkg/preconfirmation/store/export_test.go | 5 +- p2p/pkg/preconfirmation/store/store.go | 205 ++++++++------ p2p/pkg/preconfirmation/store/store_test.go | 275 ++++++++++++++++--- p2p/pkg/preconfirmation/tracker/tracker.go | 195 ++++++++----- 6 files changed, 487 insertions(+), 228 deletions(-) diff --git a/oracle/pkg/updater/updater.go b/oracle/pkg/updater/updater.go index 7af116382..04eb4d370 100644 --- a/oracle/pkg/updater/updater.go +++ b/oracle/pkg/updater/updater.go @@ -9,7 +9,6 @@ import ( "math/big" "strings" "sync" - "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" @@ -17,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/log" lru "github.com/hashicorp/golang-lru/v2" "github.com/lib/pq" - blocktracker "github.com/primev/mev-commit/contracts-abi/clients/BlockTracker" preconf "github.com/primev/mev-commit/contracts-abi/clients/PreconfManager" "github.com/primev/mev-commit/x/contracts/events" "github.com/primev/mev-commit/x/contracts/txmonitor" @@ -111,7 +109,6 @@ type Updater struct { l1BlockCache *lru.Cache[uint64, map[string]TxMetadata] unopenedCmts chan *preconf.PreconfmanagerUnopenedCommitmentStored openedCmts chan *preconf.PreconfmanagerOpenedCommitmentStored - currentWindow atomic.Int64 metrics *metrics receiptBatcher txmonitor.BatchReceiptGetter } @@ -171,14 +168,7 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { }, ) - ev3 := events.NewEventHandler( - "NewWindow", - func(update *blocktracker.BlocktrackerNewWindow) { - u.currentWindow.Store(update.Window.Int64()) - }, - ) - - sub, err := u.evtMgr.Subscribe(ev1, ev2, ev3) + sub, err := u.evtMgr.Subscribe(ev1, ev2) if err != nil { u.logger.Error("failed to subscribe to events", "error", err) close(doneChan) @@ -311,18 +301,6 @@ func (u *Updater) handleOpenedCommitment( return err } - if u.currentWindow.Load() > 2 && winner.Window < u.currentWindow.Load()-2 { - u.logger.Info( - "commitment is too old", - "commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]), - "winner", winner.Winner, - "window", winner.Window, - "currentWindow", u.currentWindow.Load(), - ) - u.metrics.CommitmentsTooOldCount.Inc() - return nil - } - if common.BytesToAddress(winner.Winner).Cmp(update.Committer) != 0 { // The winner is not the committer of the commitment u.logger.Info( @@ -365,7 +343,8 @@ func (u *Updater) handleOpenedCommitment( // Ensure Bundle is atomic and present in the block for i := 0; i < len(commitmentTxnHashes); i++ { txnDetails, found := txns[commitmentTxnHashes[i]] - if !found || txnDetails.PosInBlock != (txns[commitmentTxnHashes[0]].PosInBlock)+i || (!txnDetails.Succeeded && !revertableTxnsMap[commitmentTxnHashes[i]]) { + if !found || txnDetails.PosInBlock != (txns[commitmentTxnHashes[0]].PosInBlock)+i || + (!txnDetails.Succeeded && !revertableTxnsMap[commitmentTxnHashes[i]]) { u.logger.Info( "bundle does not satisfy committed requirements", "commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]), diff --git a/oracle/pkg/updater/updater_test.go b/oracle/pkg/updater/updater_test.go index cff14edfb..b6f76177a 100644 --- a/oracle/pkg/updater/updater_test.go +++ b/oracle/pkg/updater/updater_test.go @@ -1223,7 +1223,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { t.Fatal(err) } - if i < 8 { + if i > 5 && i < 8 { continue } @@ -1239,7 +1239,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { if !bytes.Equal(commitment.commitmentIdx[:], c.CommitmentIndex[:]) { t.Fatal("wrong commitment index") } - if commitment.blockNum.Cmp(big.NewInt(10)) != 0 { + if commitment.blockNum.Cmp(big.NewInt(10)) != 0 && commitment.blockNum.Cmp(big.NewInt(5)) != 0 { t.Fatal("wrong block number", commitment.blockNum) } if commitment.builder != c.Committer { @@ -1263,7 +1263,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { if settlement.txHash != c.TxnHash { t.Fatal("wrong txn hash") } - if settlement.blockNum != 10 { + if settlement.blockNum != 10 && settlement.blockNum != 5 { t.Fatal("wrong block number") } if !bytes.Equal(settlement.builder, c.Committer.Bytes()) { @@ -1278,7 +1278,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { if settlement.decayPercentage != 50*updater.PRECISION { t.Fatal("wrong decay percentage") } - if settlement.window != 5 { + if settlement.window != 5 && settlement.window != 1 { t.Fatal("wrong window") } } diff --git a/p2p/pkg/preconfirmation/store/export_test.go b/p2p/pkg/preconfirmation/store/export_test.go index 9cdabdf02..b6ee351e6 100644 --- a/p2p/pkg/preconfirmation/store/export_test.go +++ b/p2p/pkg/preconfirmation/store/export_test.go @@ -1,3 +1,6 @@ package store -var CmtIndexNS = cmtIndexNS +var ( + CmtIndexNS = cmtIndexNS + IndexToDigestNS = indexToDigestNS +) diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index 86c9fe0d9..53898deea 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "math/big" + "strconv" + "strings" "sync" "github.com/ethereum/go-ethereum/common" @@ -38,6 +40,17 @@ var ( return fmt.Sprintf("%s%d/%s/%s", commitmentNS, blockNum, paddedBidAmountHex, string(index)) } + parseBlockNumFromCommitmentKey = func(key string) (int64, error) { + splits := strings.Split(key, "/") + if len(splits) != 4 || strings.HasPrefix(commitmentNS, splits[0]) == false { + return 0, fmt.Errorf("invalid commitment key format: %s", key) + } + blockNum, err := strconv.Atoi(splits[1]) + if err != nil { + return 0, fmt.Errorf("failed to parse block number from key %s: %w", key, err) + } + return int64(blockNum), nil + } blockCommitmentPrefix = func(blockNum int64) string { return fmt.Sprintf("%s%d", commitmentNS, blockNum) } @@ -57,15 +70,22 @@ type Store struct { st storage.Storage } +type CommitmentStatus string + +const ( + CommitmentStatusPending CommitmentStatus = "pending" + CommitmentStatusStored CommitmentStatus = "stored" + CommitmentStatusOpened CommitmentStatus = "opened" + CommitmentStatusSettled CommitmentStatus = "settled" + CommitmentStatusSlashed CommitmentStatus = "slashed" + CommitmentStatusFailed CommitmentStatus = "failed" +) + type Commitment struct { *preconfpb.EncryptedPreConfirmation *preconfpb.PreConfirmation - TxnHash common.Hash - Nonce uint64 - Status string - Opened bool - Settled bool - IsSlash bool + Status CommitmentStatus + Details string Payment string Refund string } @@ -131,7 +151,13 @@ func (s *Store) AddCommitment(commitment *Commitment) (err error) { return writer.Put(cIndexKey, cIndexValueBuf) } -func (s *Store) SetStatus(blockNumber int64, bidAmt string, cDigest []byte, status string) error { +func (s *Store) SetStatus( + blockNumber int64, + bidAmt string, + cDigest []byte, + status CommitmentStatus, + details string, +) error { s.mu.Lock() defer s.mu.Unlock() @@ -151,6 +177,7 @@ func (s *Store) SetStatus(blockNumber int64, bidAmt string, cDigest []byte, stat } commitment.Status = status + commitment.Details = details buf, err := msgpack.Marshal(commitment) if err != nil { @@ -182,65 +209,26 @@ func (s *Store) GetCommitments(blockNum int64) ([]*Commitment, error) { return commitments, nil } -func (s *Store) ClearBlockNumber(blockNum int64) error { - s.mu.Lock() - defer s.mu.Unlock() - - err := s.st.DeletePrefix(blockCommitmentPrefix(blockNum)) - if err != nil { - return err - } - - return s.st.Delete(blockWinnerKey(blockNum)) -} - -func (s *Store) DeleteCommitmentByDigest(blockNum int64, bidAmt string, digest [32]byte) error { - s.mu.Lock() - defer s.mu.Unlock() - - return s.st.Delete(commitmentKey(blockNum, bidAmt, digest[:])) -} - func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) (retErr error) { - s.mu.RLock() - cIndexValueBuf, err := s.st.Get(cmtIndexKey(cDigest[:])) - s.mu.RUnlock() - switch { - case errors.Is(err, storage.ErrKeyNotFound): - // this would happen for most of the commitments as the node only - // stores the commitments it is involved in. - return nil - case err != nil: - return err - } - - s.mu.Lock() - defer s.mu.Unlock() - - var cIndexValue CommitmentIndexValue - err = msgpack.Unmarshal(cIndexValueBuf, &cIndexValue) - if err != nil { - return err - } - - commitmentKey := commitmentKey(cIndexValue.BlockNumber, cIndexValue.BidAmount, cDigest[:]) - cmtBuf, err := s.st.Get(commitmentKey) - if err != nil { - return err - } - - cmt := new(Commitment) - err = msgpack.Unmarshal(cmtBuf, cmt) + cmt, err := s.GetCommitmentByDigest(cDigest[:]) if err != nil { + if errors.Is(err, storage.ErrKeyNotFound) { + return nil + } return err } cmt.CommitmentIndex = cIndex[:] + if cmt.Status == CommitmentStatusPending { + cmt.Status = CommitmentStatusStored + } buf, err := msgpack.Marshal(cmt) if err != nil { return err } + commitmentKey := commitmentKey(cmt.Bid.BlockNumber, cmt.Bid.BidAmount, cmt.Commitment) + var writer storage.Writer if w, ok := s.st.(storage.Batcher); ok { batch := w.Batch() @@ -288,8 +276,11 @@ func (s *Store) UpdateSettlement(index []byte, isSlash bool) error { return err } - cmt.Settled = true - cmt.IsSlash = isSlash + if isSlash { + cmt.Status = CommitmentStatusSlashed + } else { + cmt.Status = CommitmentStatusSettled + } buf, err := msgpack.Marshal(cmt) if err != nil { @@ -300,15 +291,17 @@ func (s *Store) UpdateSettlement(index []byte, isSlash bool) error { } func (s *Store) UpdatePayment(digest []byte, payment, refund string) error { - s.mu.Lock() - defer s.mu.Unlock() - - cmt := new(Commitment) - err = msgpack.Unmarshal(cmtBuf, cmt) + cmt, err := s.GetCommitmentByDigest(digest) if err != nil { + if errors.Is(err, storage.ErrKeyNotFound) { + return nil + } return err } + s.mu.Lock() + defer s.mu.Unlock() + cmt.Payment = payment cmt.Refund = refund @@ -317,74 +310,101 @@ func (s *Store) UpdatePayment(digest []byte, payment, refund string) error { return err } + commitmentKey := commitmentKey(cmt.Bid.BlockNumber, cmt.Bid.BidAmount, cmt.Commitment) + return s.st.Put(string(commitmentKey), buf) } -func (s *Store) GetCommitmentByIndex(index []byte) (*Commitment, error) { +func (s *Store) GetCommitmentByDigest(digest []byte) (*Commitment, error) { s.mu.RLock() defer s.mu.RUnlock() - key := indexToDigestKey(index) - commitmentKey, err := s.st.Get(key) + cIndexValueBuf, err := s.st.Get(cmtIndexKey(digest)) if err != nil { return nil, err } - cmtBuf, err := s.st.Get(string(commitmentKey)) + var cIndexValue CommitmentIndexValue + err = msgpack.Unmarshal(cIndexValueBuf, &cIndexValue) if err != nil { return nil, err } - cmt := new(Commitment) - err = msgpack.Unmarshal(cmtBuf, cmt) + commitmentKey := commitmentKey(cIndexValue.BlockNumber, cIndexValue.BidAmount, digest) + cmtBuf, err := s.st.Get(commitmentKey) if err != nil { return nil, err } - return cmt, nil -} - -func (s *Store) UpdateCommitment(cmt *Commitment) error { - s.mu.Lock() - defer s.mu.Unlock() - - key := commitmentKey(cmt.Bid.BlockNumber, cmt.Bid.BidAmount, cmt.Commitment) - - buf, err := msgpack.Marshal(cmt) + cmt := new(Commitment) + err = msgpack.Unmarshal(cmtBuf, cmt) if err != nil { - return err + return nil, err } - return s.st.Put(key, buf) + return cmt, nil } func (s *Store) ClearCommitmentIndexes(uptoBlock int64) error { keys := make([]string, 0) s.mu.RLock() - err := s.st.WalkPrefix(cmtIndexNS, func(key string, val []byte) bool { - var cIndexValue CommitmentIndexValue - err := msgpack.Unmarshal(val, &cIndexValue) + err := s.st.WalkPrefix(commitmentNS, func(key string, val []byte) bool { + blockNum, err := parseBlockNumFromCommitmentKey(key) if err != nil { - // If unmarshaling fails, we might have corrupted data; skip this key + // If parsing fails, we might have corrupted data; discard this key + keys = append(keys, key) return false } - if cIndexValue.BlockNumber < uptoBlock { + if blockNum < uptoBlock { + var commitment Commitment + err := msgpack.Unmarshal(val, &commitment) + if err != nil { + // If unmarshaling fails, we might have corrupted data; skip this key + return false + } keys = append(keys, key) + keys = append(keys, cmtIndexKey(commitment.Commitment)) + if commitment.CommitmentIndex != nil { + keys = append(keys, indexToDigestKey(commitment.CommitmentIndex)) + } + return false + } else { + // DB is expected to be sorted by block number, so we can stop here + // since all subsequent keys will also be greater than or equal to `uptoBlock`. + return true } - return false }) s.mu.RUnlock() if err != nil { return err } + var ( + writer storage.Writer + writeErr error + ) + if w, ok := s.st.(storage.Batcher); ok { + batch := w.Batch() + writer = batch + defer func() { + switch { + case writeErr != nil: + batch.Reset() + case err == nil: + writeErr = batch.Write() + } + }() + } else { + writer = s.st + } + s.mu.Lock() defer s.mu.Unlock() for _, key := range keys { - err := s.st.Delete(key) - if err != nil { - return err + writeErr = writer.Delete(key) + if writeErr != nil { + return writeErr } } @@ -422,3 +442,10 @@ func (s *Store) BlockWinners() ([]*BlockWinner, error) { } return winners, nil } + +func (s *Store) ClearBlockNumber(blockNum int64) error { + s.mu.Lock() + defer s.mu.Unlock() + + return s.st.Delete(blockWinnerKey(blockNum)) +} diff --git a/p2p/pkg/preconfirmation/store/store_test.go b/p2p/pkg/preconfirmation/store/store_test.go index 36a4e9700..19f277c5d 100644 --- a/p2p/pkg/preconfirmation/store/store_test.go +++ b/p2p/pkg/preconfirmation/store/store_test.go @@ -7,12 +7,13 @@ import ( "github.com/ethereum/go-ethereum/common" preconfpb "github.com/primev/mev-commit/p2p/gen/go/preconfirmation/v1" "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" + "github.com/primev/mev-commit/p2p/pkg/storage" inmem "github.com/primev/mev-commit/p2p/pkg/storage/inmem" ) func TestStore_AddCommitment(t *testing.T) { st := store.New(inmem.New()) - commitment := &store.EncryptedPreConfirmationWithDecrypted{ + commitment := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: []byte("commitment"), }, @@ -44,7 +45,7 @@ func TestStore_AddCommitment(t *testing.T) { func TestStore_ClearBlockNumber(t *testing.T) { st := store.New(inmem.New()) - commitment := &store.EncryptedPreConfirmationWithDecrypted{ + commitment := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: []byte("commitment"), }, @@ -77,9 +78,13 @@ func TestStore_ClearBlockNumber(t *testing.T) { func TestStore_ClearCommitmentIndex(t *testing.T) { inmemstore := inmem.New() st := store.New(inmemstore) - commitment := &store.EncryptedPreConfirmationWithDecrypted{ + + digest := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") + index := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef") + + commitment := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ - Commitment: []byte("commitment"), + Commitment: digest[:], }, PreConfirmation: &preconfpb.PreConfirmation{ Bid: &preconfpb.Bid{ @@ -93,6 +98,11 @@ func TestStore_ClearCommitmentIndex(t *testing.T) { t.Fatal(err) } + err = st.SetCommitmentIndexByDigest(digest, index) + if err != nil { + t.Fatal(err) + } + err = st.ClearCommitmentIndexes(2) if err != nil { t.Fatal(err) @@ -106,45 +116,27 @@ func TestStore_ClearCommitmentIndex(t *testing.T) { if err != nil { t.Fatal(err) } - if entries != 0 { t.Fatalf("expected 0 entries, got %d", entries) } -} -func TestStore_DeleteCommitmentByDigest(t *testing.T) { - st := store.New(inmem.New()) - digest := [32]byte{} - copy(digest[:], []byte("commitment")) - - commitment := &store.EncryptedPreConfirmationWithDecrypted{ - EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ - Commitment: digest[:], - }, - PreConfirmation: &preconfpb.PreConfirmation{ - Bid: &preconfpb.Bid{ - BlockNumber: 1, - BidAmount: "100", - }, - }, - } - err := st.AddCommitment(commitment) + commitments, err := st.GetCommitments(1) if err != nil { t.Fatal(err) } - - err = st.DeleteCommitmentByDigest(1, commitment.Bid.BidAmount, digest) - if err != nil { - t.Fatal(err) + if len(commitments) != 0 { + t.Fatalf("expected 0 commitments, got %d", len(commitments)) } - commitments, err := st.GetCommitments(1) + err = inmemstore.WalkPrefix(store.IndexToDigestNS, func(_ string, _ []byte) bool { + entries++ + return false + }) if err != nil { t.Fatal(err) } - - if len(commitments) != 0 { - t.Fatalf("expected 0 commitments, got %d", len(commitments)) + if entries != 0 { + t.Fatalf("expected 0 entries, got %d", entries) } } @@ -155,7 +147,7 @@ func TestStore_SetCommitmentIndexByDigest(t *testing.T) { index := [32]byte{} copy(index[:], []byte("index")) - commitment := &store.EncryptedPreConfirmationWithDecrypted{ + commitment := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: digest[:], }, @@ -222,7 +214,7 @@ func TestStore_AddWinner(t *testing.T) { func TestStore_GetCommitments_Order(t *testing.T) { st := store.New(inmem.New()) - commitment1 := &store.EncryptedPreConfirmationWithDecrypted{ + commitment1 := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: []byte("commitment1"), }, @@ -233,7 +225,7 @@ func TestStore_GetCommitments_Order(t *testing.T) { }, }, } - commitment2 := &store.EncryptedPreConfirmationWithDecrypted{ + commitment2 := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: []byte("commitment2"), }, @@ -244,7 +236,7 @@ func TestStore_GetCommitments_Order(t *testing.T) { }, }, } - commitment3 := &store.EncryptedPreConfirmationWithDecrypted{ + commitment3 := &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: []byte("commitment3"), }, @@ -286,3 +278,216 @@ func TestStore_GetCommitments_Order(t *testing.T) { } } } + +func TestStore_GetCommitmentByDigest(t *testing.T) { + st := store.New(inmem.New()) + digest := [32]byte{} + copy(digest[:], []byte("commitment")) + + commitment := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: digest[:], + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 1, + BidAmount: "100", + }, + }, + } + err := st.AddCommitment(commitment) + if err != nil { + t.Fatal(err) + } + + foundCommitment, err := st.GetCommitmentByDigest(digest[:]) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(foundCommitment.Commitment, digest[:]) { + t.Fatalf("expected commitment %x, got %x", digest, foundCommitment.Commitment) + } +} + +func TestStore_GetCommitmentByDigest_NotFound(t *testing.T) { + st := store.New(inmem.New()) + digest := [32]byte{} + copy(digest[:], []byte("nonexistent")) + + _, err := st.GetCommitmentByDigest(digest[:]) + if err == nil { + t.Fatal("expected error, got nil") + } + + expectedErr := storage.ErrKeyNotFound + if err != expectedErr { + t.Fatalf("expected error %v, got %v", expectedErr, err) + } +} + +func TestStore_SetStatus(t *testing.T) { + st := store.New(inmem.New()) + digest := [32]byte{} + copy(digest[:], []byte("commitment")) + + commitment := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: digest[:], + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 1, + BidAmount: "100", + }, + }, + } + err := st.AddCommitment(commitment) + if err != nil { + t.Fatal(err) + } + + err = st.SetStatus(1, "100", digest[:], store.CommitmentStatusOpened, "details") + if err != nil { + t.Fatal(err) + } + + foundCommitment, err := st.GetCommitmentByDigest(digest[:]) + if err != nil { + t.Fatal(err) + } + + if foundCommitment.Status != store.CommitmentStatusOpened { + t.Fatalf("expected status %s, got %s", store.CommitmentStatusOpened, foundCommitment.Status) + } + if foundCommitment.Details != "details" { + t.Fatalf("expected details 'details', got '%s'", foundCommitment.Details) + } +} + +func TestStore_UpdateSettlementSettled(t *testing.T) { + st := store.New(inmem.New()) + digest := [32]byte{} + copy(digest[:], []byte("commitment")) + + index := [32]byte{} + copy(index[:], []byte("index")) + + commitment := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: digest[:], + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 1, + BidAmount: "100", + }, + }, + } + err := st.AddCommitment(commitment) + if err != nil { + t.Fatal(err) + } + + err = st.SetCommitmentIndexByDigest(digest, index) + if err != nil { + t.Fatal(err) + } + + err = st.UpdateSettlement(index[:], false) + if err != nil { + t.Fatal(err) + } + + foundCommitment, err := st.GetCommitmentByDigest(digest[:]) + if err != nil { + t.Fatal(err) + } + + if foundCommitment.Status != store.CommitmentStatusSettled { + t.Fatalf("expected settlement status %s, got %s", store.CommitmentStatusSettled, foundCommitment.Status) + } +} + +func TestStore_UpdateSettlementSlashed(t *testing.T) { + st := store.New(inmem.New()) + digest := [32]byte{} + copy(digest[:], []byte("commitment")) + + index := [32]byte{} + copy(index[:], []byte("index")) + + commitment := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: digest[:], + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 1, + BidAmount: "100", + }, + }, + } + err := st.AddCommitment(commitment) + if err != nil { + t.Fatal(err) + } + + err = st.SetCommitmentIndexByDigest(digest, index) + if err != nil { + t.Fatal(err) + } + + err = st.UpdateSettlement(index[:], true) + if err != nil { + t.Fatal(err) + } + + foundCommitment, err := st.GetCommitmentByDigest(digest[:]) + if err != nil { + t.Fatal(err) + } + + if foundCommitment.Status != store.CommitmentStatusSlashed { + t.Fatalf("expected settlement status %s, got %s", store.CommitmentStatusSlashed, foundCommitment.Status) + } +} + +func TestStore_UpdatePayment(t *testing.T) { + st := store.New(inmem.New()) + digest := [32]byte{} + copy(digest[:], []byte("commitment")) + + commitment := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: digest[:], + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 1, + BidAmount: "100", + }, + }, + } + err := st.AddCommitment(commitment) + if err != nil { + t.Fatal(err) + } + + err = st.UpdatePayment(digest[:], "80", "20") + if err != nil { + t.Fatal(err) + } + + foundCommitment, err := st.GetCommitmentByDigest(digest[:]) + if err != nil { + t.Fatal(err) + } + + if foundCommitment.Payment != "80" { + t.Fatalf("expected payment '80', got '%s'", foundCommitment.Payment) + } + if foundCommitment.Refund != "20" { + t.Fatalf("expected refund '20', got '%s'", foundCommitment.Refund) + } +} diff --git a/p2p/pkg/preconfirmation/tracker/tracker.go b/p2p/pkg/preconfirmation/tracker/tracker.go index 022f31e4f..fd2fcb597 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker.go +++ b/p2p/pkg/preconfirmation/tracker/tracker.go @@ -3,10 +3,10 @@ package preconftracker import ( "context" "encoding/hex" + "errors" "fmt" "log/slog" "math/big" - "slices" "time" "github.com/consensys/gnark-crypto/ecc/bn254" @@ -21,15 +21,14 @@ import ( "github.com/primev/mev-commit/p2p/pkg/crypto" "github.com/primev/mev-commit/p2p/pkg/p2p" "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" + "github.com/primev/mev-commit/p2p/pkg/storage" "github.com/primev/mev-commit/x/contracts/events" "github.com/primev/mev-commit/x/contracts/txmonitor" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sync/errgroup" ) -const ( - allowedDelayToOpenCommitment = 10 -) +const blockHistoryLimit = 10000 type Tracker struct { ctxChainIDData []byte @@ -40,16 +39,15 @@ type Tracker struct { preconfContract PreconfContract providerNikePK *bn254.G1Affine providerNikeSK *fr.Element - receiptGetter txmonitor.BatchReceiptGetter optsGetter OptsGetter watcher Watcher newL1Blocks chan *blocktracker.BlocktrackerNewL1Block unopenedCmts chan *preconfcommstore.PreconfmanagerUnopenedCommitmentStored commitments chan *preconfcommstore.PreconfmanagerOpenedCommitmentStored - statusUpdate chan statusUpdateTask processed chan *oracle.OracleCommitmentProcessed rewards chan *bidderregistry.BidderregistryFundsRewarded returns chan *bidderregistry.BidderregistryFundsRetrieved + statusUpdate chan statusUpdateTask triggerOpen chan struct{} metrics *metrics logger *slog.Logger @@ -60,12 +58,6 @@ type OptsGetter func(context.Context) (*bind.TransactOpts, error) type CommitmentStore interface { GetCommitments(blockNum int64) ([]*store.Commitment, error) AddCommitment(commitment *store.Commitment) error - ClearBlockNumber(blockNum int64) error - DeleteCommitmentByDigest( - blockNum int64, - bidAmt string, - digest [32]byte, - ) error SetCommitmentIndexByDigest( commitmentDigest, commitmentIndex [32]byte, @@ -74,16 +66,16 @@ type CommitmentStore interface { blockNumber int64, bidAmt string, commitmentDigest []byte, - status string, + status store.CommitmentStatus, + details string, ) error - GetCommitmentByIndex(index []byte) (*store.Commitment, error) GetCommitmentByDigest(digest []byte) (*store.Commitment, error) - UpdateCommitment(cmt *store.Commitment) error UpdateSettlement(index []byte, isSlash bool) error UpdatePayment(digest []byte, payment, refund string) error ClearCommitmentIndexes(upto int64) error AddWinner(winner *store.BlockWinner) error BlockWinners() ([]*store.BlockWinner, error) + ClearBlockNumber(blockNum int64) error } type PreconfContract interface { @@ -104,7 +96,6 @@ func NewTracker( evtMgr events.EventManager, store CommitmentStore, preconfContract PreconfContract, - receiptGetter txmonitor.BatchReceiptGetter, providerNikePublicKey *bn254.G1Affine, providerNikeSecretKey *fr.Element, optsGetter OptsGetter, @@ -117,13 +108,16 @@ func NewTracker( evtMgr: evtMgr, store: store, preconfContract: preconfContract, - receiptGetter: receiptGetter, optsGetter: optsGetter, providerNikePK: providerNikePublicKey, providerNikeSK: providerNikeSecretKey, newL1Blocks: make(chan *blocktracker.BlocktrackerNewL1Block), unopenedCmts: make(chan *preconfcommstore.PreconfmanagerUnopenedCommitmentStored), commitments: make(chan *preconfcommstore.PreconfmanagerOpenedCommitmentStored), + processed: make(chan *oracle.OracleCommitmentProcessed), + rewards: make(chan *bidderregistry.BidderregistryFundsRewarded), + returns: make(chan *bidderregistry.BidderregistryFundsRetrieved), + statusUpdate: make(chan statusUpdateTask), triggerOpen: make(chan struct{}), metrics: newMetrics(), logger: logger, @@ -138,6 +132,7 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { evts := []events.EventHandler{ events.NewChannelEventHandler(egCtx, "NewL1Block", t.newL1Blocks), events.NewChannelEventHandler(egCtx, "UnopenedCommitmentStored", t.unopenedCmts), + events.NewChannelEventHandler(egCtx, "OpenedCommitmentStored", t.commitments), events.NewChannelEventHandler(egCtx, "CommitmentProcessed", t.processed), events.NewChannelEventHandler(egCtx, "FundsRewarded", t.rewards), } @@ -145,7 +140,6 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { if t.peerType == p2p.PeerTypeBidder { evts = append( evts, - events.NewChannelEventHandler(egCtx, "OpenedCommitmentStored", t.commitments), events.NewChannelEventHandler(egCtx, "FundsRetrieved", t.returns), ) } @@ -218,23 +212,6 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { continue } t.logger.Debug("stored block winners", "count", len(winners)) - oldBlockNos := make([]int64, 0) - winners = slices.DeleteFunc(winners, func(item *store.BlockWinner) bool { - // the last block is the latest, so if any of the previous blocks are - // older than the allowed delay, we should not open the commitments - if winners[len(winners)-1].BlockNumber-item.BlockNumber > allowedDelayToOpenCommitment { - oldBlockNos = append(oldBlockNos, item.BlockNumber) - return true - } - return false - }) - // cleanup old state - for _, oldBlockNo := range oldBlockNos { - if err := t.store.ClearBlockNumber(oldBlockNo); err != nil { - t.logger.Error("failed to delete commitments by block number", "blockNumber", oldBlockNo, "error", err) - } - t.logger.Info("old block commitments deleted", "blockNumber", oldBlockNo) - } if t.peerType == p2p.PeerTypeBidder { if len(winners) > 2 { // Bidders should process the block 2 behind the current one. Ideally the @@ -293,27 +270,28 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { } }) + eg.Go(func() error { + for { + select { + case <-egCtx.Done(): + t.logger.Info("handleCommitmentStored context done") + return nil + case err := <-sub.Err(): + return fmt.Errorf("event subscription error: %w", err) + case cs := <-t.commitments: + if err := t.handleOpenedCommitmentStored(egCtx, cs); err != nil { + t.logger.Error("failed to handle opened commitment stored", "error", err) + continue + } + } + } + }) + eg.Go(func() error { return t.clearCommitments(egCtx) }) if t.peerType == p2p.PeerTypeBidder { - eg.Go(func() error { - for { - select { - case <-egCtx.Done(): - t.logger.Info("handleCommitmentStored context done") - return nil - case err := <-sub.Err(): - return fmt.Errorf("event subscription error: %w", err) - case cs := <-t.commitments: - if err := t.handleOpenedCommitmentStored(egCtx, cs); err != nil { - t.logger.Error("failed to handle opened commitment stored", "error", err) - continue - } - } - } - }) eg.Go(func() error { for { select { @@ -345,22 +323,24 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { func (t *Tracker) TrackCommitment( ctx context.Context, commitment *store.Commitment, + txn *types.Transaction, ) error { + commitment.Status = store.CommitmentStatusPending + if err := t.store.AddCommitment(commitment); err != nil { t.logger.Error("failed to add commitment", "error", err) return err } - if commitment.TxnHash != (common.Hash{}) { + if txn != nil { select { case <-ctx.Done(): return ctx.Err() case t.statusUpdate <- statusUpdateTask{ commitment: commitment, - txnHash: commitment.TxnHash, - nonce: commitment.Nonce, - onSuccess: "Unopened commitment stored", - onError: "Failed to store unopened commitment", + txnHash: txn.Hash(), + nonce: txn.Nonce(), + onSuccess: store.CommitmentStatusStored, }: } } @@ -400,8 +380,7 @@ type statusUpdateTask struct { commitment *store.Commitment txnHash common.Hash nonce uint64 - onSuccess string - onError string + onSuccess store.CommitmentStatus } func (t *Tracker) statusUpdater( @@ -422,19 +401,39 @@ func (t *Tracker) statusUpdater( t.logger.Info("watcher context done") return ctx.Err() case r := <-res: - var status string - if r.Err != nil { - status = fmt.Sprintf("%s: %s", task.onError, r.Err) - t.logger.Error("txn failure on chain", "error", r.Err) - } else { - status = task.onSuccess - t.logger.Debug("status updated on chain", "hash", task.txnHash, "status", r.Receipt.Status) + var ( + status store.CommitmentStatus + details string + ) + switch task.onSuccess { + case store.CommitmentStatusStored: + if r.Err != nil { + status = store.CommitmentStatusFailed + details = fmt.Sprintf("failed to store commitment: %s", r.Err) + } else { + status = store.CommitmentStatusStored + } + case store.CommitmentStatusOpened: + if r.Err != nil { + status = store.CommitmentStatusFailed + details = fmt.Sprintf("failed to open commitment: %s", r.Err) + } else { + status = store.CommitmentStatusOpened + details = fmt.Sprintf("opened by %s", t.peerType) + } } + t.logger.Info( + "commitment status update", + "commitmentDigest", hex.EncodeToString(task.commitment.Commitment[:]), + "status", status, + "details", details, + ) if err := t.store.SetStatus( task.commitment.Bid.BlockNumber, task.commitment.Bid.BidAmount, task.commitment.Commitment, status, + details, ); err != nil { t.logger.Error("failed to set status", "error", err) } @@ -457,13 +456,24 @@ func (t *Tracker) openCommitments( return err } - settled := 0 - failed := 0 + var settled, failed, alreadyOpened int = 0, 0, 0 + for _, commitment := range commitments { - if commitment.CommitmentIndex == nil { - t.logger.Debug("commitment index not found", "commitment", commitment) + switch commitment.Status { + case store.CommitmentStatusPending, store.CommitmentStatusFailed: + t.logger.Debug("commitment cannot be opened", "commitment", commitment) failed++ continue + case store.CommitmentStatusOpened, store.CommitmentStatusSettled, store.CommitmentStatusSlashed: + t.logger.Debug("commitment already opened", "commitment", commitment) + alreadyOpened++ + continue + default: + if commitment.CommitmentIndex == nil { + t.logger.Debug("commitment index not found", "commitment", commitment) + failed++ + continue + } } if common.BytesToAddress(commitment.ProviderAddress).Cmp(newL1Block.Winner) != 0 { t.logger.Debug( @@ -536,8 +546,7 @@ func (t *Tracker) openCommitments( commitment: commitment, txnHash: txn.Hash(), nonce: txn.Nonce(), - onSuccess: "Opened commitment", - onError: "Failed to open commitment", + onSuccess: store.CommitmentStatusOpened, }: } } @@ -554,6 +563,7 @@ func (t *Tracker) openCommitments( "total", len(commitments), "settled", settled, "failed", failed, + "alreadyOpened", alreadyOpened, "duration", openDuration, ) @@ -583,8 +593,18 @@ func (t *Tracker) clearCommitments(ctx context.Context) error { continue } + var clearBlockNumber int64 = 0 + if winners[0].BlockNumber > blockHistoryLimit { + clearBlockNumber = winners[0].BlockNumber - blockHistoryLimit + } + + if clearBlockNumber == 0 { + t.logger.Debug("no block numbers to clear") + continue + } + // clear commitment indexes for all the blocks before the oldest winner - err = t.store.ClearCommitmentIndexes(winners[0].BlockNumber) + err = t.store.ClearCommitmentIndexes(clearBlockNumber) if err != nil { t.logger.Error( "failed to clear commitment indexes", @@ -610,9 +630,34 @@ func (t *Tracker) handleOpenedCommitmentStored( ctx context.Context, cs *preconfcommstore.PreconfmanagerOpenedCommitmentStored, ) error { - // In case of bidders this event keeps track of the commitments already opened - // by the provider. - return t.store.DeleteCommitmentByDigest(int64(cs.BlockNumber), cs.BidAmt.String(), cs.CommitmentDigest) + cmt, err := t.store.GetCommitmentByDigest(cs.CommitmentDigest[:]) + if err != nil { + if errors.Is(err, storage.ErrKeyNotFound) { + return nil + } + return fmt.Errorf("failed to get commitment by digest: %w", err) + } + + if cmt.Status != store.CommitmentStatusOpened { + var details string + switch t.peerType { + case p2p.PeerTypeBidder: + details = fmt.Sprintf("opened by %s", p2p.PeerTypeProvider) + case p2p.PeerTypeProvider: + details = fmt.Sprintf("opened by %s", p2p.PeerTypeBidder) + } + if err := t.store.SetStatus( + cmt.Bid.BlockNumber, + cmt.Bid.BidAmount, + cs.CommitmentDigest[:], + store.CommitmentStatusOpened, + details, + ); err != nil { + return fmt.Errorf("failed to set status: %w", err) + } + } + + return nil } func (t *Tracker) generateZKProof( From 11b041a3d74e1782a0a9b6f20bee9122a5e9766e Mon Sep 17 00:00:00 2001 From: Alok Nerurkar Date: Mon, 26 May 2025 13:52:47 +0530 Subject: [PATCH 04/14] fix: tracker update with tests --- p2p/pkg/node/node.go | 3 +- p2p/pkg/notifications/notifications.go | 23 +- p2p/pkg/preconfirmation/preconfirmation.go | 11 +- .../preconfirmation/preconfirmation_test.go | 6 +- p2p/pkg/preconfirmation/store/store.go | 20 ++ p2p/pkg/preconfirmation/store/store_test.go | 45 +++ p2p/pkg/preconfirmation/tracker/tracker.go | 93 +++-- .../preconfirmation/tracker/tracker_test.go | 338 +++++++++++++----- 8 files changed, 410 insertions(+), 129 deletions(-) diff --git a/p2p/pkg/node/node.go b/p2p/pkg/node/node.go index 13f7abad1..cd656c067 100644 --- a/p2p/pkg/node/node.go +++ b/p2p/pkg/node/node.go @@ -477,7 +477,8 @@ func NewNode(opts *Options) (*Node, error) { evtMgr, preconfstore.New(store), commitmentDA, - txmonitor.NewEVMHelperWithLogger(contractRPC, opts.Logger.With("component", "evm_helper"), contracts), + monitor, + notificationsSvc, pk, sk, optsGetter, diff --git a/p2p/pkg/notifications/notifications.go b/p2p/pkg/notifications/notifications.go index 15d89c7b5..023be5c16 100644 --- a/p2p/pkg/notifications/notifications.go +++ b/p2p/pkg/notifications/notifications.go @@ -15,15 +15,26 @@ const ( TopicProviderDeposit Topic = "provider_deposit" TopicProviderSlashed Topic = "provider_slashed" TopicProviderDeregistered Topic = "provider_deregistered" + TopicCommitmentStoreFailed Topic = "commitment_store_failed" + TopicCommitmentOpenFailed Topic = "commitment_open_failed" ) +var validTopic = map[Topic]struct{}{ + TopicPeerConnected: {}, + TopicPeerDisconnected: {}, + TopicValidatorOptedIn: {}, + TopicEpochValidatorsOptedIn: {}, + TopicProviderRegistered: {}, + TopicProviderDeposit: {}, + TopicProviderSlashed: {}, + TopicProviderDeregistered: {}, + TopicCommitmentStoreFailed: {}, + TopicCommitmentOpenFailed: {}, +} + func IsTopicValid(topic Topic) bool { - switch topic { - case TopicPeerConnected, TopicPeerDisconnected, TopicValidatorOptedIn, TopicEpochValidatorsOptedIn: - return true - default: - return false - } + _, ok := validTopic[topic] + return ok } // Notification is a struct that represents a notification. It has a Topic field diff --git a/p2p/pkg/preconfirmation/preconfirmation.go b/p2p/pkg/preconfirmation/preconfirmation.go index 7b6f66710..04a35b8d6 100644 --- a/p2p/pkg/preconfirmation/preconfirmation.go +++ b/p2p/pkg/preconfirmation/preconfirmation.go @@ -61,7 +61,7 @@ type DepositManager interface { } type Tracker interface { - TrackCommitment(ctx context.Context, cm *store.EncryptedPreConfirmationWithDecrypted) error + TrackCommitment(ctx context.Context, cm *store.Commitment, txn *types.Transaction) error } type PreconfContract interface { @@ -221,14 +221,14 @@ func (p *Preconfirmation) SendBid( preConfirmation.ProviderAddress = make([]byte, len(providerAddress)) copy(preConfirmation.ProviderAddress, providerAddress[:]) - encryptedAndDecryptedPreconfirmation := &store.EncryptedPreConfirmationWithDecrypted{ + encryptedAndDecryptedPreconfirmation := &store.Commitment{ EncryptedPreConfirmation: encryptedPreConfirmation, PreConfirmation: preConfirmation, } p.metrics.ReceivedPreconfsCount.Inc() // Track the preconfirmation - if err := p.tracker.TrackCommitment(ctx, encryptedAndDecryptedPreconfirmation); err != nil { + if err := p.tracker.TrackCommitment(ctx, encryptedAndDecryptedPreconfirmation, nil); err != nil { logger.Error("tracking commitment", "error", err) return } @@ -345,13 +345,12 @@ func (p *Preconfirmation) handleBid( return status.Errorf(codes.Internal, "failed to store commitments: %v", err) } - encryptedAndDecryptedPreconfirmation := &store.EncryptedPreConfirmationWithDecrypted{ - TxnHash: txn.Hash(), + encryptedAndDecryptedPreconfirmation := &store.Commitment{ EncryptedPreConfirmation: encryptedPreConfirmation, PreConfirmation: preConfirmation, } - if err := p.tracker.TrackCommitment(ctx, encryptedAndDecryptedPreconfirmation); err != nil { + if err := p.tracker.TrackCommitment(ctx, encryptedAndDecryptedPreconfirmation, txn); err != nil { p.logger.Error("tracking commitment", "error", err) return status.Errorf(codes.Internal, "failed to track commitment: %v", err) } diff --git a/p2p/pkg/preconfirmation/preconfirmation_test.go b/p2p/pkg/preconfirmation/preconfirmation_test.go index 356967708..97f98edba 100644 --- a/p2p/pkg/preconfirmation/preconfirmation_test.go +++ b/p2p/pkg/preconfirmation/preconfirmation_test.go @@ -122,7 +122,11 @@ func (t *testDepositManager) CheckAndDeductDeposit( type testTracker struct{} -func (t *testTracker) TrackCommitment(ctx context.Context, cm *store.EncryptedPreConfirmationWithDecrypted) error { +func (t *testTracker) TrackCommitment( + ctx context.Context, + cm *store.Commitment, + txn *types.Transaction, +) error { return nil } diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index 53898deea..ad4bca9bc 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -209,6 +209,26 @@ func (s *Store) GetCommitments(blockNum int64) ([]*Commitment, error) { return commitments, nil } +func (s *Store) GetAllCommitments() ([]*Commitment, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + commitments := make([]*Commitment, 0) + err := s.st.WalkPrefix(commitmentNS, func(key string, value []byte) bool { + commitment := new(Commitment) + err := msgpack.Unmarshal(value, commitment) + if err != nil { + return false + } + commitments = append(commitments, commitment) + return false + }) + if err != nil { + return nil, err + } + return commitments, nil +} + func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) (retErr error) { cmt, err := s.GetCommitmentByDigest(cDigest[:]) if err != nil { diff --git a/p2p/pkg/preconfirmation/store/store_test.go b/p2p/pkg/preconfirmation/store/store_test.go index 19f277c5d..e8e6e9103 100644 --- a/p2p/pkg/preconfirmation/store/store_test.go +++ b/p2p/pkg/preconfirmation/store/store_test.go @@ -491,3 +491,48 @@ func TestStore_UpdatePayment(t *testing.T) { t.Fatalf("expected refund '20', got '%s'", foundCommitment.Refund) } } + +func TestStore_GetAllCommitments(t *testing.T) { + st := store.New(inmem.New()) + + commitment1 := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: []byte("commitment1"), + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 1, + BidAmount: "300", + }, + }, + } + commitment2 := &store.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + Commitment: []byte("commitment2"), + }, + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + BlockNumber: 2, + BidAmount: "200", + }, + }, + } + + err := st.AddCommitment(commitment1) + if err != nil { + t.Fatal(err) + } + err = st.AddCommitment(commitment2) + if err != nil { + t.Fatal(err) + } + + allCommitments, err := st.GetAllCommitments() + if err != nil { + t.Fatal(err) + } + + if len(allCommitments) != 2 { + t.Fatalf("expected 2 commitments, got %d", len(allCommitments)) + } +} diff --git a/p2p/pkg/preconfirmation/tracker/tracker.go b/p2p/pkg/preconfirmation/tracker/tracker.go index fd2fcb597..9148661ae 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker.go +++ b/p2p/pkg/preconfirmation/tracker/tracker.go @@ -19,6 +19,7 @@ import ( oracle "github.com/primev/mev-commit/contracts-abi/clients/Oracle" preconfcommstore "github.com/primev/mev-commit/contracts-abi/clients/PreconfManager" "github.com/primev/mev-commit/p2p/pkg/crypto" + "github.com/primev/mev-commit/p2p/pkg/notifications" "github.com/primev/mev-commit/p2p/pkg/p2p" "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" "github.com/primev/mev-commit/p2p/pkg/storage" @@ -41,6 +42,7 @@ type Tracker struct { providerNikeSK *fr.Element optsGetter OptsGetter watcher Watcher + notifier notifications.Notifier newL1Blocks chan *blocktracker.BlocktrackerNewL1Block unopenedCmts chan *preconfcommstore.PreconfmanagerUnopenedCommitmentStored commitments chan *preconfcommstore.PreconfmanagerOpenedCommitmentStored @@ -48,6 +50,7 @@ type Tracker struct { rewards chan *bidderregistry.BidderregistryFundsRewarded returns chan *bidderregistry.BidderregistryFundsRetrieved statusUpdate chan statusUpdateTask + blockOpened chan int64 triggerOpen chan struct{} metrics *metrics logger *slog.Logger @@ -96,6 +99,8 @@ func NewTracker( evtMgr events.EventManager, store CommitmentStore, preconfContract PreconfContract, + watcher Watcher, + notifier notifications.Notifier, providerNikePublicKey *bn254.G1Affine, providerNikeSecretKey *fr.Element, optsGetter OptsGetter, @@ -109,6 +114,8 @@ func NewTracker( store: store, preconfContract: preconfContract, optsGetter: optsGetter, + watcher: watcher, + notifier: notifier, providerNikePK: providerNikePublicKey, providerNikeSK: providerNikeSecretKey, newL1Blocks: make(chan *blocktracker.BlocktrackerNewL1Block), @@ -118,6 +125,7 @@ func NewTracker( rewards: make(chan *bidderregistry.BidderregistryFundsRewarded), returns: make(chan *bidderregistry.BidderregistryFundsRetrieved), statusUpdate: make(chan statusUpdateTask), + blockOpened: make(chan int64), triggerOpen: make(chan struct{}), metrics: newMetrics(), logger: logger, @@ -233,6 +241,8 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { continue } } + + t.blockOpened <- winners[len(winners)-1].BlockNumber } }) @@ -288,7 +298,11 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { }) eg.Go(func() error { - return t.clearCommitments(egCtx) + return t.clearCommitments(egCtx, t.blockOpened) + }) + + eg.Go(func() error { + return t.statusUpdater(egCtx, t.statusUpdate) }) if t.peerType == p2p.PeerTypeBidder { @@ -437,6 +451,29 @@ func (t *Tracker) statusUpdater( ); err != nil { t.logger.Error("failed to set status", "error", err) } + if status == store.CommitmentStatusFailed { + notificationPayload := map[string]any{ + "commitmentDigest": hex.EncodeToString(task.commitment.Commitment[:]), + "txnHash": task.commitment.Bid.TxHash, + "error": r.Err.Error(), + } + switch task.onSuccess { + case store.CommitmentStatusStored: + t.notifier.Notify( + notifications.NewNotification( + notifications.TopicCommitmentStoreFailed, + notificationPayload, + ), + ) + case store.CommitmentStatusOpened: + t.notifier.Notify( + notifications.NewNotification( + notifications.TopicCommitmentOpenFailed, + notificationPayload, + ), + ) + } + } } return nil }) @@ -574,47 +611,35 @@ func (t *Tracker) openCommitments( return nil } -func (t *Tracker) clearCommitments(ctx context.Context) error { - ticker := time.NewTicker(10 * time.Minute) - defer ticker.Stop() - +func (t *Tracker) clearCommitments(ctx context.Context, blockOpened <-chan int64) error { for { select { case <-ctx.Done(): return ctx.Err() - case <-ticker.C: - } - winners, err := t.store.BlockWinners() - if err != nil { - return err - } - - if len(winners) == 0 { - continue - } + case blockNumber := <-blockOpened: + var clearBlockNumber int64 + if blockNumber > blockHistoryLimit { + clearBlockNumber = blockNumber - blockHistoryLimit + } - var clearBlockNumber int64 = 0 - if winners[0].BlockNumber > blockHistoryLimit { - clearBlockNumber = winners[0].BlockNumber - blockHistoryLimit - } + if clearBlockNumber == 0 { + t.logger.Debug("no block numbers to clear") + continue + } - if clearBlockNumber == 0 { - t.logger.Debug("no block numbers to clear") - continue - } + // clear commitment indexes for all the blocks before the oldest winner + err := t.store.ClearCommitmentIndexes(clearBlockNumber) + if err != nil { + t.logger.Error( + "failed to clear commitment indexes", + "block", blockNumber, + "error", err, + ) + continue + } - // clear commitment indexes for all the blocks before the oldest winner - err = t.store.ClearCommitmentIndexes(clearBlockNumber) - if err != nil { - t.logger.Error( - "failed to clear commitment indexes", - "block", winners[0].BlockNumber, - "error", err, - ) - continue + t.logger.Info("commitment indexes cleared", "blockNumber", clearBlockNumber) } - - t.logger.Info("commitment indexes cleared", "blockNumber", winners[0].BlockNumber) } } diff --git a/p2p/pkg/preconfirmation/tracker/tracker_test.go b/p2p/pkg/preconfirmation/tracker/tracker_test.go index 1d59f5cc0..247dc7fdb 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker_test.go +++ b/p2p/pkg/preconfirmation/tracker/tracker_test.go @@ -3,11 +3,11 @@ package preconftracker_test import ( "bytes" "context" - "errors" "fmt" "math/big" "os" "strings" + "sync/atomic" "testing" "time" @@ -17,9 +17,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" bidderregistry "github.com/primev/mev-commit/contracts-abi/clients/BidderRegistry" blocktracker "github.com/primev/mev-commit/contracts-abi/clients/BlockTracker" + oracle "github.com/primev/mev-commit/contracts-abi/clients/Oracle" preconf "github.com/primev/mev-commit/contracts-abi/clients/PreconfManager" preconfpb "github.com/primev/mev-commit/p2p/gen/go/preconfirmation/v1" "github.com/primev/mev-commit/p2p/pkg/crypto" + "github.com/primev/mev-commit/p2p/pkg/notifications" "github.com/primev/mev-commit/p2p/pkg/p2p" "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" preconftracker "github.com/primev/mev-commit/p2p/pkg/preconfirmation/tracker" @@ -47,17 +49,31 @@ func TestTracker(t *testing.T) { t.Fatal(err) } + orABI, err := abi.JSON(strings.NewReader(oracle.OracleABI)) + if err != nil { + t.Fatal(err) + } + evtMgr := events.NewListener( util.NewTestLogger(os.Stdout), &btABI, &pcABI, &brABI, + &orABI, ) st := store.New(inmemstorage.New()) contract := &testPreconfContract{ openedCommitments: make(chan openedCommitment, 10), + startNonce: 11, // start nonce at 11 to avoid conflicts with test cases + } + + watcher := &mockWatcher{} + watcher.failNonce.Store(3) // fail nonce 3 to simulate a transaction error + + notifier := &mockNotifier{ + evt: make(chan *notifications.Notification, 10), } sk, pk, err := crypto.GenerateKeyPairBN254() @@ -71,7 +87,8 @@ func TestTracker(t *testing.T) { evtMgr, st, contract, - &testReceiptGetter{count: 1}, + watcher, + notifier, pk, sk, func(context.Context) (*bind.TransactOpts, error) { @@ -99,7 +116,8 @@ func TestTracker(t *testing.T) { return int64(idx/2 + idx%2) } - commitments := make([]*store.EncryptedPreConfirmationWithDecrypted, 0) + commitments := make([]*store.Commitment, 0) + txns := make([]*types.Transaction, 0) for i := 1; i <= 10; i++ { digest := common.HexToHash(fmt.Sprintf("0x%x", i)) @@ -109,7 +127,7 @@ func TestTracker(t *testing.T) { t.Fatal(err) } sharedKey := crypto.DeriveSharedKey(sk, pkBid) - commitments = append(commitments, &store.EncryptedPreConfirmationWithDecrypted{ + commitments = append(commitments, &store.Commitment{ EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ Commitment: digest.Bytes(), Signature: []byte(fmt.Sprintf("signature%d", i)), @@ -131,12 +149,12 @@ func TestTracker(t *testing.T) { ProviderAddress: getProvider(getBlockNum(i)).Bytes(), SharedSecret: crypto.BN254PublicKeyToBytes(sharedKey), }, - TxnHash: common.HexToHash(fmt.Sprintf("0x%x", i)), }) + txns = append(txns, types.NewTransaction(uint64(i), common.HexToAddress("0x1234"), nil, 0, nil, nil)) } for i, c := range commitments { - err := tracker.TrackCommitment(context.Background(), c) + err := tracker.TrackCommitment(context.Background(), c, txns[i]) if err != nil { t.Fatal(err) } @@ -156,6 +174,7 @@ func TestTracker(t *testing.T) { if err != nil { t.Fatal(err) } + commitments[i].CommitmentIndex = common.HexToHash(fmt.Sprintf("0x%x", i+1)).Bytes() } amount, ok := new(big.Int).SetString(commitments[4].Bid.BidAmount, 10) @@ -195,7 +214,7 @@ func TestTracker(t *testing.T) { }) } - opened := []*store.EncryptedPreConfirmationWithDecrypted{ + opened := []*store.Commitment{ commitments[0], commitments[1], commitments[5], @@ -247,6 +266,8 @@ func TestTracker(t *testing.T) { default: } + watcher.failNonce.Store(15) // fail nonce 15 to simulate a transaction error + publishNewWinner(evtMgr, &btABI, blocktracker.BlocktrackerNewL1Block{ BlockNumber: big.NewInt(6), Winner: winnerProvider, @@ -258,7 +279,7 @@ func TestTracker(t *testing.T) { Window: big.NewInt(1), }) - opened = []*store.EncryptedPreConfirmationWithDecrypted{ + opened = []*store.Commitment{ commitments[8], commitments[9], } @@ -303,91 +324,145 @@ func TestTracker(t *testing.T) { } } - cancel() - - <-doneChan -} - -func TestTrackerIgnoreOldBlocks(t *testing.T) { - t.Parallel() + storingFailed := <-notifier.evt + if storingFailed.Topic() != notifications.TopicCommitmentStoreFailed { + t.Fatalf("expected storing failed notification, got %s", storingFailed.Topic()) + } - pcABI, err := abi.JSON(strings.NewReader(preconf.PreconfmanagerABI)) - if err != nil { - t.Fatal(err) + openingFailed := <-notifier.evt + if openingFailed.Topic() != notifications.TopicCommitmentOpenFailed { + t.Fatalf("expected opening failed notification, got %s", openingFailed.Topic()) } - btABI, err := abi.JSON(strings.NewReader(blocktracker.BlocktrackerABI)) - if err != nil { - t.Fatal(err) + settledCommitments := []*store.Commitment{ + commitments[0], + commitments[1], + commitments[4], + commitments[5], + commitments[9], } - brABI, err := abi.JSON(strings.NewReader(bidderregistry.BidderregistryABI)) - if err != nil { - t.Fatal(err) + for i, c := range settledCommitments { + if i < 3 { + err = publishCommitmentProcessed( + evtMgr, + &orABI, + oracle.OracleCommitmentProcessed{ + IsSlash: false, + CommitmentIndex: common.BytesToHash(c.CommitmentIndex), + }, + ) + if err != nil { + t.Fatal(err) + } + + err = publishReward( + evtMgr, + &brABI, + bidderregistry.BidderregistryFundsRewarded{ + Window: big.NewInt(int64(c.Bid.BlockNumber)), + Amount: big.NewInt(900), + CommitmentDigest: common.BytesToHash(c.Digest), + Bidder: common.HexToAddress("0x1234"), + Provider: common.HexToAddress("0x1234"), + }, + ) + if err != nil { + t.Fatal(err) + } + } else { + err = publishCommitmentProcessed( + evtMgr, + &orABI, + oracle.OracleCommitmentProcessed{ + IsSlash: true, + CommitmentIndex: common.BytesToHash(c.CommitmentIndex), + }, + ) + if err != nil { + t.Fatal(err) + } + + err = publishReturn( + evtMgr, + &brABI, + bidderregistry.BidderregistryFundsRetrieved{ + Window: big.NewInt(int64(c.Bid.BlockNumber)), + Amount: big.NewInt(900), + CommitmentDigest: common.BytesToHash(c.Digest), + Bidder: common.HexToAddress("0x1234"), + }, + ) + if err != nil { + t.Fatal(err) + } + } } - evtMgr := events.NewListener( - util.NewTestLogger(os.Stdout), - &btABI, - &pcABI, - &brABI, - ) + var cmts []*store.Commitment + start := time.Now() + for { + cmts, err := st.GetAllCommitments() + if err != nil { + t.Fatal(err) + } - st := store.New(inmemstorage.New()) + if len(cmts) != 10 { + t.Fatalf("expected 10 commitments, got %d", len(cmts)) + } - for _, b := range []int64{1, 12, 13} { - if err := st.AddWinner(&store.BlockWinner{ - BlockNumber: b, - Winner: common.HexToAddress("0x1234"), - }); err != nil { - t.Fatal(err) + if cmts[9].Status == store.CommitmentStatusSlashed { + break + } + + if time.Since(start) > 15*time.Second { + t.Fatal("timeout waiting for commitments to be processed") } } - contract := &testPreconfContract{ - openedCommitments: make(chan openedCommitment, 10), + statuses := map[int]store.CommitmentStatus{ + 0: store.CommitmentStatusSettled, + 1: store.CommitmentStatusSettled, + 2: store.CommitmentStatusStored, + 3: store.CommitmentStatusFailed, + 4: store.CommitmentStatusSettled, + 5: store.CommitmentStatusSlashed, + 6: store.CommitmentStatusStored, + 7: store.CommitmentStatusStored, + 8: store.CommitmentStatusFailed, + 9: store.CommitmentStatusSlashed, } - sk, pk, err := crypto.GenerateKeyPairBN254() - if err != nil { - t.Fatal(err) + for idx, c := range cmts { + if c.Status != statuses[idx] { + t.Fatalf( + "expected commitment %d status %s, got %s", + idx, + statuses[idx], + c.Status, + ) + } } - tracker := preconftracker.NewTracker( - big.NewInt(5), - p2p.PeerTypeProvider, - common.HexToAddress("0x1234"), - evtMgr, - st, - contract, - &testReceiptGetter{count: 1}, - pk, - sk, - func(context.Context) (*bind.TransactOpts, error) { - return &bind.TransactOpts{ - From: common.HexToAddress("0x1234"), - }, nil - }, - util.NewTestLogger(os.Stdout), - ) - ctx, cancel := context.WithCancel(context.Background()) - doneChan := tracker.Start(ctx) + publishNewWinner(evtMgr, &btABI, blocktracker.BlocktrackerNewL1Block{ + BlockNumber: big.NewInt(10012), + Winner: winnerProvider, + Window: big.NewInt(1001), + }) - startTime := time.Now() + start = time.Now() for { - winners, err := st.BlockWinners() + if time.Since(start) > 15*time.Second { + t.Fatal("timeout waiting for tracker to finish") + } + cmts, err = st.GetAllCommitments() if err != nil { t.Fatal(err) } - - if len(winners) == 0 { + if len(cmts) == 0 { break } - time.Sleep(100 * time.Millisecond) - if time.Since(startTime) > 5*time.Second { - t.Fatal("timed out waiting for block winners to be cleared") - } } cancel() @@ -410,6 +485,7 @@ type openedCommitment struct { type testPreconfContract struct { openedCommitments chan openedCommitment + startNonce uint64 } func (t *testPreconfContract) OpenCommitment( @@ -429,24 +505,39 @@ func (t *testPreconfContract) OpenCommitment( slashAmt: params.SlashAmt, zkProof: params.ZkProof, } - return types.NewTransaction(0, common.Address{}, nil, 0, nil, nil), nil + nonce := t.startNonce + t.startNonce++ + return types.NewTransaction(nonce, common.Address{}, nil, 0, nil, nil), nil +} + +type mockNotifier struct { + evt chan *notifications.Notification } -type testReceiptGetter struct { - count int +func (m *mockNotifier) Notify(n *notifications.Notification) { + m.evt <- n } -func (t *testReceiptGetter) BatchReceipts(_ context.Context, txns []common.Hash) ([]txmonitor.Result, error) { - if t.count != len(txns) { - return nil, fmt.Errorf("expected %d txns, got %d", t.count, len(txns)) +type mockWatcher struct { + failNonce atomic.Uint64 +} + +func (m *mockWatcher) WatchTx(_ common.Hash, nonce uint64) <-chan txmonitor.Result { + result := make(chan txmonitor.Result, 1) + if m.failNonce.Load() == nonce { + result <- txmonitor.Result{ + Err: fmt.Errorf("failed to watch transaction with nonce %d", nonce), + } + return result } - results := make([]txmonitor.Result, 0, len(txns)) - for range txns { - results = append(results, txmonitor.Result{ - Err: errors.New("test error"), - }) + result <- txmonitor.Result{ + Receipt: &types.Receipt{ + Status: 1, + }, + Err: nil, } - return results, nil + + return result } func publishUnopenedCommitment( @@ -541,3 +632,88 @@ func publishNewWinner( evtMgr.PublishLogEvent(context.Background(), testLog) } + +func publishCommitmentProcessed( + evtMgr events.EventManager, + orABI *abi.ABI, + c oracle.OracleCommitmentProcessed, +) error { + event := orABI.Events["CommitmentProcessed"] + buf, err := event.Inputs.NonIndexed().Pack( + c.IsSlash, + ) + if err != nil { + return err + } + + commitmentIndex := common.BytesToHash(c.CommitmentIndex[:]) + + // Creating a Log object + testLog := types.Log{ + Topics: []common.Hash{ + event.ID, // The first topic is the hash of the event signature + commitmentIndex, // The next topics are the indexed event parameters + }, + Data: buf, + } + + evtMgr.PublishLogEvent(context.Background(), testLog) + return nil +} + +func publishReward( + evtMgr events.EventManager, + brABI *abi.ABI, + r bidderregistry.BidderregistryFundsRewarded, +) error { + event := brABI.Events["FundsRewarded"] + buf, err := event.Inputs.NonIndexed().Pack( + r.Window, + r.Amount, + ) + if err != nil { + return err + } + + // Creating a Log object + testLog := types.Log{ + Topics: []common.Hash{ + event.ID, // The first topic is the hash of the event signature + r.CommitmentDigest, + common.HexToHash(r.Bidder.Hex()), + common.HexToHash(r.Provider.Hex()), + }, + Data: buf, + } + + evtMgr.PublishLogEvent(context.Background(), testLog) + return nil +} + +func publishReturn( + evtMgr events.EventManager, + brABI *abi.ABI, + r bidderregistry.BidderregistryFundsRetrieved, +) error { + event := brABI.Events["FundsRetrieved"] + buf, err := event.Inputs.NonIndexed().Pack( + r.Amount, + ) + if err != nil { + return err + } + + // Creating a Log object + testLog := types.Log{ + Topics: []common.Hash{ + event.ID, // The first topic is the hash of the event signature + r.CommitmentDigest, + common.HexToHash(r.Bidder.Hex()), + common.BigToHash(r.Window), + }, + Data: buf, + } + + evtMgr.PublishLogEvent(context.Background(), testLog) + return nil +} From 3c14b7cf586975f1327a5b641058e3a22c8e3b8c Mon Sep 17 00:00:00 2001 From: Alok Date: Mon, 26 May 2025 20:01:52 +0530 Subject: [PATCH 05/14] feat: preconf flow tracking --- p2p/gen/go/bidderapi/v1/bidderapi.pb.go | 1663 +++++++++++------ p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go | 148 ++ p2p/gen/go/bidderapi/v1/bidderapi_grpc.pb.go | 93 + p2p/gen/go/providerapi/v1/providerapi.pb.go | 759 ++++++-- .../go/providerapi/v1/providerapi.pb.gw.go | 72 + .../go/providerapi/v1/providerapi_grpc.pb.go | 44 + .../bidderapi/v1/bidderapi.swagger.yaml | 214 ++- .../providerapi/v1/providerapi.swagger.yaml | 112 ++ p2p/rpc/bidderapi/v1/bidderapi.proto | 76 +- p2p/rpc/providerapi/v1/providerapi.proto | 89 + 10 files changed, 2500 insertions(+), 770 deletions(-) diff --git a/p2p/gen/go/bidderapi/v1/bidderapi.pb.go b/p2p/gen/go/bidderapi/v1/bidderapi.pb.go index d79a686b3..839ede730 100644 --- a/p2p/gen/go/bidderapi/v1/bidderapi.pb.go +++ b/p2p/gen/go/bidderapi/v1/bidderapi.pb.go @@ -952,6 +952,305 @@ func (x *Commitment) GetSlashAmount() string { return "" } +type GetBidInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockNumber int64 `protobuf:"varint,1,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + Limit int32 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (x *GetBidInfoRequest) Reset() { + *x = GetBidInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBidInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBidInfoRequest) ProtoMessage() {} + +func (x *GetBidInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBidInfoRequest.ProtoReflect.Descriptor instead. +func (*GetBidInfoRequest) Descriptor() ([]byte, []int) { + return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{15} +} + +func (x *GetBidInfoRequest) GetBlockNumber() int64 { + if x != nil { + return x.BlockNumber + } + return 0 +} + +func (x *GetBidInfoRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GetBidInfoRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +type GetBidInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockBidInfo []*GetBidInfoResponse_BlockBidInfo `protobuf:"bytes,1,rep,name=block_bid_info,json=blockBidInfo,proto3" json:"block_bid_info,omitempty"` +} + +func (x *GetBidInfoResponse) Reset() { + *x = GetBidInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBidInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBidInfoResponse) ProtoMessage() {} + +func (x *GetBidInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBidInfoResponse.ProtoReflect.Descriptor instead. +func (*GetBidInfoResponse) Descriptor() ([]byte, []int) { + return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{16} +} + +func (x *GetBidInfoResponse) GetBlockBidInfo() []*GetBidInfoResponse_BlockBidInfo { + if x != nil { + return x.BlockBidInfo + } + return nil +} + +type GetBidInfoResponse_CommitmentWithStatus struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Commitment *Commitment `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + Details string `protobuf:"bytes,3,opt,name=details,proto3" json:"details,omitempty"` + Payment string `protobuf:"bytes,4,opt,name=payment,proto3" json:"payment,omitempty"` + Refund string `protobuf:"bytes,5,opt,name=refund,proto3" json:"refund,omitempty"` +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) Reset() { + *x = GetBidInfoResponse_CommitmentWithStatus{} + if protoimpl.UnsafeEnabled { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBidInfoResponse_CommitmentWithStatus) ProtoMessage() {} + +func (x *GetBidInfoResponse_CommitmentWithStatus) ProtoReflect() protoreflect.Message { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBidInfoResponse_CommitmentWithStatus.ProtoReflect.Descriptor instead. +func (*GetBidInfoResponse_CommitmentWithStatus) Descriptor() ([]byte, []int) { + return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{16, 0} +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) GetCommitment() *Commitment { + if x != nil { + return x.Commitment + } + return nil +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) GetDetails() string { + if x != nil { + return x.Details + } + return "" +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) GetPayment() string { + if x != nil { + return x.Payment + } + return "" +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) GetRefund() string { + if x != nil { + return x.Refund + } + return "" +} + +type GetBidInfoResponse_BidInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Bid *Bid `protobuf:"bytes,1,opt,name=bid,proto3" json:"bid,omitempty"` + Commitments []*GetBidInfoResponse_CommitmentWithStatus `protobuf:"bytes,2,rep,name=commitments,proto3" json:"commitments,omitempty"` +} + +func (x *GetBidInfoResponse_BidInfo) Reset() { + *x = GetBidInfoResponse_BidInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBidInfoResponse_BidInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBidInfoResponse_BidInfo) ProtoMessage() {} + +func (x *GetBidInfoResponse_BidInfo) ProtoReflect() protoreflect.Message { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBidInfoResponse_BidInfo.ProtoReflect.Descriptor instead. +func (*GetBidInfoResponse_BidInfo) Descriptor() ([]byte, []int) { + return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{16, 1} +} + +func (x *GetBidInfoResponse_BidInfo) GetBid() *Bid { + if x != nil { + return x.Bid + } + return nil +} + +func (x *GetBidInfoResponse_BidInfo) GetCommitments() []*GetBidInfoResponse_CommitmentWithStatus { + if x != nil { + return x.Commitments + } + return nil +} + +type GetBidInfoResponse_BlockBidInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockNumber int64 `protobuf:"varint,1,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + Bids []*GetBidInfoResponse_BidInfo `protobuf:"bytes,2,rep,name=bids,proto3" json:"bids,omitempty"` +} + +func (x *GetBidInfoResponse_BlockBidInfo) Reset() { + *x = GetBidInfoResponse_BlockBidInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBidInfoResponse_BlockBidInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBidInfoResponse_BlockBidInfo) ProtoMessage() {} + +func (x *GetBidInfoResponse_BlockBidInfo) ProtoReflect() protoreflect.Message { + mi := &file_bidderapi_v1_bidderapi_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetBidInfoResponse_BlockBidInfo.ProtoReflect.Descriptor instead. +func (*GetBidInfoResponse_BlockBidInfo) Descriptor() ([]byte, []int) { + return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{16, 2} +} + +func (x *GetBidInfoResponse_BlockBidInfo) GetBlockNumber() int64 { + if x != nil { + return x.BlockNumber + } + return 0 +} + +func (x *GetBidInfoResponse_BlockBidInfo) GetBids() []*GetBidInfoResponse_BidInfo { + if x != nil { + return x.Bids + } + return nil +} + var File_bidderapi_v1_bidderapi_proto protoreflect.FileDescriptor var file_bidderapi_v1_bidderapi_proto_rawDesc = []byte{ @@ -1019,574 +1318,679 @@ var file_bidderapi_v1_bidderapi_proto_rawDesc = []byte{ 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x69, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x2e, - 0xd2, 0x01, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xec, 0x01, 0x0a, 0x0f, 0x44, 0x65, + 0xd2, 0x01, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x82, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x7e, 0x92, 0x41, 0x7b, 0x0a, 0x42, 0x2a, - 0x10, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x32, 0x35, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x7d, 0x22, 0x9a, 0x02, 0x0a, 0x13, 0x41, 0x75, 0x74, - 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4c, 0x0a, 0x13, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x11, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2a, - 0x0a, 0x11, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x77, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x50, 0x65, 0x72, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a, 0x88, 0x01, 0x92, 0x41, 0x84, - 0x01, 0x0a, 0x38, 0x2a, 0x14, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x32, 0x48, 0x7b, 0x22, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x22, 0x2c, 0x20, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x3a, 0x20, 0x22, - 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x22, 0x7d, 0x22, 0xdf, 0x03, 0x0a, 0x19, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x69, 0x73, 0x5f, 0x61, 0x75, - 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x64, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0xc7, 0x02, - 0x92, 0x41, 0xc3, 0x02, 0x0a, 0x4b, 0x2a, 0x1b, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0x2c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0x32, 0xf3, 0x01, 0x7b, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x7b, 0x22, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0x3a, 0x20, 0x32, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0x3a, 0x20, 0x33, 0x7d, 0x5d, 0x2c, 0x20, 0x22, 0x69, 0x73, 0x41, 0x75, 0x74, - 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, - 0x3a, 0x20, 0x74, 0x72, 0x75, 0x65, 0x7d, 0x22, 0x78, 0x0a, 0x18, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x3a, - 0x40, 0x92, 0x41, 0x3d, 0x0a, 0x3b, 0x2a, 0x19, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, - 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x32, 0x1e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x2e, 0x22, 0xd7, 0x01, 0x0a, 0x19, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x43, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x3a, 0x75, 0x92, 0x41, 0x72, 0x0a, 0x51, 0x2a, 0x1a, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x33, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, - 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x32, 0x1d, 0x7b, 0x22, - 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x3a, - 0x20, 0x5b, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x5d, 0x7d, 0x22, 0x8f, 0x04, 0x0a, 0x0b, - 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x4e, 0x0a, 0x0f, 0x64, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0x92, 0x41, 0x21, 0x32, 0x1f, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, - 0x54, 0x48, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x2e, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x66, 0x0a, 0x0d, 0x77, - 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x42, 0x23, 0x92, 0x41, 0x20, 0x32, 0x1e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x2e, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x42, 0x33, 0x92, 0x41, 0x30, 0x32, 0x2e, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, - 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x52, 0x09, 0x69, 0x73, - 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x7c, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x93, 0x01, 0x92, 0x41, 0x8f, 0x01, 0x0a, + 0x56, 0x2a, 0x10, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0x42, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x20, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x32, 0x35, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x7d, 0x22, 0x9a, + 0x02, 0x0a, 0x13, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x13, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x42, 0x30, 0x92, 0x41, 0x2d, 0x32, 0x2b, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x61, 0x6c, 0x20, 0x4c, 0x31, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, + 0x65, 0x52, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, + 0x65, 0x72, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x65, 0x72, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x3a, 0x88, 0x01, 0x92, 0x41, 0x84, 0x01, 0x0a, 0x38, 0x2a, 0x14, 0x41, 0x75, 0x74, 0x6f, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, + 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, + 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x32, 0x48, 0x7b, 0x22, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x22, 0x2c, 0x20, + 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x22, 0xdf, 0x03, 0x0a, 0x19, + 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0f, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x0e, 0x77, + 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x34, 0x0a, + 0x16, 0x69, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, + 0x73, 0x41, 0x75, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x3a, 0xc7, 0x02, 0x92, 0x41, 0xc3, 0x02, 0x0a, 0x4b, 0x2a, 0x1b, 0x41, 0x75, + 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x2c, 0x41, 0x75, 0x74, 0x6f, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x66, 0x72, + 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x32, 0xf3, 0x01, 0x7b, 0x22, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x7b, + 0x22, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x7d, 0x2c, 0x20, 0x7b, + 0x22, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x32, 0x7d, 0x2c, 0x20, 0x7b, + 0x22, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x33, 0x7d, 0x5d, 0x2c, 0x20, + 0x22, 0x69, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x20, 0x74, 0x72, 0x75, 0x65, 0x7d, 0x22, 0x78, 0x0a, + 0x18, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x3a, 0x40, 0x92, 0x41, 0x3d, 0x0a, 0x3b, 0x2a, 0x19, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0x1e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2e, 0x22, 0xd7, 0x01, 0x0a, 0x19, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0d, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x3a, 0x75, 0x92, 0x41, 0x72, 0x0a, + 0x51, 0x2a, 0x1a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x33, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x79, 0x2e, 0x32, 0x1d, 0x7b, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x5d, + 0x7d, 0x22, 0x8f, 0x04, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x24, 0x92, 0x41, 0x21, 0x32, + 0x1f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x2e, + 0x52, 0x0f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x66, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, + 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x23, 0x92, 0x41, 0x20, 0x32, 0x1e, 0x57, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2e, 0x52, 0x0c, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x0a, 0x69, 0x73, 0x5f, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x42, 0x33, 0x92, + 0x41, 0x30, 0x32, 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x69, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x2e, 0x52, 0x09, 0x69, 0x73, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x7c, 0x0a, + 0x12, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, + 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x30, 0x92, 0x41, 0x2d, 0x32, 0x2b, 0x54, 0x68, + 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x4c, 0x31, 0x20, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x52, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x76, 0x0a, 0x10, 0x65, + 0x6e, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x20, 0x4c, 0x31, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x2e, 0x52, 0x10, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x76, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x2e, 0x92, - 0x41, 0x2b, 0x32, 0x29, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x4c, 0x31, - 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x52, 0x0e, 0x65, - 0x6e, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x0e, 0x0a, - 0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa9, 0x02, - 0x0a, 0x11, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x93, 0x02, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, + 0x6f, 0x77, 0x2e, 0x52, 0x0e, 0x65, 0x6e, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x22, 0x0e, 0x0a, 0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x93, 0x02, 0x0a, 0x0d, 0x77, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, + 0xcf, 0x01, 0x92, 0x41, 0x63, 0x32, 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, + 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x2e, 0xba, 0x48, 0x66, 0xba, 0x01, 0x63, 0x0a, 0x0d, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x36, 0x77, + 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x2e, 0x1a, 0x1a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x6e, + 0x75, 0x6c, 0x6c, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3e, 0x20, 0x30, + 0x29, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, + 0xed, 0x02, 0x0a, 0x0f, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x94, 0x02, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0xcf, 0x01, 0x92, 0x41, 0x63, 0x32, - 0x61, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x2e, 0x20, 0x49, - 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x2e, 0xba, 0x48, 0x66, 0xba, 0x01, 0x63, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x36, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, - 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, - 0x72, 0x20, 0x69, 0x66, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2e, 0x1a, - 0x1a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x7c, 0x7c, - 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x52, 0x0c, 0x77, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xed, 0x02, 0x0a, 0x0f, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x94, 0x02, - 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x42, 0xd0, 0x01, 0x92, 0x41, 0x64, 0x32, 0x62, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, - 0x67, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x2e, 0xba, 0x48, 0x66, - 0xba, 0x01, 0x63, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x12, 0x36, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, - 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2e, 0x1a, 0x1a, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x74, 0x68, 0x69, - 0x73, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x43, 0x92, 0x41, 0x40, 0x0a, 0x3e, 0x2a, 0x10, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0x2a, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x22, 0xeb, 0x01, 0x0a, 0x10, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x77, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x7c, 0x92, 0x41, 0x79, 0x0a, 0x3f, - 0x2a, 0x11, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0x2a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x64, 0x65, + 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0xd0, 0x01, 0x92, 0x41, 0x64, 0x32, + 0x62, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, + 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, + 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, + 0x65, 0x64, 0x2e, 0xba, 0x48, 0x66, 0xba, 0x01, 0x63, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x36, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, + 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2e, + 0x1a, 0x1a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x7c, + 0x7c, 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x52, 0x0c, 0x77, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x43, 0x92, 0x41, 0x40, 0x0a, + 0x3e, 0x2a, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x32, 0x2a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x32, - 0x36, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x22, + 0xec, 0x01, 0x0a, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x0d, + 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, + 0x7d, 0x92, 0x41, 0x7a, 0x0a, 0x40, 0x2a, 0x11, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, + 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x2b, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x6e, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x32, 0x36, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x20, 0x7d, 0x22, 0x97, + 0x03, 0x0a, 0x1a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, + 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0xeb, 0x01, + 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x42, 0xa5, 0x01, 0x92, 0x41, 0x2a, 0x32, 0x28, 0x57, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x73, 0x2e, 0xba, 0x48, 0x75, 0xba, 0x01, 0x72, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x3a, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, + 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, + 0x20, 0x6f, 0x66, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x65, 0x72, 0x73, 0x2e, 0x1a, 0x24, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, 0x6c, 0x6c, + 0x28, 0x72, 0x2c, 0x20, 0x72, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x20, 0x26, 0x26, 0x20, 0x73, 0x69, + 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x52, 0x0d, 0x77, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x3a, 0x8a, 0x01, 0x92, 0x41, + 0x86, 0x01, 0x0a, 0x65, 0x2a, 0x26, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0x2a, 0x57, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0xd2, 0x01, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x32, 0x1d, 0x7b, 0x22, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x31, + 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x5d, 0x7d, 0x22, 0x8f, 0x03, 0x0a, 0x1b, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x77, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x11, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x3a, 0xa0, 0x02, 0x92, 0x41, 0x9c, 0x02, 0x0a, 0x56, + 0x2a, 0x27, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, + 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x2b, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x6e, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x32, 0xc1, 0x01, 0x7b, 0x22, 0x77, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x3a, 0x20, + 0x5b, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x22, 0x3a, 0x20, 0x31, 0x20, 0x7d, 0x22, 0x97, 0x03, 0x0a, 0x1a, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0xeb, 0x01, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0xa5, 0x01, - 0x92, 0x41, 0x2a, 0x32, 0x28, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x2e, 0xba, 0x48, 0x75, - 0xba, 0x01, 0x72, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x12, 0x3a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x2e, 0x1a, - 0x24, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x2c, 0x20, 0x72, 0x20, 0x3e, - 0x20, 0x30, 0x29, 0x20, 0x26, 0x26, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, - 0x29, 0x20, 0x3e, 0x20, 0x30, 0x52, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x3a, 0x8a, 0x01, 0x92, 0x41, 0x86, 0x01, 0x0a, 0x65, 0x2a, 0x26, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0x2a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, - 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, - 0x2e, 0xd2, 0x01, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x32, 0x1d, 0x7b, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x5d, - 0x7d, 0x22, 0x8e, 0x03, 0x0a, 0x1b, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, - 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x11, 0x77, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, - 0x3a, 0x9f, 0x02, 0x92, 0x41, 0x9b, 0x02, 0x0a, 0x55, 0x2a, 0x27, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, - 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x32, 0x2a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x20, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, - 0x64, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x32, 0xc1, - 0x01, 0x7b, 0x22, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x72, 0x22, 0x3a, 0x20, 0x31, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x20, 0x7d, 0x2c, + 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x32, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x22, 0x3a, 0x20, 0x32, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x33, 0x20, 0x7d, 0x20, - 0x5d, 0x7d, 0x22, 0xf2, 0x13, 0x0a, 0x03, 0x42, 0x69, 0x64, 0x12, 0x94, 0x02, 0x0a, 0x09, 0x74, - 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0xf6, - 0x01, 0x92, 0x41, 0x78, 0x32, 0x64, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, - 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0xba, 0x48, 0x78, 0xba, - 0x01, 0x75, 0x0a, 0x09, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x36, 0x74, - 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, - 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x30, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, 0x6c, 0x6c, 0x28, - 0x72, 0x2c, 0x20, 0x72, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, - 0x30, 0x78, 0x29, 0x3f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, - 0x36, 0x34, 0x7d, 0x24, 0x27, 0x29, 0x29, 0x52, 0x08, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x12, 0xe0, 0x01, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x42, 0xc7, 0x01, 0x92, 0x41, 0x76, 0x32, 0x6b, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x8a, 0x01, 0x06, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0xba, 0x48, - 0x4b, 0xba, 0x01, 0x48, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x1d, 0x74, - 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x31, - 0x2d, 0x39, 0x5d, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x24, 0x27, 0x29, 0x52, 0x06, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0xb9, 0x01, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x95, 0x01, 0x92, 0x41, - 0x47, 0x32, 0x45, 0x4d, 0x61, 0x78, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, + 0x72, 0x22, 0x3a, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x5d, 0x7d, 0x22, 0xf2, 0x13, 0x0a, 0x03, 0x42, + 0x69, 0x64, 0x12, 0x94, 0x02, 0x0a, 0x09, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0xf6, 0x01, 0x92, 0x41, 0x78, 0x32, 0x64, 0x48, 0x65, + 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, + 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x2e, 0xba, 0x48, 0x48, 0xba, 0x01, 0x45, 0x0a, 0x0c, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x25, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, - 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, - 0x65, 0x72, 0x2e, 0x1a, 0x0e, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, - 0x3e, 0x20, 0x30, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0xc2, 0x01, 0x0a, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x42, 0x8d, 0x01, 0x92, 0x41, 0x2d, 0x32, 0x2b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, - 0x69, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x69, - 0x6e, 0x67, 0x2e, 0xba, 0x48, 0x5a, 0xba, 0x01, 0x57, 0x0a, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, - 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x2e, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, - 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, - 0x1a, 0x0e, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, - 0x52, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0xb8, 0x01, 0x0a, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, - 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x42, 0x87, 0x01, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, - 0x69, 0x6e, 0x67, 0x2e, 0xba, 0x48, 0x56, 0xba, 0x01, 0x53, 0x0a, 0x13, 0x64, 0x65, 0x63, 0x61, - 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x2c, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x0e, 0x75, - 0x69, 0x6e, 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x52, 0x11, 0x64, - 0x65, 0x63, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x8f, 0x02, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, - 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x42, 0xde, - 0x01, 0x92, 0x41, 0x49, 0x32, 0x47, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x78, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x20, - 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x64, 0x2e, 0xba, 0x48, 0x8e, - 0x01, 0xba, 0x01, 0x8a, 0x01, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x41, 0x72, 0x65, 0x76, 0x65, - 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, - 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, + 0x7b, 0x36, 0x34, 0x7d, 0xba, 0x48, 0x78, 0xba, 0x01, 0x75, 0x0a, 0x09, 0x74, 0x78, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x36, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x30, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x2c, 0x20, 0x72, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, 0x30, 0x78, 0x29, 0x3f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0x24, 0x27, 0x29, 0x29, 0x52, - 0x11, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, - 0x65, 0x73, 0x12, 0xa3, 0x02, 0x0a, 0x10, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x42, 0xf7, 0x01, - 0x92, 0x41, 0x6e, 0x32, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x4c, 0x50, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x20, 0x72, 0x61, 0x77, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0xba, 0x48, 0x82, 0x01, 0xba, 0x01, 0x7f, 0x0a, 0x10, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x72, 0x61, 0x77, 0x5f, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x75, 0x73, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, - 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x72, 0x61, 0x77, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x1a, 0x2d, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, - 0x6c, 0x6c, 0x28, 0x72, 0x2c, 0x20, 0x72, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, - 0x27, 0x5e, 0x28, 0x30, 0x78, 0x29, 0x3f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, - 0x39, 0x5d, 0x2a, 0x24, 0x27, 0x29, 0x29, 0x52, 0x0f, 0x72, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xbf, 0x02, 0x0a, 0x0c, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x9b, 0x02, 0x92, 0x41, 0x9f, 0x01, 0x32, 0x93, 0x01, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, - 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, - 0x20, 0x62, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x69, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x7a, 0x65, 0x72, 0x6f, 0x2c, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x65, 0x64, 0x20, 0x62, 0x69, 0x64, 0x20, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x8a, 0x01, 0x06, 0x5b, - 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0xba, 0x48, 0x75, 0xba, 0x01, 0x72, 0x0a, 0x0c, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x73, 0x6c, 0x61, 0x73, 0x68, - 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, - 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, - 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x27, 0x20, 0x7c, 0x7c, 0x20, - 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, - 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x27, 0x29, 0x20, 0x26, 0x26, 0x20, 0x75, 0x69, 0x6e, - 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x29, 0x52, 0x0b, 0x73, - 0x6c, 0x61, 0x73, 0x68, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0xba, 0x04, 0x92, 0x41, 0xb6, - 0x04, 0x0a, 0x95, 0x01, 0x2a, 0x0b, 0x42, 0x69, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x32, 0x40, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x69, 0x64, 0x20, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x20, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0xd2, 0x01, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0xd2, 0x01, 0x0c, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xd2, 0x01, 0x15, 0x64, 0x65, - 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0xd2, 0x01, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x32, 0x9b, 0x03, 0x7b, 0x22, 0x74, 0x78, - 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x22, 0x66, 0x65, 0x34, 0x63, - 0x62, 0x34, 0x37, 0x64, 0x62, 0x33, 0x36, 0x33, 0x30, 0x35, 0x35, 0x31, 0x62, 0x65, 0x65, 0x64, - 0x66, 0x62, 0x64, 0x30, 0x32, 0x61, 0x37, 0x31, 0x65, 0x63, 0x63, 0x36, 0x39, 0x66, 0x64, 0x35, - 0x39, 0x37, 0x35, 0x38, 0x65, 0x32, 0x62, 0x61, 0x36, 0x39, 0x39, 0x36, 0x30, 0x36, 0x65, 0x32, - 0x64, 0x35, 0x63, 0x37, 0x34, 0x32, 0x38, 0x34, 0x66, 0x66, 0x61, 0x37, 0x22, 0x2c, 0x20, 0x22, - 0x37, 0x31, 0x63, 0x31, 0x33, 0x34, 0x38, 0x66, 0x32, 0x64, 0x37, 0x66, 0x66, 0x37, 0x65, 0x38, - 0x31, 0x34, 0x66, 0x39, 0x63, 0x33, 0x36, 0x31, 0x37, 0x39, 0x38, 0x33, 0x37, 0x30, 0x33, 0x34, - 0x33, 0x35, 0x65, 0x61, 0x37, 0x34, 0x34, 0x36, 0x64, 0x65, 0x34, 0x32, 0x30, 0x61, 0x65, 0x61, - 0x63, 0x34, 0x38, 0x38, 0x62, 0x66, 0x31, 0x64, 0x65, 0x33, 0x35, 0x37, 0x33, 0x37, 0x65, 0x38, - 0x22, 0x5d, 0x2c, 0x20, 0x22, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x2c, 0x20, 0x22, 0x64, 0x65, - 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x20, 0x31, 0x36, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x2c, 0x20, 0x22, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x20, 0x31, 0x36, 0x33, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x2c, 0x20, 0x22, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, - 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x22, 0x66, 0x65, - 0x34, 0x63, 0x62, 0x34, 0x37, 0x64, 0x62, 0x33, 0x36, 0x33, 0x30, 0x35, 0x35, 0x31, 0x62, 0x65, - 0x65, 0x64, 0x66, 0x62, 0x64, 0x30, 0x32, 0x61, 0x37, 0x31, 0x65, 0x63, 0x63, 0x36, 0x39, 0x66, - 0x64, 0x35, 0x39, 0x37, 0x35, 0x38, 0x65, 0x32, 0x62, 0x61, 0x36, 0x39, 0x39, 0x36, 0x30, 0x36, - 0x65, 0x32, 0x64, 0x35, 0x63, 0x37, 0x34, 0x32, 0x38, 0x34, 0x66, 0x66, 0x61, 0x37, 0x22, 0x5d, - 0x2c, 0x20, 0x22, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x3a, 0x20, 0x22, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x22, 0xe2, 0x0c, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x95, 0x01, 0x0a, 0x09, 0x74, 0x78, 0x5f, 0x68, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x78, 0x92, 0x41, 0x75, 0x32, - 0x61, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, - 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x73, 0x68, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, - 0x7b, 0x36, 0x34, 0x7d, 0x52, 0x08, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x8f, - 0x01, 0x0a, 0x0a, 0x62, 0x69, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x70, 0x92, 0x41, 0x6d, 0x32, 0x6b, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x67, 0x72, 0x65, - 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x52, 0x09, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x6d, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x4a, 0x92, 0x41, 0x47, 0x32, 0x45, 0x4d, 0x61, 0x78, - 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, - 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, - 0x6e, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, - 0x7b, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x64, 0x5f, - 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x4b, 0x92, 0x41, - 0x48, 0x32, 0x46, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, - 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x64, 0x42, 0x69, 0x64, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x7d, 0x0a, 0x16, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x47, 0x92, 0x41, - 0x44, 0x32, 0x42, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, - 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x62, 0x69, 0x64, 0x2e, 0x52, 0x14, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x42, - 0x69, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x62, 0x0a, 0x11, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x35, 0x92, 0x41, 0x32, 0x32, 0x30, 0x48, 0x65, 0x78, + 0x08, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0xe0, 0x01, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0xc7, 0x01, 0x92, 0x41, 0x76, + 0x32, 0x6b, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, + 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, + 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, + 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x8a, 0x01, 0x06, + 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0xba, 0x48, 0x4b, 0xba, 0x01, 0x48, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6d, 0x75, 0x73, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x1d, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x31, 0x2d, 0x39, 0x5d, 0x5b, 0x30, 0x2d, 0x39, 0x5d, + 0x2a, 0x24, 0x27, 0x29, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0xb9, 0x01, 0x0a, + 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x42, 0x95, 0x01, 0x92, 0x41, 0x47, 0x32, 0x45, 0x4d, 0x61, 0x78, 0x20, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, + 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x2e, + 0xba, 0x48, 0x48, 0xba, 0x01, 0x45, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x25, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x0e, 0x75, 0x69, 0x6e, + 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x52, 0x0b, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0xc2, 0x01, 0x0a, 0x15, 0x64, 0x65, 0x63, + 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x42, 0x8d, 0x01, 0x92, 0x41, 0x2d, 0x32, 0x2b, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, + 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2e, 0xba, 0x48, 0x5a, 0xba, 0x01, + 0x57, 0x0a, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2e, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, + 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x0e, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x74, + 0x68, 0x69, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x52, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0xb8, 0x01, + 0x0a, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x42, 0x87, 0x01, 0x92, 0x41, + 0x2b, 0x32, 0x29, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, + 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x65, 0x6e, + 0x64, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2e, 0xba, 0x48, 0x56, 0xba, + 0x01, 0x53, 0x0a, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, + 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x6d, 0x75, 0x73, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x0e, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, + 0x29, 0x20, 0x3e, 0x20, 0x30, 0x52, 0x11, 0x64, 0x65, 0x63, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x8f, 0x02, 0x0a, 0x13, 0x72, 0x65, 0x76, + 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x42, 0xde, 0x01, 0x92, 0x41, 0x49, 0x32, 0x47, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x78, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, + 0x76, 0x65, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x65, 0x64, 0x2e, 0xba, 0x48, 0x8e, 0x01, 0xba, 0x01, 0x8a, 0x01, 0x0a, 0x13, 0x72, + 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x65, 0x73, 0x12, 0x41, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x2e, 0x1a, 0x30, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, 0x6c, 0x6c, 0x28, + 0x72, 0x2c, 0x20, 0x72, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, + 0x30, 0x78, 0x29, 0x3f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, + 0x36, 0x34, 0x7d, 0x24, 0x27, 0x29, 0x29, 0x52, 0x11, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, + 0x6e, 0x67, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0xa3, 0x02, 0x0a, 0x10, 0x72, + 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x09, 0x42, 0xf7, 0x01, 0x92, 0x41, 0x6e, 0x32, 0x6c, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x52, + 0x4c, 0x50, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x72, 0x61, 0x77, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, + 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0xba, 0x48, 0x82, 0x01, 0xba, 0x01, 0x7f, + 0x0a, 0x10, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x3c, 0x72, 0x61, 0x77, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, + 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x72, + 0x61, 0x77, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x1a, 0x2d, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x2c, 0x20, 0x72, 0x2e, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x28, 0x30, 0x78, 0x29, 0x3f, 0x5b, + 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x24, 0x27, 0x29, 0x29, 0x52, + 0x0f, 0x72, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0xbf, 0x02, 0x0a, 0x0c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9b, 0x02, 0x92, 0x41, 0x9f, 0x01, 0x32, 0x93, + 0x01, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x74, + 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x66, 0x61, + 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, + 0x66, 0x20, 0x7a, 0x65, 0x72, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x63, 0x61, + 0x79, 0x65, 0x64, 0x20, 0x62, 0x69, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, + 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x2e, 0x8a, 0x01, 0x06, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0xba, 0x48, 0x75, + 0xba, 0x01, 0x72, 0x0a, 0x0c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x25, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, + 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x1a, 0x3b, 0x74, 0x68, 0x69, 0x73, 0x20, 0x3d, + 0x3d, 0x20, 0x27, 0x27, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x27, + 0x29, 0x20, 0x26, 0x26, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x74, 0x68, 0x69, 0x73, 0x29, 0x20, + 0x3e, 0x3d, 0x20, 0x30, 0x29, 0x52, 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x3a, 0xba, 0x04, 0x92, 0x41, 0xb6, 0x04, 0x0a, 0x95, 0x01, 0x2a, 0x0b, 0x42, 0x69, + 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x40, 0x55, 0x6e, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x20, 0x62, 0x69, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x6d, 0x65, 0x76, 0x2d, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0xd2, 0x01, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0xd2, 0x01, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0xd2, 0x01, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0xd2, 0x01, 0x13, 0x64, 0x65, + 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x32, 0x9b, 0x03, 0x7b, 0x22, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, + 0x3a, 0x20, 0x5b, 0x22, 0x66, 0x65, 0x34, 0x63, 0x62, 0x34, 0x37, 0x64, 0x62, 0x33, 0x36, 0x33, + 0x30, 0x35, 0x35, 0x31, 0x62, 0x65, 0x65, 0x64, 0x66, 0x62, 0x64, 0x30, 0x32, 0x61, 0x37, 0x31, + 0x65, 0x63, 0x63, 0x36, 0x39, 0x66, 0x64, 0x35, 0x39, 0x37, 0x35, 0x38, 0x65, 0x32, 0x62, 0x61, + 0x36, 0x39, 0x39, 0x36, 0x30, 0x36, 0x65, 0x32, 0x64, 0x35, 0x63, 0x37, 0x34, 0x32, 0x38, 0x34, + 0x66, 0x66, 0x61, 0x37, 0x22, 0x2c, 0x20, 0x22, 0x37, 0x31, 0x63, 0x31, 0x33, 0x34, 0x38, 0x66, + 0x32, 0x64, 0x37, 0x66, 0x66, 0x37, 0x65, 0x38, 0x31, 0x34, 0x66, 0x39, 0x63, 0x33, 0x36, 0x31, + 0x37, 0x39, 0x38, 0x33, 0x37, 0x30, 0x33, 0x34, 0x33, 0x35, 0x65, 0x61, 0x37, 0x34, 0x34, 0x36, + 0x64, 0x65, 0x34, 0x32, 0x30, 0x61, 0x65, 0x61, 0x63, 0x34, 0x38, 0x38, 0x62, 0x66, 0x31, 0x64, + 0x65, 0x33, 0x35, 0x37, 0x33, 0x37, 0x65, 0x38, 0x22, 0x5d, 0x2c, 0x20, 0x22, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x20, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x2c, 0x20, 0x22, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x20, 0x31, 0x36, + 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2c, 0x20, 0x22, 0x64, 0x65, 0x63, 0x61, 0x79, + 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, + 0x20, 0x31, 0x36, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2c, 0x20, 0x22, 0x72, 0x65, + 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x22, 0x3a, 0x20, 0x5b, 0x22, 0x66, 0x65, 0x34, 0x63, 0x62, 0x34, 0x37, 0x64, 0x62, 0x33, + 0x36, 0x33, 0x30, 0x35, 0x35, 0x31, 0x62, 0x65, 0x65, 0x64, 0x66, 0x62, 0x64, 0x30, 0x32, 0x61, + 0x37, 0x31, 0x65, 0x63, 0x63, 0x36, 0x39, 0x66, 0x64, 0x35, 0x39, 0x37, 0x35, 0x38, 0x65, 0x32, + 0x62, 0x61, 0x36, 0x39, 0x39, 0x36, 0x30, 0x36, 0x65, 0x32, 0x64, 0x35, 0x63, 0x37, 0x34, 0x32, + 0x38, 0x34, 0x66, 0x66, 0x61, 0x37, 0x22, 0x5d, 0x2c, 0x20, 0x22, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x20, 0x22, 0x35, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x22, + 0xc2, 0x0d, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x95, + 0x01, 0x0a, 0x09, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x42, 0x78, 0x92, 0x41, 0x75, 0x32, 0x61, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, + 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, + 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0x52, 0x08, 0x74, 0x78, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x0a, 0x62, 0x69, 0x64, 0x5f, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x70, 0x92, 0x41, 0x6d, + 0x32, 0x6b, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, + 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, + 0x68, 0x61, 0x73, 0x20, 0x61, 0x67, 0x72, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, + 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x52, 0x09, 0x62, + 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x6d, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x4a, + 0x92, 0x41, 0x47, 0x32, 0x45, 0x4d, 0x61, 0x78, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x7b, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x76, 0x65, 0x64, 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x4b, 0x92, 0x41, 0x48, 0x32, 0x46, 0x48, 0x65, 0x78, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, + 0x66, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x69, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, + 0x2e, 0x52, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x42, 0x69, 0x64, 0x44, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x12, 0x7d, 0x0a, 0x16, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, + 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x47, 0x92, 0x41, 0x44, 0x32, 0x42, 0x48, 0x65, 0x78, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, + 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, + 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x69, 0x64, 0x2e, 0x52, 0x14, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x42, 0x69, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x12, 0x62, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x35, + 0x92, 0x41, 0x32, 0x32, 0x30, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x67, 0x65, + 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x9e, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6b, 0x92, 0x41, 0x68, 0x32, 0x66, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, - 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x10, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, - 0x9e, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6b, - 0x92, 0x41, 0x68, 0x32, 0x66, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, - 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, - 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x13, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x88, 0x01, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x5d, 0x92, 0x41, 0x5a, - 0x32, 0x58, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, - 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x64, 0x0a, 0x15, 0x64, - 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x42, 0x30, 0x92, 0x41, 0x2d, 0x32, - 0x2b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, - 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x13, 0x64, 0x65, - 0x63, 0x61, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x5e, 0x0a, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x42, 0x2e, - 0x92, 0x41, 0x2b, 0x32, 0x29, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, - 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, - 0x65, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x11, - 0x64, 0x65, 0x63, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x63, 0x0a, 0x12, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x42, 0x34, 0x92, - 0x41, 0x31, 0x32, 0x2f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, - 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, - 0x65, 0x64, 0x2e, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x7c, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x0c, 0x20, - 0x03, 0x28, 0x09, 0x42, 0x4c, 0x92, 0x41, 0x49, 0x32, 0x47, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x78, 0x20, 0x68, - 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, - 0x20, 0x6f, 0x72, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x64, - 0x2e, 0x52, 0x11, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x78, 0x48, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x0c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x62, 0x92, 0x41, 0x5f, - 0x32, 0x5d, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x66, - 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, - 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0xc6, 0x07, 0x0a, - 0x06, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x53, 0x65, 0x6e, 0x64, 0x42, - 0x69, 0x64, 0x12, 0x11, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x69, 0x64, 0x1a, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, - 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x62, 0x69, 0x64, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x07, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, - 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x2f, 0x7b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, 0x12, 0x78, 0x0a, 0x0b, 0x41, 0x75, 0x74, - 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x22, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, 0x75, - 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x7d, 0x12, 0x8c, 0x01, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, - 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x26, 0x2e, 0x62, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, - 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x20, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x12, 0x80, 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x1a, 0x27, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x28, 0x2e, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, - 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x69, 0x6e, + 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x13, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x10, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x5d, 0x92, 0x41, 0x5a, 0x32, 0x58, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x2e, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x64, 0x0a, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x42, 0x30, 0x92, 0x41, 0x2d, 0x32, 0x2b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x69, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, + 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x5e, 0x0a, 0x13, 0x64, 0x65, 0x63, + 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x65, 0x63, + 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x11, 0x64, 0x65, 0x63, 0x61, 0x79, 0x45, 0x6e, 0x64, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x63, 0x0a, 0x12, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x03, 0x42, 0x34, 0x92, 0x41, 0x31, 0x32, 0x2f, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2e, 0x52, 0x11, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x7c, + 0x0a, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x42, 0x4c, 0x92, 0x41, 0x49, + 0x32, 0x47, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x78, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x62, 0x65, 0x20, 0x64, + 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x64, 0x2e, 0x52, 0x11, 0x72, 0x65, 0x76, 0x65, 0x72, + 0x74, 0x69, 0x6e, 0x67, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, + 0x0c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x62, 0x92, 0x41, 0x5f, 0x32, 0x5d, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, + 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x69, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x5e, 0x92, 0x41, 0x5b, 0x0a, 0x59, 0x2a, 0x12, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, + 0x43, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x20, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6e, + 0x6f, 0x64, 0x65, 0x2e, 0x22, 0xbe, 0x02, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x9f, 0x01, 0x0a, 0x0c, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x42, 0x7c, 0x92, 0x41, 0x79, 0x32, 0x77, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x69, 0x64, 0x20, 0x69, + 0x6e, 0x66, 0x6f, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, + 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, + 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x52, + 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x04, + 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x42, 0x20, 0x92, 0x41, 0x1d, 0x32, + 0x1b, 0x50, 0x61, 0x67, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x04, 0x70, 0x61, + 0x67, 0x65, 0x12, 0x51, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x05, 0x42, 0x3b, 0x92, 0x41, 0x38, 0x32, 0x36, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, + 0x66, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x70, 0x61, 0x67, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x73, 0x20, 0x35, 0x30, 0x52, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xe1, 0x07, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x97, 0x01, 0x0a, + 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x69, 0x64, + 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x42, 0x92, 0x41, 0x3f, 0x32, 0x3d, 0x4c, 0x69, 0x73, 0x74, 0x20, + 0x6f, 0x66, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x62, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x66, + 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x69, 0x64, + 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x42, + 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xc9, 0x03, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x38, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x86, 0x01, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6e, 0x92, 0x41, 0x6b, 0x32, + 0x69, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x50, 0x6f, 0x73, 0x73, 0x69, + 0x62, 0x6c, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3a, 0x20, 0x27, 0x70, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x27, 0x2c, + 0x20, 0x27, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x65, 0x74, 0x74, + 0x6c, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x27, 0x2c, + 0x20, 0x27, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x27, 0x2e, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x34, 0x92, 0x41, 0x31, 0x32, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x61, 0x62, 0x6f, + 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x73, 0x12, 0x48, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, + 0x6e, 0x74, 0x2e, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x06, + 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3c, 0x92, 0x41, + 0x39, 0x32, 0x37, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x61, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x52, 0x06, 0x72, 0x65, 0x66, 0x75, + 0x6e, 0x64, 0x1a, 0x87, 0x01, 0x0a, 0x07, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, + 0x0a, 0x03, 0x62, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x69, + 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x64, 0x52, 0x03, + 0x62, 0x69, 0x64, 0x12, 0x57, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, + 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0xda, 0x01, 0x0a, + 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x59, 0x0a, + 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x42, 0x36, 0x92, 0x41, 0x33, 0x32, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x69, 0x73, + 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x04, 0x62, 0x69, 0x64, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, + 0x42, 0x31, 0x92, 0x41, 0x2e, 0x32, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62, + 0x69, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x2e, 0x52, 0x04, 0x62, 0x69, 0x64, 0x73, 0x32, 0xbe, 0x09, 0x0a, 0x06, 0x42, 0x69, + 0x64, 0x64, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x69, 0x64, 0x12, + 0x11, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x69, 0x64, 0x1a, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x19, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x2f, 0x62, 0x69, 0x64, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x07, 0x44, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x62, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, 0x12, 0x78, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x20, + 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x5f, + 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, + 0x12, 0x8c, 0x01, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x26, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, + 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, + 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, + 0x80, 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x1a, 0x27, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, + 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, + 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x28, 0x2e, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, + 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, + 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x6c, 0x0a, 0x0a, + 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1f, 0x2e, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, + 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, + 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x66, 0x0a, 0x08, 0x57, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, - 0x6c, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1f, 0x2e, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x66, 0x0a, - 0x08, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x42, 0xaa, 0x02, 0x92, 0x41, 0x72, 0x12, 0x70, 0x0a, 0x0a, 0x42, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, 0x0a, 0x1b, 0x42, 0x75, 0x73, - 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x4c, 0x69, 0x63, - 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, - 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2f, 0x62, - 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, - 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x0a, 0x10, 0x63, - 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, - 0x0e, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2f, - 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, 0x0c, 0x42, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x42, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, - 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x0d, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x3a, 0x3a, - 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x77, 0x12, 0x7f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x1f, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x76, 0x31, + 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x64, 0x5f, + 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x7d, 0x12, 0x75, 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, + 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x73, 0x6c, 0x61, + 0x73, 0x68, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x42, 0xaa, 0x02, 0x92, 0x41, 0x72, + 0x12, 0x70, 0x0a, 0x0a, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, + 0x0a, 0x1b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, + 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, + 0x0c, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, + 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x42, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, + 0x61, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1601,61 +2005,76 @@ func file_bidderapi_v1_bidderapi_proto_rawDescGZIP() []byte { return file_bidderapi_v1_bidderapi_proto_rawDescData } -var file_bidderapi_v1_bidderapi_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_bidderapi_v1_bidderapi_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_bidderapi_v1_bidderapi_proto_goTypes = []interface{}{ - (*DepositRequest)(nil), // 0: bidderapi.v1.DepositRequest - (*DepositResponse)(nil), // 1: bidderapi.v1.DepositResponse - (*AutoDepositResponse)(nil), // 2: bidderapi.v1.AutoDepositResponse - (*AutoDepositStatusResponse)(nil), // 3: bidderapi.v1.AutoDepositStatusResponse - (*CancelAutoDepositRequest)(nil), // 4: bidderapi.v1.CancelAutoDepositRequest - (*CancelAutoDepositResponse)(nil), // 5: bidderapi.v1.CancelAutoDepositResponse - (*AutoDeposit)(nil), // 6: bidderapi.v1.AutoDeposit - (*EmptyMessage)(nil), // 7: bidderapi.v1.EmptyMessage - (*GetDepositRequest)(nil), // 8: bidderapi.v1.GetDepositRequest - (*WithdrawRequest)(nil), // 9: bidderapi.v1.WithdrawRequest - (*WithdrawResponse)(nil), // 10: bidderapi.v1.WithdrawResponse - (*WithdrawFromWindowsRequest)(nil), // 11: bidderapi.v1.WithdrawFromWindowsRequest - (*WithdrawFromWindowsResponse)(nil), // 12: bidderapi.v1.WithdrawFromWindowsResponse - (*Bid)(nil), // 13: bidderapi.v1.Bid - (*Commitment)(nil), // 14: bidderapi.v1.Commitment - (*wrapperspb.UInt64Value)(nil), // 15: google.protobuf.UInt64Value + (*DepositRequest)(nil), // 0: bidderapi.v1.DepositRequest + (*DepositResponse)(nil), // 1: bidderapi.v1.DepositResponse + (*AutoDepositResponse)(nil), // 2: bidderapi.v1.AutoDepositResponse + (*AutoDepositStatusResponse)(nil), // 3: bidderapi.v1.AutoDepositStatusResponse + (*CancelAutoDepositRequest)(nil), // 4: bidderapi.v1.CancelAutoDepositRequest + (*CancelAutoDepositResponse)(nil), // 5: bidderapi.v1.CancelAutoDepositResponse + (*AutoDeposit)(nil), // 6: bidderapi.v1.AutoDeposit + (*EmptyMessage)(nil), // 7: bidderapi.v1.EmptyMessage + (*GetDepositRequest)(nil), // 8: bidderapi.v1.GetDepositRequest + (*WithdrawRequest)(nil), // 9: bidderapi.v1.WithdrawRequest + (*WithdrawResponse)(nil), // 10: bidderapi.v1.WithdrawResponse + (*WithdrawFromWindowsRequest)(nil), // 11: bidderapi.v1.WithdrawFromWindowsRequest + (*WithdrawFromWindowsResponse)(nil), // 12: bidderapi.v1.WithdrawFromWindowsResponse + (*Bid)(nil), // 13: bidderapi.v1.Bid + (*Commitment)(nil), // 14: bidderapi.v1.Commitment + (*GetBidInfoRequest)(nil), // 15: bidderapi.v1.GetBidInfoRequest + (*GetBidInfoResponse)(nil), // 16: bidderapi.v1.GetBidInfoResponse + (*GetBidInfoResponse_CommitmentWithStatus)(nil), // 17: bidderapi.v1.GetBidInfoResponse.CommitmentWithStatus + (*GetBidInfoResponse_BidInfo)(nil), // 18: bidderapi.v1.GetBidInfoResponse.BidInfo + (*GetBidInfoResponse_BlockBidInfo)(nil), // 19: bidderapi.v1.GetBidInfoResponse.BlockBidInfo + (*wrapperspb.UInt64Value)(nil), // 20: google.protobuf.UInt64Value + (*wrapperspb.StringValue)(nil), // 21: google.protobuf.StringValue } var file_bidderapi_v1_bidderapi_proto_depIdxs = []int32{ - 15, // 0: bidderapi.v1.DepositRequest.window_number:type_name -> google.protobuf.UInt64Value - 15, // 1: bidderapi.v1.DepositRequest.block_number:type_name -> google.protobuf.UInt64Value - 15, // 2: bidderapi.v1.DepositResponse.window_number:type_name -> google.protobuf.UInt64Value - 15, // 3: bidderapi.v1.AutoDepositResponse.start_window_number:type_name -> google.protobuf.UInt64Value + 20, // 0: bidderapi.v1.DepositRequest.window_number:type_name -> google.protobuf.UInt64Value + 20, // 1: bidderapi.v1.DepositRequest.block_number:type_name -> google.protobuf.UInt64Value + 20, // 2: bidderapi.v1.DepositResponse.window_number:type_name -> google.protobuf.UInt64Value + 20, // 3: bidderapi.v1.AutoDepositResponse.start_window_number:type_name -> google.protobuf.UInt64Value 6, // 4: bidderapi.v1.AutoDepositStatusResponse.window_balances:type_name -> bidderapi.v1.AutoDeposit - 15, // 5: bidderapi.v1.CancelAutoDepositResponse.window_numbers:type_name -> google.protobuf.UInt64Value - 15, // 6: bidderapi.v1.AutoDeposit.window_number:type_name -> google.protobuf.UInt64Value - 15, // 7: bidderapi.v1.AutoDeposit.start_block_number:type_name -> google.protobuf.UInt64Value - 15, // 8: bidderapi.v1.AutoDeposit.end_block_number:type_name -> google.protobuf.UInt64Value - 15, // 9: bidderapi.v1.GetDepositRequest.window_number:type_name -> google.protobuf.UInt64Value - 15, // 10: bidderapi.v1.WithdrawRequest.window_number:type_name -> google.protobuf.UInt64Value - 15, // 11: bidderapi.v1.WithdrawResponse.window_number:type_name -> google.protobuf.UInt64Value - 15, // 12: bidderapi.v1.WithdrawFromWindowsRequest.window_numbers:type_name -> google.protobuf.UInt64Value + 20, // 5: bidderapi.v1.CancelAutoDepositResponse.window_numbers:type_name -> google.protobuf.UInt64Value + 20, // 6: bidderapi.v1.AutoDeposit.window_number:type_name -> google.protobuf.UInt64Value + 20, // 7: bidderapi.v1.AutoDeposit.start_block_number:type_name -> google.protobuf.UInt64Value + 20, // 8: bidderapi.v1.AutoDeposit.end_block_number:type_name -> google.protobuf.UInt64Value + 20, // 9: bidderapi.v1.GetDepositRequest.window_number:type_name -> google.protobuf.UInt64Value + 20, // 10: bidderapi.v1.WithdrawRequest.window_number:type_name -> google.protobuf.UInt64Value + 20, // 11: bidderapi.v1.WithdrawResponse.window_number:type_name -> google.protobuf.UInt64Value + 20, // 12: bidderapi.v1.WithdrawFromWindowsRequest.window_numbers:type_name -> google.protobuf.UInt64Value 10, // 13: bidderapi.v1.WithdrawFromWindowsResponse.withdraw_responses:type_name -> bidderapi.v1.WithdrawResponse - 13, // 14: bidderapi.v1.Bidder.SendBid:input_type -> bidderapi.v1.Bid - 0, // 15: bidderapi.v1.Bidder.Deposit:input_type -> bidderapi.v1.DepositRequest - 0, // 16: bidderapi.v1.Bidder.AutoDeposit:input_type -> bidderapi.v1.DepositRequest - 4, // 17: bidderapi.v1.Bidder.CancelAutoDeposit:input_type -> bidderapi.v1.CancelAutoDepositRequest - 7, // 18: bidderapi.v1.Bidder.AutoDepositStatus:input_type -> bidderapi.v1.EmptyMessage - 11, // 19: bidderapi.v1.Bidder.WithdrawFromWindows:input_type -> bidderapi.v1.WithdrawFromWindowsRequest - 8, // 20: bidderapi.v1.Bidder.GetDeposit:input_type -> bidderapi.v1.GetDepositRequest - 9, // 21: bidderapi.v1.Bidder.Withdraw:input_type -> bidderapi.v1.WithdrawRequest - 14, // 22: bidderapi.v1.Bidder.SendBid:output_type -> bidderapi.v1.Commitment - 1, // 23: bidderapi.v1.Bidder.Deposit:output_type -> bidderapi.v1.DepositResponse - 2, // 24: bidderapi.v1.Bidder.AutoDeposit:output_type -> bidderapi.v1.AutoDepositResponse - 5, // 25: bidderapi.v1.Bidder.CancelAutoDeposit:output_type -> bidderapi.v1.CancelAutoDepositResponse - 3, // 26: bidderapi.v1.Bidder.AutoDepositStatus:output_type -> bidderapi.v1.AutoDepositStatusResponse - 12, // 27: bidderapi.v1.Bidder.WithdrawFromWindows:output_type -> bidderapi.v1.WithdrawFromWindowsResponse - 1, // 28: bidderapi.v1.Bidder.GetDeposit:output_type -> bidderapi.v1.DepositResponse - 10, // 29: bidderapi.v1.Bidder.Withdraw:output_type -> bidderapi.v1.WithdrawResponse - 22, // [22:30] is the sub-list for method output_type - 14, // [14:22] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 19, // 14: bidderapi.v1.GetBidInfoResponse.block_bid_info:type_name -> bidderapi.v1.GetBidInfoResponse.BlockBidInfo + 14, // 15: bidderapi.v1.GetBidInfoResponse.CommitmentWithStatus.commitment:type_name -> bidderapi.v1.Commitment + 13, // 16: bidderapi.v1.GetBidInfoResponse.BidInfo.bid:type_name -> bidderapi.v1.Bid + 17, // 17: bidderapi.v1.GetBidInfoResponse.BidInfo.commitments:type_name -> bidderapi.v1.GetBidInfoResponse.CommitmentWithStatus + 18, // 18: bidderapi.v1.GetBidInfoResponse.BlockBidInfo.bids:type_name -> bidderapi.v1.GetBidInfoResponse.BidInfo + 13, // 19: bidderapi.v1.Bidder.SendBid:input_type -> bidderapi.v1.Bid + 0, // 20: bidderapi.v1.Bidder.Deposit:input_type -> bidderapi.v1.DepositRequest + 0, // 21: bidderapi.v1.Bidder.AutoDeposit:input_type -> bidderapi.v1.DepositRequest + 4, // 22: bidderapi.v1.Bidder.CancelAutoDeposit:input_type -> bidderapi.v1.CancelAutoDepositRequest + 7, // 23: bidderapi.v1.Bidder.AutoDepositStatus:input_type -> bidderapi.v1.EmptyMessage + 11, // 24: bidderapi.v1.Bidder.WithdrawFromWindows:input_type -> bidderapi.v1.WithdrawFromWindowsRequest + 8, // 25: bidderapi.v1.Bidder.GetDeposit:input_type -> bidderapi.v1.GetDepositRequest + 9, // 26: bidderapi.v1.Bidder.Withdraw:input_type -> bidderapi.v1.WithdrawRequest + 15, // 27: bidderapi.v1.Bidder.GetBidInfo:input_type -> bidderapi.v1.GetBidInfoRequest + 7, // 28: bidderapi.v1.Bidder.ClaimSlashedFunds:input_type -> bidderapi.v1.EmptyMessage + 14, // 29: bidderapi.v1.Bidder.SendBid:output_type -> bidderapi.v1.Commitment + 1, // 30: bidderapi.v1.Bidder.Deposit:output_type -> bidderapi.v1.DepositResponse + 2, // 31: bidderapi.v1.Bidder.AutoDeposit:output_type -> bidderapi.v1.AutoDepositResponse + 5, // 32: bidderapi.v1.Bidder.CancelAutoDeposit:output_type -> bidderapi.v1.CancelAutoDepositResponse + 3, // 33: bidderapi.v1.Bidder.AutoDepositStatus:output_type -> bidderapi.v1.AutoDepositStatusResponse + 12, // 34: bidderapi.v1.Bidder.WithdrawFromWindows:output_type -> bidderapi.v1.WithdrawFromWindowsResponse + 1, // 35: bidderapi.v1.Bidder.GetDeposit:output_type -> bidderapi.v1.DepositResponse + 10, // 36: bidderapi.v1.Bidder.Withdraw:output_type -> bidderapi.v1.WithdrawResponse + 16, // 37: bidderapi.v1.Bidder.GetBidInfo:output_type -> bidderapi.v1.GetBidInfoResponse + 21, // 38: bidderapi.v1.Bidder.ClaimSlashedFunds:output_type -> google.protobuf.StringValue + 29, // [29:39] is the sub-list for method output_type + 19, // [19:29] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_bidderapi_v1_bidderapi_proto_init() } @@ -1844,6 +2263,66 @@ func file_bidderapi_v1_bidderapi_proto_init() { return nil } } + file_bidderapi_v1_bidderapi_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBidInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bidderapi_v1_bidderapi_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBidInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bidderapi_v1_bidderapi_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBidInfoResponse_CommitmentWithStatus); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bidderapi_v1_bidderapi_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBidInfoResponse_BidInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bidderapi_v1_bidderapi_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBidInfoResponse_BlockBidInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1851,7 +2330,7 @@ func file_bidderapi_v1_bidderapi_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bidderapi_v1_bidderapi_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 20, NumExtensions: 0, NumServices: 1, }, diff --git a/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go b/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go index 8cdb1e90a..03f084c65 100644 --- a/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go +++ b/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go @@ -299,6 +299,76 @@ func local_request_Bidder_Withdraw_0(ctx context.Context, marshaler runtime.Mars return msg, metadata, err } +var filter_Bidder_GetBidInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{"block_number": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} + +func request_Bidder_GetBidInfo_0(ctx context.Context, marshaler runtime.Marshaler, client BidderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetBidInfoRequest + metadata runtime.ServerMetadata + err error + ) + io.Copy(io.Discard, req.Body) + val, ok := pathParams["block_number"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "block_number") + } + protoReq.BlockNumber, err = runtime.Int64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "block_number", err) + } + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Bidder_GetBidInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetBidInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_Bidder_GetBidInfo_0(ctx context.Context, marshaler runtime.Marshaler, server BidderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetBidInfoRequest + metadata runtime.ServerMetadata + err error + ) + val, ok := pathParams["block_number"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "block_number") + } + protoReq.BlockNumber, err = runtime.Int64(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "block_number", err) + } + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Bidder_GetBidInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetBidInfo(ctx, &protoReq) + return msg, metadata, err +} + +func request_Bidder_ClaimSlashedFunds_0(ctx context.Context, marshaler runtime.Marshaler, client BidderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq EmptyMessage + metadata runtime.ServerMetadata + ) + io.Copy(io.Discard, req.Body) + msg, err := client.ClaimSlashedFunds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_Bidder_ClaimSlashedFunds_0(ctx context.Context, marshaler runtime.Marshaler, server BidderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq EmptyMessage + metadata runtime.ServerMetadata + ) + msg, err := server.ClaimSlashedFunds(ctx, &protoReq) + return msg, metadata, err +} + // RegisterBidderHandlerServer registers the http handlers for service Bidder to "mux". // UnaryRPC :call BidderServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -451,6 +521,46 @@ func RegisterBidderHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser } forward_Bidder_Withdraw_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_Bidder_GetBidInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/bidderapi.v1.Bidder/GetBidInfo", runtime.WithHTTPPathPattern("/v1/bidder/get_bid_info/{block_number}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Bidder_GetBidInfo_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_Bidder_GetBidInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_Bidder_ClaimSlashedFunds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/bidderapi.v1.Bidder/ClaimSlashedFunds", runtime.WithHTTPPathPattern("/v1/bidder/claim_slashed_funds")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Bidder_ClaimSlashedFunds_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_Bidder_ClaimSlashedFunds_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -627,6 +737,40 @@ func RegisterBidderHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli } forward_Bidder_Withdraw_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_Bidder_GetBidInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/bidderapi.v1.Bidder/GetBidInfo", runtime.WithHTTPPathPattern("/v1/bidder/get_bid_info/{block_number}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Bidder_GetBidInfo_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_Bidder_GetBidInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_Bidder_ClaimSlashedFunds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/bidderapi.v1.Bidder/ClaimSlashedFunds", runtime.WithHTTPPathPattern("/v1/bidder/claim_slashed_funds")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Bidder_ClaimSlashedFunds_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_Bidder_ClaimSlashedFunds_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -639,6 +783,8 @@ var ( pattern_Bidder_WithdrawFromWindows_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "withdraw_from_windows"}, "")) pattern_Bidder_GetDeposit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "get_deposit"}, "")) pattern_Bidder_Withdraw_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "withdraw"}, "")) + pattern_Bidder_GetBidInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "bidder", "get_bid_info", "block_number"}, "")) + pattern_Bidder_ClaimSlashedFunds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "claim_slashed_funds"}, "")) ) var ( @@ -650,4 +796,6 @@ var ( forward_Bidder_WithdrawFromWindows_0 = runtime.ForwardResponseMessage forward_Bidder_GetDeposit_0 = runtime.ForwardResponseMessage forward_Bidder_Withdraw_0 = runtime.ForwardResponseMessage + forward_Bidder_GetBidInfo_0 = runtime.ForwardResponseMessage + forward_Bidder_ClaimSlashedFunds_0 = runtime.ForwardResponseMessage ) diff --git a/p2p/gen/go/bidderapi/v1/bidderapi_grpc.pb.go b/p2p/gen/go/bidderapi/v1/bidderapi_grpc.pb.go index 9afac40b8..91fbc1f6c 100644 --- a/p2p/gen/go/bidderapi/v1/bidderapi_grpc.pb.go +++ b/p2p/gen/go/bidderapi/v1/bidderapi_grpc.pb.go @@ -11,6 +11,7 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" ) // This is a compile-time assertion to ensure that this generated file @@ -27,6 +28,8 @@ const ( Bidder_WithdrawFromWindows_FullMethodName = "/bidderapi.v1.Bidder/WithdrawFromWindows" Bidder_GetDeposit_FullMethodName = "/bidderapi.v1.Bidder/GetDeposit" Bidder_Withdraw_FullMethodName = "/bidderapi.v1.Bidder/Withdraw" + Bidder_GetBidInfo_FullMethodName = "/bidderapi.v1.Bidder/GetBidInfo" + Bidder_ClaimSlashedFunds_FullMethodName = "/bidderapi.v1.Bidder/ClaimSlashedFunds" ) // BidderClient is the client API for Bidder service. @@ -80,6 +83,16 @@ type BidderClient interface { // // Withdraw is called by the bidder to withdraw deposit from the bidder registry. Withdraw(ctx context.Context, in *WithdrawRequest, opts ...grpc.CallOption) (*WithdrawResponse, error) + // GetBidInfo + // + // GetBidInfo is called by the bidder to get the bid information. If block number is not specified, + // all known block numbers are returned in the ascending order. + GetBidInfo(ctx context.Context, in *GetBidInfoRequest, opts ...grpc.CallOption) (*GetBidInfoResponse, error) + // ClaimSlashedFunds + // + // ClaimSlashedFunds is called by the bidder to claim slashed funds from the provider. The response + // will show the amount claimed if any in wei. + ClaimSlashedFunds(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) } type bidderClient struct { @@ -179,6 +192,26 @@ func (c *bidderClient) Withdraw(ctx context.Context, in *WithdrawRequest, opts . return out, nil } +func (c *bidderClient) GetBidInfo(ctx context.Context, in *GetBidInfoRequest, opts ...grpc.CallOption) (*GetBidInfoResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetBidInfoResponse) + err := c.cc.Invoke(ctx, Bidder_GetBidInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *bidderClient) ClaimSlashedFunds(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(wrapperspb.StringValue) + err := c.cc.Invoke(ctx, Bidder_ClaimSlashedFunds_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // BidderServer is the server API for Bidder service. // All implementations must embed UnimplementedBidderServer // for forward compatibility. @@ -230,6 +263,16 @@ type BidderServer interface { // // Withdraw is called by the bidder to withdraw deposit from the bidder registry. Withdraw(context.Context, *WithdrawRequest) (*WithdrawResponse, error) + // GetBidInfo + // + // GetBidInfo is called by the bidder to get the bid information. If block number is not specified, + // all known block numbers are returned in the ascending order. + GetBidInfo(context.Context, *GetBidInfoRequest) (*GetBidInfoResponse, error) + // ClaimSlashedFunds + // + // ClaimSlashedFunds is called by the bidder to claim slashed funds from the provider. The response + // will show the amount claimed if any in wei. + ClaimSlashedFunds(context.Context, *EmptyMessage) (*wrapperspb.StringValue, error) mustEmbedUnimplementedBidderServer() } @@ -264,6 +307,12 @@ func (UnimplementedBidderServer) GetDeposit(context.Context, *GetDepositRequest) func (UnimplementedBidderServer) Withdraw(context.Context, *WithdrawRequest) (*WithdrawResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Withdraw not implemented") } +func (UnimplementedBidderServer) GetBidInfo(context.Context, *GetBidInfoRequest) (*GetBidInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBidInfo not implemented") +} +func (UnimplementedBidderServer) ClaimSlashedFunds(context.Context, *EmptyMessage) (*wrapperspb.StringValue, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClaimSlashedFunds not implemented") +} func (UnimplementedBidderServer) mustEmbedUnimplementedBidderServer() {} func (UnimplementedBidderServer) testEmbeddedByValue() {} @@ -422,6 +471,42 @@ func _Bidder_Withdraw_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _Bidder_GetBidInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBidInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BidderServer).GetBidInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Bidder_GetBidInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BidderServer).GetBidInfo(ctx, req.(*GetBidInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Bidder_ClaimSlashedFunds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EmptyMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BidderServer).ClaimSlashedFunds(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Bidder_ClaimSlashedFunds_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BidderServer).ClaimSlashedFunds(ctx, req.(*EmptyMessage)) + } + return interceptor(ctx, in, info, handler) +} + // Bidder_ServiceDesc is the grpc.ServiceDesc for Bidder service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -457,6 +542,14 @@ var Bidder_ServiceDesc = grpc.ServiceDesc{ MethodName: "Withdraw", Handler: _Bidder_Withdraw_Handler, }, + { + MethodName: "GetBidInfo", + Handler: _Bidder_GetBidInfo_Handler, + }, + { + MethodName: "ClaimSlashedFunds", + Handler: _Bidder_ClaimSlashedFunds_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/p2p/gen/go/providerapi/v1/providerapi.pb.go b/p2p/gen/go/providerapi/v1/providerapi.pb.go index f48e67af0..7dfb0d270 100644 --- a/p2p/gen/go/providerapi/v1/providerapi.pb.go +++ b/p2p/gen/go/providerapi/v1/providerapi.pb.go @@ -496,6 +496,314 @@ func (x *BidResponse) GetDispatchTimestamp() int64 { return 0 } +type GetCommitmentInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockNumber int64 `protobuf:"varint,1,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + Limit int32 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (x *GetCommitmentInfoRequest) Reset() { + *x = GetCommitmentInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetCommitmentInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCommitmentInfoRequest) ProtoMessage() {} + +func (x *GetCommitmentInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetCommitmentInfoRequest.ProtoReflect.Descriptor instead. +func (*GetCommitmentInfoRequest) Descriptor() ([]byte, []int) { + return file_providerapi_v1_providerapi_proto_rawDescGZIP(), []int{7} +} + +func (x *GetCommitmentInfoRequest) GetBlockNumber() int64 { + if x != nil { + return x.BlockNumber + } + return 0 +} + +func (x *GetCommitmentInfoRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GetCommitmentInfoRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +type CommitmentInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Commitments []*CommitmentInfoResponse_BlockCommitments `protobuf:"bytes,1,rep,name=commitments,proto3" json:"commitments,omitempty"` +} + +func (x *CommitmentInfoResponse) Reset() { + *x = CommitmentInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommitmentInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommitmentInfoResponse) ProtoMessage() {} + +func (x *CommitmentInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommitmentInfoResponse.ProtoReflect.Descriptor instead. +func (*CommitmentInfoResponse) Descriptor() ([]byte, []int) { + return file_providerapi_v1_providerapi_proto_rawDescGZIP(), []int{8} +} + +func (x *CommitmentInfoResponse) GetCommitments() []*CommitmentInfoResponse_BlockCommitments { + if x != nil { + return x.Commitments + } + return nil +} + +type CommitmentInfoResponse_Commitment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TxnHashes []string `protobuf:"bytes,1,rep,name=txn_hashes,json=txnHashes,proto3" json:"txn_hashes,omitempty"` + RevertableTxnHashes []string `protobuf:"bytes,2,rep,name=revertable_txn_hashes,json=revertableTxnHashes,proto3" json:"revertable_txn_hashes,omitempty"` + Amount string `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount,omitempty"` + BlockNumber int64 `protobuf:"varint,4,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + ProviderAddress string `protobuf:"bytes,5,opt,name=provider_address,json=providerAddress,proto3" json:"provider_address,omitempty"` + DecayStartTimestamp int64 `protobuf:"varint,6,opt,name=decay_start_timestamp,json=decayStartTimestamp,proto3" json:"decay_start_timestamp,omitempty"` + DecayEndTimestamp int64 `protobuf:"varint,7,opt,name=decay_end_timestamp,json=decayEndTimestamp,proto3" json:"decay_end_timestamp,omitempty"` + DispatchTimestamp int64 `protobuf:"varint,8,opt,name=dispatch_timestamp,json=dispatchTimestamp,proto3" json:"dispatch_timestamp,omitempty"` + SlashAmount string `protobuf:"bytes,9,opt,name=slash_amount,json=slashAmount,proto3" json:"slash_amount,omitempty"` + Status string `protobuf:"bytes,10,opt,name=status,proto3" json:"status,omitempty"` + Details string `protobuf:"bytes,11,opt,name=details,proto3" json:"details,omitempty"` + Payment string `protobuf:"bytes,12,opt,name=payment,proto3" json:"payment,omitempty"` + Refund string `protobuf:"bytes,13,opt,name=refund,proto3" json:"refund,omitempty"` +} + +func (x *CommitmentInfoResponse_Commitment) Reset() { + *x = CommitmentInfoResponse_Commitment{} + if protoimpl.UnsafeEnabled { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommitmentInfoResponse_Commitment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommitmentInfoResponse_Commitment) ProtoMessage() {} + +func (x *CommitmentInfoResponse_Commitment) ProtoReflect() protoreflect.Message { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommitmentInfoResponse_Commitment.ProtoReflect.Descriptor instead. +func (*CommitmentInfoResponse_Commitment) Descriptor() ([]byte, []int) { + return file_providerapi_v1_providerapi_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *CommitmentInfoResponse_Commitment) GetTxnHashes() []string { + if x != nil { + return x.TxnHashes + } + return nil +} + +func (x *CommitmentInfoResponse_Commitment) GetRevertableTxnHashes() []string { + if x != nil { + return x.RevertableTxnHashes + } + return nil +} + +func (x *CommitmentInfoResponse_Commitment) GetAmount() string { + if x != nil { + return x.Amount + } + return "" +} + +func (x *CommitmentInfoResponse_Commitment) GetBlockNumber() int64 { + if x != nil { + return x.BlockNumber + } + return 0 +} + +func (x *CommitmentInfoResponse_Commitment) GetProviderAddress() string { + if x != nil { + return x.ProviderAddress + } + return "" +} + +func (x *CommitmentInfoResponse_Commitment) GetDecayStartTimestamp() int64 { + if x != nil { + return x.DecayStartTimestamp + } + return 0 +} + +func (x *CommitmentInfoResponse_Commitment) GetDecayEndTimestamp() int64 { + if x != nil { + return x.DecayEndTimestamp + } + return 0 +} + +func (x *CommitmentInfoResponse_Commitment) GetDispatchTimestamp() int64 { + if x != nil { + return x.DispatchTimestamp + } + return 0 +} + +func (x *CommitmentInfoResponse_Commitment) GetSlashAmount() string { + if x != nil { + return x.SlashAmount + } + return "" +} + +func (x *CommitmentInfoResponse_Commitment) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *CommitmentInfoResponse_Commitment) GetDetails() string { + if x != nil { + return x.Details + } + return "" +} + +func (x *CommitmentInfoResponse_Commitment) GetPayment() string { + if x != nil { + return x.Payment + } + return "" +} + +func (x *CommitmentInfoResponse_Commitment) GetRefund() string { + if x != nil { + return x.Refund + } + return "" +} + +type CommitmentInfoResponse_BlockCommitments struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockNumber int64 `protobuf:"varint,1,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + Commitments []*CommitmentInfoResponse_Commitment `protobuf:"bytes,2,rep,name=commitments,proto3" json:"commitments,omitempty"` +} + +func (x *CommitmentInfoResponse_BlockCommitments) Reset() { + *x = CommitmentInfoResponse_BlockCommitments{} + if protoimpl.UnsafeEnabled { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommitmentInfoResponse_BlockCommitments) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommitmentInfoResponse_BlockCommitments) ProtoMessage() {} + +func (x *CommitmentInfoResponse_BlockCommitments) ProtoReflect() protoreflect.Message { + mi := &file_providerapi_v1_providerapi_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommitmentInfoResponse_BlockCommitments.ProtoReflect.Descriptor instead. +func (*CommitmentInfoResponse_BlockCommitments) Descriptor() ([]byte, []int) { + return file_providerapi_v1_providerapi_proto_rawDescGZIP(), []int{8, 1} +} + +func (x *CommitmentInfoResponse_BlockCommitments) GetBlockNumber() int64 { + if x != nil { + return x.BlockNumber + } + return 0 +} + +func (x *CommitmentInfoResponse_BlockCommitments) GetCommitments() []*CommitmentInfoResponse_Commitment { + if x != nil { + return x.Commitments + } + return nil +} + var File_providerapi_v1_providerapi_proto protoreflect.FileDescriptor var file_providerapi_v1_providerapi_proto_rawDesc = []byte{ @@ -827,93 +1135,250 @@ var file_providerapi_v1_providerapi_proto_rawDesc = []byte{ 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x22, 0x2c, 0x20, 0x22, 0x64, 0x65, 0x63, 0x61, 0x79, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x20, 0x31, 0x32, 0x33, 0x34, 0x35, - 0x36, 0x37, 0x38, 0x39, 0x30, 0x7d, 0x32, 0x9a, 0x08, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x12, 0x65, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x42, 0x69, - 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x69, 0x64, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, - 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x5f, 0x62, 0x69, 0x64, 0x73, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x11, 0x53, 0x65, - 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x42, 0x69, 0x64, 0x73, 0x12, - 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x69, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1c, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x65, 0x64, 0x5f, 0x62, 0x69, 0x64, 0x73, 0x28, 0x01, 0x12, 0x69, 0x0a, 0x05, 0x53, 0x74, 0x61, - 0x6b, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2f, 0x7b, 0x61, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x7d, 0x12, 0x67, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x6b, 0x65, - 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1d, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x74, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x6e, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x6b, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1c, 0x12, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, - 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x76, 0x0a, - 0x0d, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x22, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, - 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x63, 0x0a, 0x07, 0x55, 0x6e, 0x73, 0x74, 0x61, 0x6b, 0x65, - 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, + 0x36, 0x37, 0x38, 0x39, 0x30, 0x7d, 0x22, 0xd9, 0x03, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0xb0, 0x01, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x8c, 0x01, 0x92, 0x41, 0x88, + 0x01, 0x32, 0x85, 0x01, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, + 0x69, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, + 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x42, 0x38, 0x92, 0x41, 0x35, 0x32, 0x33, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, + 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x30, 0x2e, 0x52, 0x04, + 0x70, 0x61, 0x67, 0x65, 0x12, 0x6c, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x42, 0x56, 0x92, 0x41, 0x53, 0x32, 0x51, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x20, 0x70, 0x65, 0x72, 0x20, 0x70, 0x61, 0x67, 0x65, 0x2e, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x30, 0x30, 0x2e, 0x52, 0x05, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x3a, 0x4e, 0x92, 0x41, 0x4b, 0x0a, 0x49, 0x2a, 0x1b, 0x47, 0x65, 0x74, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0x2a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, + 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x22, 0xdc, 0x0e, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, + 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x2b, 0x92, 0x41, + 0x28, 0x32, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0xe6, 0x0a, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x71, 0x0a, 0x0a, 0x74, 0x78, 0x6e, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x52, 0x92, 0x41, 0x4f, 0x32, 0x3b, + 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, + 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0x52, 0x09, 0x74, + 0x78, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x81, 0x01, 0x0a, 0x15, 0x72, 0x65, 0x76, + 0x65, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x78, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x4d, 0x92, 0x41, 0x4a, 0x32, 0x36, 0x4c, + 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, + 0x76, 0x65, 0x72, 0x74, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, + 0x2d, 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0x52, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x54, 0x78, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x53, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3b, 0x92, 0x41, + 0x38, 0x32, 0x2d, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, + 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2e, + 0x8a, 0x01, 0x06, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x55, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x42, 0x32, 0x92, 0x41, 0x2f, 0x32, 0x2d, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, + 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, + 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x88, 0x01, 0x0a, 0x10, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x5d, 0x92, 0x41, 0x5a, 0x32, 0x58, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x2e, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x64, 0x0a, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x42, 0x30, 0x92, 0x41, 0x2d, 0x32, 0x2b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x69, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, + 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x5e, 0x0a, 0x13, 0x64, 0x65, 0x63, + 0x61, 0x79, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x65, 0x63, + 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x11, 0x64, 0x65, 0x63, 0x61, 0x79, 0x45, 0x6e, 0x64, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x63, 0x0a, 0x12, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x03, 0x42, 0x34, 0x92, 0x41, 0x31, 0x32, 0x2f, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2e, 0x52, 0x11, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x85, + 0x01, 0x0a, 0x0c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x62, 0x92, 0x41, 0x5f, 0x32, 0x5d, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, + 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x86, 0x01, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6e, 0x92, 0x41, 0x6b, 0x32, 0x69, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x50, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, + 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3a, 0x20, 0x27, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x6f, + 0x70, 0x65, 0x6e, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, + 0x27, 0x2c, 0x20, 0x27, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x66, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x27, 0x2e, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x4e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x34, 0x92, 0x41, 0x31, 0x32, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, + 0x48, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, + 0x52, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x06, 0x72, 0x65, 0x66, + 0x75, 0x6e, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3c, 0x92, 0x41, 0x39, 0x32, 0x37, + 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, + 0x20, 0x77, 0x65, 0x69, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x61, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x52, 0x06, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x1a, + 0xef, 0x01, 0x0a, 0x10, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x42, 0x35, 0x92, 0x41, 0x32, 0x32, + 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, + 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x80, + 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x2b, 0x92, 0x41, 0x28, 0x32, 0x26, 0x4c, 0x69, + 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x2e, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x3a, 0x5e, 0x92, 0x41, 0x5b, 0x0a, 0x59, 0x2a, 0x18, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x32, 0x2f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0xd2, 0x01, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x32, 0xac, 0x09, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x65, + 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x42, 0x69, 0x64, 0x73, 0x12, 0x1c, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x13, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x64, + 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x62, + 0x69, 0x64, 0x73, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x42, 0x69, 0x64, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, + 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x73, + 0x65, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x69, + 0x64, 0x73, 0x28, 0x01, 0x12, 0x69, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x74, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, + 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x2f, 0x7b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, 0x12, + 0x67, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, + 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x67, + 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, + 0x69, 0x6e, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x76, + 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x6d, + 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x76, 0x0a, 0x0d, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, + 0x12, 0x63, 0x0a, 0x07, 0x55, 0x6e, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, + 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x75, 0x6e, + 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x7b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, + 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x67, + 0x65, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x12, 0x89, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x1c, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x22, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x22, 0x25, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x8f, + 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1c, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x16, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x2f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x12, 0x7b, 0x0a, 0x11, 0x47, 0x65, - 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, - 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1e, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x89, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x22, 0x25, 0x2f, 0x76, - 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x42, 0xbc, 0x02, 0x92, 0x41, 0x74, 0x12, 0x72, 0x0a, 0x0c, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, 0x0a, 0x1b, 0x42, 0x75, 0x73, - 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x4c, 0x69, 0x63, - 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, - 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2f, 0x62, - 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, - 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x0a, 0x12, 0x63, - 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x42, 0x10, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x58, - 0x58, 0xaa, 0x02, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, - 0x56, 0x31, 0xca, 0x02, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x0f, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x3a, 0x3a, - 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, + 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, + 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, + 0x42, 0xbc, 0x02, 0x92, 0x41, 0x74, 0x12, 0x72, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, 0x0a, 0x1b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, + 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, + 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, + 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, + 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x0b, 0x31, + 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x10, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, + 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, + 0xe2, 0x02, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -929,42 +1394,50 @@ func file_providerapi_v1_providerapi_proto_rawDescGZIP() []byte { } var file_providerapi_v1_providerapi_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_providerapi_v1_providerapi_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_providerapi_v1_providerapi_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_providerapi_v1_providerapi_proto_goTypes = []interface{}{ - (BidResponse_Status)(0), // 0: providerapi.v1.BidResponse.Status - (*StakeRequest)(nil), // 1: providerapi.v1.StakeRequest - (*StakeResponse)(nil), // 2: providerapi.v1.StakeResponse - (*WithdrawalResponse)(nil), // 3: providerapi.v1.WithdrawalResponse - (*RewardResponse)(nil), // 4: providerapi.v1.RewardResponse - (*EmptyMessage)(nil), // 5: providerapi.v1.EmptyMessage - (*Bid)(nil), // 6: providerapi.v1.Bid - (*BidResponse)(nil), // 7: providerapi.v1.BidResponse + (BidResponse_Status)(0), // 0: providerapi.v1.BidResponse.Status + (*StakeRequest)(nil), // 1: providerapi.v1.StakeRequest + (*StakeResponse)(nil), // 2: providerapi.v1.StakeResponse + (*WithdrawalResponse)(nil), // 3: providerapi.v1.WithdrawalResponse + (*RewardResponse)(nil), // 4: providerapi.v1.RewardResponse + (*EmptyMessage)(nil), // 5: providerapi.v1.EmptyMessage + (*Bid)(nil), // 6: providerapi.v1.Bid + (*BidResponse)(nil), // 7: providerapi.v1.BidResponse + (*GetCommitmentInfoRequest)(nil), // 8: providerapi.v1.GetCommitmentInfoRequest + (*CommitmentInfoResponse)(nil), // 9: providerapi.v1.CommitmentInfoResponse + (*CommitmentInfoResponse_Commitment)(nil), // 10: providerapi.v1.CommitmentInfoResponse.Commitment + (*CommitmentInfoResponse_BlockCommitments)(nil), // 11: providerapi.v1.CommitmentInfoResponse.BlockCommitments } var file_providerapi_v1_providerapi_proto_depIdxs = []int32{ 0, // 0: providerapi.v1.BidResponse.status:type_name -> providerapi.v1.BidResponse.Status - 5, // 1: providerapi.v1.Provider.ReceiveBids:input_type -> providerapi.v1.EmptyMessage - 7, // 2: providerapi.v1.Provider.SendProcessedBids:input_type -> providerapi.v1.BidResponse - 1, // 3: providerapi.v1.Provider.Stake:input_type -> providerapi.v1.StakeRequest - 5, // 4: providerapi.v1.Provider.GetStake:input_type -> providerapi.v1.EmptyMessage - 5, // 5: providerapi.v1.Provider.GetMinStake:input_type -> providerapi.v1.EmptyMessage - 5, // 6: providerapi.v1.Provider.WithdrawStake:input_type -> providerapi.v1.EmptyMessage - 5, // 7: providerapi.v1.Provider.Unstake:input_type -> providerapi.v1.EmptyMessage - 5, // 8: providerapi.v1.Provider.GetProviderReward:input_type -> providerapi.v1.EmptyMessage - 5, // 9: providerapi.v1.Provider.WithdrawProviderReward:input_type -> providerapi.v1.EmptyMessage - 6, // 10: providerapi.v1.Provider.ReceiveBids:output_type -> providerapi.v1.Bid - 5, // 11: providerapi.v1.Provider.SendProcessedBids:output_type -> providerapi.v1.EmptyMessage - 2, // 12: providerapi.v1.Provider.Stake:output_type -> providerapi.v1.StakeResponse - 2, // 13: providerapi.v1.Provider.GetStake:output_type -> providerapi.v1.StakeResponse - 2, // 14: providerapi.v1.Provider.GetMinStake:output_type -> providerapi.v1.StakeResponse - 3, // 15: providerapi.v1.Provider.WithdrawStake:output_type -> providerapi.v1.WithdrawalResponse - 5, // 16: providerapi.v1.Provider.Unstake:output_type -> providerapi.v1.EmptyMessage - 4, // 17: providerapi.v1.Provider.GetProviderReward:output_type -> providerapi.v1.RewardResponse - 3, // 18: providerapi.v1.Provider.WithdrawProviderReward:output_type -> providerapi.v1.WithdrawalResponse - 10, // [10:19] is the sub-list for method output_type - 1, // [1:10] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 11, // 1: providerapi.v1.CommitmentInfoResponse.commitments:type_name -> providerapi.v1.CommitmentInfoResponse.BlockCommitments + 10, // 2: providerapi.v1.CommitmentInfoResponse.BlockCommitments.commitments:type_name -> providerapi.v1.CommitmentInfoResponse.Commitment + 5, // 3: providerapi.v1.Provider.ReceiveBids:input_type -> providerapi.v1.EmptyMessage + 7, // 4: providerapi.v1.Provider.SendProcessedBids:input_type -> providerapi.v1.BidResponse + 1, // 5: providerapi.v1.Provider.Stake:input_type -> providerapi.v1.StakeRequest + 5, // 6: providerapi.v1.Provider.GetStake:input_type -> providerapi.v1.EmptyMessage + 5, // 7: providerapi.v1.Provider.GetMinStake:input_type -> providerapi.v1.EmptyMessage + 5, // 8: providerapi.v1.Provider.WithdrawStake:input_type -> providerapi.v1.EmptyMessage + 5, // 9: providerapi.v1.Provider.Unstake:input_type -> providerapi.v1.EmptyMessage + 5, // 10: providerapi.v1.Provider.GetProviderReward:input_type -> providerapi.v1.EmptyMessage + 5, // 11: providerapi.v1.Provider.WithdrawProviderReward:input_type -> providerapi.v1.EmptyMessage + 8, // 12: providerapi.v1.Provider.GetCommitmentInfo:input_type -> providerapi.v1.GetCommitmentInfoRequest + 6, // 13: providerapi.v1.Provider.ReceiveBids:output_type -> providerapi.v1.Bid + 5, // 14: providerapi.v1.Provider.SendProcessedBids:output_type -> providerapi.v1.EmptyMessage + 2, // 15: providerapi.v1.Provider.Stake:output_type -> providerapi.v1.StakeResponse + 2, // 16: providerapi.v1.Provider.GetStake:output_type -> providerapi.v1.StakeResponse + 2, // 17: providerapi.v1.Provider.GetMinStake:output_type -> providerapi.v1.StakeResponse + 3, // 18: providerapi.v1.Provider.WithdrawStake:output_type -> providerapi.v1.WithdrawalResponse + 5, // 19: providerapi.v1.Provider.Unstake:output_type -> providerapi.v1.EmptyMessage + 4, // 20: providerapi.v1.Provider.GetProviderReward:output_type -> providerapi.v1.RewardResponse + 3, // 21: providerapi.v1.Provider.WithdrawProviderReward:output_type -> providerapi.v1.WithdrawalResponse + 9, // 22: providerapi.v1.Provider.GetCommitmentInfo:output_type -> providerapi.v1.CommitmentInfoResponse + 13, // [13:23] is the sub-list for method output_type + 3, // [3:13] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_providerapi_v1_providerapi_proto_init() } @@ -1057,6 +1530,54 @@ func file_providerapi_v1_providerapi_proto_init() { return nil } } + file_providerapi_v1_providerapi_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetCommitmentInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_providerapi_v1_providerapi_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommitmentInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_providerapi_v1_providerapi_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommitmentInfoResponse_Commitment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_providerapi_v1_providerapi_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommitmentInfoResponse_BlockCommitments); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1064,7 +1585,7 @@ func file_providerapi_v1_providerapi_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_providerapi_v1_providerapi_proto_rawDesc, NumEnums: 1, - NumMessages: 7, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/p2p/gen/go/providerapi/v1/providerapi.pb.gw.go b/p2p/gen/go/providerapi/v1/providerapi.pb.gw.go index 13d5d6fe7..652fccfb2 100644 --- a/p2p/gen/go/providerapi/v1/providerapi.pb.gw.go +++ b/p2p/gen/go/providerapi/v1/providerapi.pb.gw.go @@ -259,6 +259,39 @@ func local_request_Provider_WithdrawProviderReward_0(ctx context.Context, marsha return msg, metadata, err } +var filter_Provider_GetCommitmentInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + +func request_Provider_GetCommitmentInfo_0(ctx context.Context, marshaler runtime.Marshaler, client ProviderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetCommitmentInfoRequest + metadata runtime.ServerMetadata + ) + io.Copy(io.Discard, req.Body) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Provider_GetCommitmentInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetCommitmentInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_Provider_GetCommitmentInfo_0(ctx context.Context, marshaler runtime.Marshaler, server ProviderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetCommitmentInfoRequest + metadata runtime.ServerMetadata + ) + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Provider_GetCommitmentInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetCommitmentInfo(ctx, &protoReq) + return msg, metadata, err +} + // RegisterProviderHandlerServer registers the http handlers for service Provider to "mux". // UnaryRPC :call ProviderServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -418,6 +451,26 @@ func RegisterProviderHandlerServer(ctx context.Context, mux *runtime.ServeMux, s } forward_Provider_WithdrawProviderReward_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_Provider_GetCommitmentInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/providerapi.v1.Provider/GetCommitmentInfo", runtime.WithHTTPPathPattern("/v1/provider/get_commitment_info")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Provider_GetCommitmentInfo_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_Provider_GetCommitmentInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -611,6 +664,23 @@ func RegisterProviderHandlerClient(ctx context.Context, mux *runtime.ServeMux, c } forward_Provider_WithdrawProviderReward_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_Provider_GetCommitmentInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/providerapi.v1.Provider/GetCommitmentInfo", runtime.WithHTTPPathPattern("/v1/provider/get_commitment_info")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Provider_GetCommitmentInfo_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_Provider_GetCommitmentInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -624,6 +694,7 @@ var ( pattern_Provider_Unstake_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "provider", "unstake"}, "")) pattern_Provider_GetProviderReward_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "provider", "get_provider_reward"}, "")) pattern_Provider_WithdrawProviderReward_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "provider", "withdraw_provider_reward"}, "")) + pattern_Provider_GetCommitmentInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "provider", "get_commitment_info"}, "")) ) var ( @@ -636,4 +707,5 @@ var ( forward_Provider_Unstake_0 = runtime.ForwardResponseMessage forward_Provider_GetProviderReward_0 = runtime.ForwardResponseMessage forward_Provider_WithdrawProviderReward_0 = runtime.ForwardResponseMessage + forward_Provider_GetCommitmentInfo_0 = runtime.ForwardResponseMessage ) diff --git a/p2p/gen/go/providerapi/v1/providerapi_grpc.pb.go b/p2p/gen/go/providerapi/v1/providerapi_grpc.pb.go index 01c514b41..63c2ec687 100644 --- a/p2p/gen/go/providerapi/v1/providerapi_grpc.pb.go +++ b/p2p/gen/go/providerapi/v1/providerapi_grpc.pb.go @@ -28,6 +28,7 @@ const ( Provider_Unstake_FullMethodName = "/providerapi.v1.Provider/Unstake" Provider_GetProviderReward_FullMethodName = "/providerapi.v1.Provider/GetProviderReward" Provider_WithdrawProviderReward_FullMethodName = "/providerapi.v1.Provider/WithdrawProviderReward" + Provider_GetCommitmentInfo_FullMethodName = "/providerapi.v1.Provider/GetCommitmentInfo" ) // ProviderClient is the client API for Provider service. @@ -76,6 +77,10 @@ type ProviderClient interface { // WithdrawProviderReward is called by the provider to withdraw their accumulated rewards // from the bidder registry contract. WithdrawProviderReward(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*WithdrawalResponse, error) + // GetCommitmentInfo + // + // GetCommitmentInfo is called by the provider to retrieve the commitment information. + GetCommitmentInfo(ctx context.Context, in *GetCommitmentInfoRequest, opts ...grpc.CallOption) (*CommitmentInfoResponse, error) } type providerClient struct { @@ -188,6 +193,16 @@ func (c *providerClient) WithdrawProviderReward(ctx context.Context, in *EmptyMe return out, nil } +func (c *providerClient) GetCommitmentInfo(ctx context.Context, in *GetCommitmentInfoRequest, opts ...grpc.CallOption) (*CommitmentInfoResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CommitmentInfoResponse) + err := c.cc.Invoke(ctx, Provider_GetCommitmentInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // ProviderServer is the server API for Provider service. // All implementations must embed UnimplementedProviderServer // for forward compatibility. @@ -234,6 +249,10 @@ type ProviderServer interface { // WithdrawProviderReward is called by the provider to withdraw their accumulated rewards // from the bidder registry contract. WithdrawProviderReward(context.Context, *EmptyMessage) (*WithdrawalResponse, error) + // GetCommitmentInfo + // + // GetCommitmentInfo is called by the provider to retrieve the commitment information. + GetCommitmentInfo(context.Context, *GetCommitmentInfoRequest) (*CommitmentInfoResponse, error) mustEmbedUnimplementedProviderServer() } @@ -271,6 +290,9 @@ func (UnimplementedProviderServer) GetProviderReward(context.Context, *EmptyMess func (UnimplementedProviderServer) WithdrawProviderReward(context.Context, *EmptyMessage) (*WithdrawalResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method WithdrawProviderReward not implemented") } +func (UnimplementedProviderServer) GetCommitmentInfo(context.Context, *GetCommitmentInfoRequest) (*CommitmentInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCommitmentInfo not implemented") +} func (UnimplementedProviderServer) mustEmbedUnimplementedProviderServer() {} func (UnimplementedProviderServer) testEmbeddedByValue() {} @@ -436,6 +458,24 @@ func _Provider_WithdrawProviderReward_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } +func _Provider_GetCommitmentInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCommitmentInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProviderServer).GetCommitmentInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Provider_GetCommitmentInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProviderServer).GetCommitmentInfo(ctx, req.(*GetCommitmentInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Provider_ServiceDesc is the grpc.ServiceDesc for Provider service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -471,6 +511,10 @@ var Provider_ServiceDesc = grpc.ServiceDesc{ MethodName: "WithdrawProviderReward", Handler: _Provider_WithdrawProviderReward_Handler, }, + { + MethodName: "GetCommitmentInfo", + Handler: _Provider_GetCommitmentInfo_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml b/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml index 4aaa95821..9c694b70f 100644 --- a/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml +++ b/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml @@ -74,10 +74,10 @@ paths: type: object properties: result: - $ref: '#/definitions/v1Commitment' + $ref: '#/definitions/bidderapiv1Commitment' error: $ref: '#/definitions/googlerpcStatus' - title: Stream result of v1Commitment + title: Stream result of bidderapiv1Commitment default: description: An unexpected error response. schema: @@ -111,6 +111,22 @@ paths: in: query required: false type: boolean + /v1/bidder/claim_slashed_funds: + post: + summary: ClaimSlashedFunds + description: |- + ClaimSlashedFunds is called by the bidder to claim slashed funds from the provider. The response + will show the amount claimed if any in wei. + operationId: Bidder_ClaimSlashedFunds + responses: + "200": + description: A successful response. + schema: + type: string + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' /v1/bidder/deposit/{amount}: post: summary: Deposit @@ -148,6 +164,41 @@ paths: required: false type: string format: uint64 + /v1/bidder/get_bid_info/{blockNumber}: + get: + summary: GetBidInfo + description: |- + GetBidInfo is called by the bidder to get the bid information. If block number is not specified, + all known block numbers are returned in the ascending order. + operationId: Bidder_GetBidInfo + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1GetBidInfoResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: blockNumber + description: Optional block number for querying bid info. If not specified, all known block numbers are returned in ascending order. + in: path + required: true + type: string + format: int64 + - name: page + description: Page number for pagination. + in: query + required: false + type: integer + format: int32 + - name: limit + description: Number of items per page for pagination. Default is 50 + in: query + required: false + type: integer + format: int32 /v1/bidder/get_deposit: get: summary: GetDeposit @@ -212,6 +263,46 @@ paths: schema: $ref: '#/definitions/v1WithdrawFromWindowsRequest' definitions: + GetBidInfoResponseBidInfo: + type: object + properties: + bid: + $ref: '#/definitions/bidderapiv1Bid' + commitments: + type: array + items: + type: object + $ref: '#/definitions/GetBidInfoResponseCommitmentWithStatus' + GetBidInfoResponseBlockBidInfo: + type: object + properties: + blockNumber: + type: string + format: int64 + description: Block number for which the bid info is requested. + bids: + type: array + items: + type: object + $ref: '#/definitions/GetBidInfoResponseBidInfo' + description: List of bids for the specified block number. + GetBidInfoResponseCommitmentWithStatus: + type: object + properties: + commitment: + $ref: '#/definitions/bidderapiv1Commitment' + status: + type: string + description: 'Status of the commitment. Possible values: ''pending'', ''stored'', ''opened'', ''settled'', ''slashed'', ''failed''.' + details: + type: string + description: Additional details about the commitment status. + payment: + type: string + description: Payment amount in wei for the commitment. + refund: + type: string + description: Refund amount in wei for the commitment, if applicable. bidderapiv1AutoDeposit: type: object properties: @@ -290,6 +381,59 @@ definitions: - blockNumber - decayStartTimestamp - decayEndTimestamp + bidderapiv1Commitment: + type: object + properties: + txHashes: + type: array + items: + type: string + pattern: '[a-fA-F0-9]{64}' + description: Hex string encoding of the hash of the transaction that the bidder wants to include in the block. + bidAmount: + type: string + description: Amount of ETH that the bidder has agreed to pay to the provider for including the transaction in the block. + blockNumber: + type: string + format: int64 + description: Max block number that the bidder wants to include the transaction in. + receivedBidDigest: + type: string + description: Hex string encoding of digest of the bid message signed by the bidder. + receivedBidSignature: + type: string + description: Hex string encoding of signature of the bidder that sent this bid. + commitmentDigest: + type: string + description: Hex string encoding of digest of the commitment. + commitmentSignature: + type: string + description: Hex string encoding of signature of the commitment signed by the provider confirming this transaction. + providerAddress: + type: string + description: Hex string encoding of the address of the provider that signed the commitment signature. + decayStartTimestamp: + type: string + format: int64 + description: Timestamp at which the bid starts decaying. + decayEndTimestamp: + type: string + format: int64 + description: Timestamp at which the bid ends decaying. + dispatchTimestamp: + type: string + format: int64 + description: Timestamp at which the commitment is published. + revertingTxHashes: + type: array + items: + type: string + description: Optional array of tx hashes that are allowed to revert or be discarded. + slashAmount: + type: string + description: Amount of ETH that will be slashed from the provider if they fail to include the transaction. + description: Commitment message from the provider to the bidder mev-commit node. + title: Commitment message googlerpcStatus: type: object properties: @@ -358,57 +502,6 @@ definitions: format: uint64 description: CancelAutoDeposit deposit from the bidder registry. title: CancelAutoDeposit response - v1Commitment: - type: object - properties: - txHashes: - type: array - items: - type: string - pattern: '[a-fA-F0-9]{64}' - description: Hex string encoding of the hash of the transaction that the bidder wants to include in the block. - bidAmount: - type: string - description: Amount of ETH that the bidder has agreed to pay to the provider for including the transaction in the block. - blockNumber: - type: string - format: int64 - description: Max block number that the bidder wants to include the transaction in. - receivedBidDigest: - type: string - description: Hex string encoding of digest of the bid message signed by the bidder. - receivedBidSignature: - type: string - description: Hex string encoding of signature of the bidder that sent this bid. - commitmentDigest: - type: string - description: Hex string encoding of digest of the commitment. - commitmentSignature: - type: string - description: Hex string encoding of signature of the commitment signed by the provider confirming this transaction. - providerAddress: - type: string - description: Hex string encoding of the address of the provider that signed the commitment signature. - decayStartTimestamp: - type: string - format: int64 - description: Timestamp at which the bid starts decaying. - decayEndTimestamp: - type: string - format: int64 - description: Timestamp at which the bid ends decaying. - dispatchTimestamp: - type: string - format: int64 - description: Timestamp at which the commitment is published. - revertingTxHashes: - type: array - items: - type: string - description: Optional array of tx hashes that are allowed to revert or be discarded. - slashAmount: - type: string - description: Amount of ETH that will be slashed from the provider if they fail to include the transaction. v1DepositResponse: type: object example: @@ -420,8 +513,17 @@ definitions: windowNumber: type: string format: uint64 - description: Get deposit for bidder in the bidder registry. + description: Deposit for bidder in the bidder registry for a particular window. title: Deposit response + v1GetBidInfoResponse: + type: object + properties: + blockBidInfo: + type: array + items: + type: object + $ref: '#/definitions/GetBidInfoResponseBlockBidInfo' + description: List of block bid info containing bids and their commitments. v1WithdrawFromWindowsRequest: type: object example: @@ -456,7 +558,7 @@ definitions: items: type: object $ref: '#/definitions/v1WithdrawResponse' - description: Withdraw deposit from the bidder registry. + description: Withdrawn deposit from the bidder registry. title: Withdraw from multiple windows response v1WithdrawResponse: type: object @@ -469,5 +571,5 @@ definitions: windowNumber: type: string format: uint64 - description: Withdraw deposit from the bidder registry. + description: Withdrawn deposit from the bidder registry. title: Withdraw response diff --git a/p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml b/p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml index 847bcd465..5749f3cd2 100644 --- a/p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml +++ b/p2p/gen/openapi/providerapi/v1/providerapi.swagger.yaml @@ -10,6 +10,39 @@ consumes: produces: - application/json paths: + /v1/provider/get_commitment_info: + get: + summary: GetCommitmentInfo + description: GetCommitmentInfo is called by the provider to retrieve the commitment information. + operationId: Provider_GetCommitmentInfo + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v1CommitmentInfoResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: blockNumber + description: Optional block number for which to get the commitment information. If not specified all block numbers are returned in ascending order + in: query + required: false + type: string + format: int64 + - name: page + description: Optional page number for pagination. Defaults to 0. + in: query + required: false + type: integer + format: int32 + - name: limit + description: Optional limit for the number of commitments to return per page. Defaults to 100. + in: query + required: false + type: integer + format: int32 /v1/provider/get_min_stake: get: summary: GetMinStake @@ -184,6 +217,19 @@ paths: schema: $ref: '#/definitions/googlerpcStatus' definitions: + CommitmentInfoResponseBlockCommitments: + type: object + properties: + blockNumber: + type: string + format: int64 + description: Block number for which the commitments are made. + commitments: + type: array + items: + type: object + $ref: '#/definitions/v1CommitmentInfoResponseCommitment' + description: List of commitments made in the block. googlerpcStatus: type: object properties: @@ -295,6 +341,72 @@ definitions: enum: - STATUS_ACCEPTED - STATUS_REJECTED + v1CommitmentInfoResponse: + type: object + properties: + commitments: + type: array + items: + type: object + $ref: '#/definitions/CommitmentInfoResponseBlockCommitments' + description: List of commitments made in the block. + description: Response containing the commitment information. + title: Commitment info response + required: + - commitments + v1CommitmentInfoResponseCommitment: + type: object + properties: + txnHashes: + type: array + items: + type: string + pattern: '[a-fA-F0-9]{64}' + description: List of transaction hashes that are part of the commitment. + revertableTxnHashes: + type: array + items: + type: string + pattern: '[a-fA-F0-9]{64}' + description: List of transaction hashes that are allowed to revert. + amount: + type: string + description: Amount of ETH in wei committed by the bidder. + pattern: '[0-9]+' + blockNumber: + type: string + format: int64 + description: Block number at which the commitment is made. + providerAddress: + type: string + description: Hex string encoding of the address of the provider that signed the commitment signature. + decayStartTimestamp: + type: string + format: int64 + description: Timestamp at which the bid starts decaying. + decayEndTimestamp: + type: string + format: int64 + description: Timestamp at which the bid ends decaying. + dispatchTimestamp: + type: string + format: int64 + description: Timestamp at which the commitment is published. + slashAmount: + type: string + description: Amount of ETH that will be slashed from the provider if they fail to include the transaction. + status: + type: string + description: 'Status of the commitment. Possible values: ''pending'', ''stored'', ''opened'', ''settled'', ''slashed'', ''failed''.' + details: + type: string + description: Additional details about the commitment status. + payment: + type: string + description: Payment amount in wei for the commitment. + refund: + type: string + description: Refund amount in wei for the commitment, if applicable. v1RewardResponse: type: object example: diff --git a/p2p/rpc/bidderapi/v1/bidderapi.proto b/p2p/rpc/bidderapi/v1/bidderapi.proto index c0a5446e4..ffc0e8dc8 100644 --- a/p2p/rpc/bidderapi/v1/bidderapi.proto +++ b/p2p/rpc/bidderapi/v1/bidderapi.proto @@ -96,6 +96,24 @@ service Bidder { rpc Withdraw(WithdrawRequest) returns (WithdrawResponse) { option (google.api.http) = {post: "/v1/bidder/withdraw"}; } + // GetBidInfo + // + // GetBidInfo is called by the bidder to get the bid information. If block number is not specified, + // all known block numbers are returned in the ascending order. + rpc GetBidInfo(GetBidInfoRequest) returns (GetBidInfoResponse) { + option (google.api.http) = { + get: "/v1/bidder/get_bid_info/{block_number}" + }; + } + // ClaimSlashedFunds + // + // ClaimSlashedFunds is called by the bidder to claim slashed funds from the provider. The response + // will show the amount claimed if any in wei. + rpc ClaimSlashedFunds(EmptyMessage) returns (google.protobuf.StringValue) { + option (google.api.http) = { + post: "/v1/bidder/claim_slashed_funds" + }; + } } message DepositRequest { @@ -139,7 +157,7 @@ message DepositResponse { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { json_schema: { title: "Deposit response" - description: "Get deposit for bidder in the bidder registry." + description: "Deposit for bidder in the bidder registry for a particular window." } example: "{\"amount\": \"1000000000000000000\", \"window_number\": 1}" }; @@ -244,7 +262,7 @@ message WithdrawResponse { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { json_schema: { title: "Withdraw response" - description: "Withdraw deposit from the bidder registry." + description: "Withdrawn deposit from the bidder registry." } example: "{\"amount\": \"1000000000000000000\", \"window_number\": 1 }" }; @@ -275,7 +293,7 @@ message WithdrawFromWindowsResponse { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { json_schema: { title: "Withdraw from multiple windows response" - description: "Withdraw deposit from the bidder registry." + description: "Withdrawn deposit from the bidder registry." } example: "{\"withdraw_responses\": [{\"amount\": \"1000000000000000000\", \"window_number\": 1 }, {\"amount\": \"1000000000000000000\", \"window_number\": 2 }, {\"amount\": \"1000000000000000000\", \"window_number\": 3 } ]}" }; @@ -353,6 +371,12 @@ message Bid { }; message Commitment { + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { + json_schema: { + title: "Commitment message" + description: "Commitment message from the provider to the bidder mev-commit node." + } + }; repeated string tx_hashes = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { description: "Hex string encoding of the hash of the transaction that the bidder wants to include in the block." pattern: "[a-fA-F0-9]{64}" @@ -394,3 +418,49 @@ message Commitment { description: "Amount of ETH that will be slashed from the provider if they fail to include the transaction." }]; }; + +message GetBidInfoRequest { + int64 block_number = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Optional block number for querying bid info. If not specified, all known block numbers are returned in ascending order." + }]; + int32 page = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Page number for pagination." + }]; + int32 limit = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Number of items per page for pagination. Default is 50" + }]; +}; + +message GetBidInfoResponse { + message CommitmentWithStatus { + Commitment commitment = 1; + string status = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Status of the commitment. Possible values: 'pending', 'stored', 'opened', 'settled', 'slashed', 'failed'." + }]; + string details = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Additional details about the commitment status." + }]; + string payment = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Payment amount in wei for the commitment." + }]; + string refund = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Refund amount in wei for the commitment, if applicable." + }]; + }; + message BidInfo { + Bid bid = 1; + repeated CommitmentWithStatus commitments = 2; + }; + message BlockBidInfo { + int64 block_number = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Block number for which the bid info is requested." + }]; + repeated BidInfo bids = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "List of bids for the specified block number." + }]; + }; + + repeated BlockBidInfo block_bid_info = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "List of block bid info containing bids and their commitments." + }]; +}; diff --git a/p2p/rpc/providerapi/v1/providerapi.proto b/p2p/rpc/providerapi/v1/providerapi.proto index 64f6ec36b..df0c1d52e 100644 --- a/p2p/rpc/providerapi/v1/providerapi.proto +++ b/p2p/rpc/providerapi/v1/providerapi.proto @@ -81,6 +81,12 @@ service Provider { rpc WithdrawProviderReward(EmptyMessage) returns (WithdrawalResponse) { option (google.api.http) = {post: "/v1/provider/withdraw_provider_reward"}; } + // GetCommitmentInfo + // + // GetCommitmentInfo is called by the provider to retrieve the commitment information. + rpc GetCommitmentInfo(GetCommitmentInfoRequest) returns (CommitmentInfoResponse) { + option (google.api.http) = {get: "/v1/provider/get_commitment_info"}; + } } message StakeRequest { @@ -256,3 +262,86 @@ message BidResponse { description: "Timestamp at which the commitment is accepted by provider and is used to compute the expected revenue from the preconfirmation" }]; }; + +message GetCommitmentInfoRequest { + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { + json_schema: { + title: "Get commitment info request" + description: "Request to get the commitment information." + } + }; + int64 block_number = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Optional block number for which to get the commitment information. If not specified all block numbers are returned in ascending order" + }]; + int32 page = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Optional page number for pagination. Defaults to 0." + }]; + int32 limit = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Optional limit for the number of commitments to return per page. Defaults to 100." + }]; +}; + +message CommitmentInfoResponse { + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { + json_schema: { + title: "Commitment info response" + description: "Response containing the commitment information." + required: ["commitments"] + } + }; + message Commitment { + repeated string txn_hashes = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "List of transaction hashes that are part of the commitment." + pattern: "[a-fA-F0-9]{64}" + }]; + repeated string revertable_txn_hashes = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "List of transaction hashes that are allowed to revert." + pattern: "[a-fA-F0-9]{64}" + }]; + string amount = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Amount of ETH in wei committed by the bidder." + pattern: "[0-9]+" + }]; + int64 block_number = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Block number at which the commitment is made." + }]; + string provider_address = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Hex string encoding of the address of the provider that signed the commitment signature." + }]; + int64 decay_start_timestamp = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Timestamp at which the bid starts decaying." + }]; + int64 decay_end_timestamp = 7 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Timestamp at which the bid ends decaying." + }]; + int64 dispatch_timestamp = 8 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Timestamp at which the commitment is published." + }]; + string slash_amount = 9 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Amount of ETH that will be slashed from the provider if they fail to include the transaction." + }]; + string status = 10 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Status of the commitment. Possible values: 'pending', 'stored', 'opened', 'settled', 'slashed', 'failed'." + }]; + string details = 11 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Additional details about the commitment status." + }]; + string payment = 12 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Payment amount in wei for the commitment." + }]; + string refund = 13 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Refund amount in wei for the commitment, if applicable." + }]; + }; + message BlockCommitments { + int64 block_number = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Block number for which the commitments are made." + }]; + repeated Commitment commitments = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "List of commitments made in the block." + }]; + }; + repeated BlockCommitments commitments = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "List of commitments made in the block." + }]; +}; From 31b657b1211263124e006d59935be0b2a8e3ad08 Mon Sep 17 00:00:00 2001 From: Alok Date: Tue, 27 May 2025 21:56:55 +0530 Subject: [PATCH 06/14] feat: preconf flow tracking --- p2p/gen/go/bidderapi/v1/bidderapi.pb.go | 512 +++++++++++------- .../bidderapi/v1/bidderapi.swagger.yaml | 48 +- p2p/pkg/node/node.go | 7 +- p2p/pkg/rpc/bidder/service.go | 149 +++++ p2p/pkg/rpc/bidder/service_test.go | 283 ++++++++++ p2p/pkg/rpc/provider/service.go | 72 +++ p2p/pkg/rpc/provider/service_test.go | 208 +++++++ p2p/rpc/bidderapi/v1/bidderapi.proto | 52 +- 8 files changed, 1134 insertions(+), 197 deletions(-) diff --git a/p2p/gen/go/bidderapi/v1/bidderapi.pb.go b/p2p/gen/go/bidderapi/v1/bidderapi.pb.go index 839ede730..27116c5ee 100644 --- a/p2p/gen/go/bidderapi/v1/bidderapi.pb.go +++ b/p2p/gen/go/bidderapi/v1/bidderapi.pb.go @@ -1067,11 +1067,12 @@ type GetBidInfoResponse_CommitmentWithStatus struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Commitment *Commitment `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` - Details string `protobuf:"bytes,3,opt,name=details,proto3" json:"details,omitempty"` - Payment string `protobuf:"bytes,4,opt,name=payment,proto3" json:"payment,omitempty"` - Refund string `protobuf:"bytes,5,opt,name=refund,proto3" json:"refund,omitempty"` + ProviderAddress string `protobuf:"bytes,1,opt,name=provider_address,json=providerAddress,proto3" json:"provider_address,omitempty"` + DispatchTimestamp int64 `protobuf:"varint,2,opt,name=dispatch_timestamp,json=dispatchTimestamp,proto3" json:"dispatch_timestamp,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Details string `protobuf:"bytes,4,opt,name=details,proto3" json:"details,omitempty"` + Payment string `protobuf:"bytes,5,opt,name=payment,proto3" json:"payment,omitempty"` + Refund string `protobuf:"bytes,6,opt,name=refund,proto3" json:"refund,omitempty"` } func (x *GetBidInfoResponse_CommitmentWithStatus) Reset() { @@ -1106,11 +1107,18 @@ func (*GetBidInfoResponse_CommitmentWithStatus) Descriptor() ([]byte, []int) { return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{16, 0} } -func (x *GetBidInfoResponse_CommitmentWithStatus) GetCommitment() *Commitment { +func (x *GetBidInfoResponse_CommitmentWithStatus) GetProviderAddress() string { if x != nil { - return x.Commitment + return x.ProviderAddress } - return nil + return "" +} + +func (x *GetBidInfoResponse_CommitmentWithStatus) GetDispatchTimestamp() int64 { + if x != nil { + return x.DispatchTimestamp + } + return 0 } func (x *GetBidInfoResponse_CommitmentWithStatus) GetStatus() string { @@ -1146,8 +1154,15 @@ type GetBidInfoResponse_BidInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Bid *Bid `protobuf:"bytes,1,opt,name=bid,proto3" json:"bid,omitempty"` - Commitments []*GetBidInfoResponse_CommitmentWithStatus `protobuf:"bytes,2,rep,name=commitments,proto3" json:"commitments,omitempty"` + TxnHashes []string `protobuf:"bytes,1,rep,name=txn_hashes,json=txnHashes,proto3" json:"txn_hashes,omitempty"` + RevertableTxnHashes []string `protobuf:"bytes,2,rep,name=revertable_txn_hashes,json=revertableTxnHashes,proto3" json:"revertable_txn_hashes,omitempty"` + BlockNumber int64 `protobuf:"varint,3,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` + BidAmount string `protobuf:"bytes,4,opt,name=bid_amount,json=bidAmount,proto3" json:"bid_amount,omitempty"` + DecayStartTimestamp int64 `protobuf:"varint,5,opt,name=decay_start_timestamp,json=decayStartTimestamp,proto3" json:"decay_start_timestamp,omitempty"` + DecayEndTimestamp int64 `protobuf:"varint,6,opt,name=decay_end_timestamp,json=decayEndTimestamp,proto3" json:"decay_end_timestamp,omitempty"` + BidDigest string `protobuf:"bytes,7,opt,name=bid_digest,json=bidDigest,proto3" json:"bid_digest,omitempty"` + SlashAmount string `protobuf:"bytes,8,opt,name=slash_amount,json=slashAmount,proto3" json:"slash_amount,omitempty"` + Commitments []*GetBidInfoResponse_CommitmentWithStatus `protobuf:"bytes,9,rep,name=commitments,proto3" json:"commitments,omitempty"` } func (x *GetBidInfoResponse_BidInfo) Reset() { @@ -1182,13 +1197,62 @@ func (*GetBidInfoResponse_BidInfo) Descriptor() ([]byte, []int) { return file_bidderapi_v1_bidderapi_proto_rawDescGZIP(), []int{16, 1} } -func (x *GetBidInfoResponse_BidInfo) GetBid() *Bid { +func (x *GetBidInfoResponse_BidInfo) GetTxnHashes() []string { + if x != nil { + return x.TxnHashes + } + return nil +} + +func (x *GetBidInfoResponse_BidInfo) GetRevertableTxnHashes() []string { if x != nil { - return x.Bid + return x.RevertableTxnHashes } return nil } +func (x *GetBidInfoResponse_BidInfo) GetBlockNumber() int64 { + if x != nil { + return x.BlockNumber + } + return 0 +} + +func (x *GetBidInfoResponse_BidInfo) GetBidAmount() string { + if x != nil { + return x.BidAmount + } + return "" +} + +func (x *GetBidInfoResponse_BidInfo) GetDecayStartTimestamp() int64 { + if x != nil { + return x.DecayStartTimestamp + } + return 0 +} + +func (x *GetBidInfoResponse_BidInfo) GetDecayEndTimestamp() int64 { + if x != nil { + return x.DecayEndTimestamp + } + return 0 +} + +func (x *GetBidInfoResponse_BidInfo) GetBidDigest() string { + if x != nil { + return x.BidDigest + } + return "" +} + +func (x *GetBidInfoResponse_BidInfo) GetSlashAmount() string { + if x != nil { + return x.SlashAmount + } + return "" +} + func (x *GetBidInfoResponse_BidInfo) GetCommitments() []*GetBidInfoResponse_CommitmentWithStatus { if x != nil { return x.Commitments @@ -1833,7 +1897,7 @@ var file_bidderapi_v1_bidderapi_proto_rawDesc = []byte{ 0x66, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x73, 0x20, 0x35, 0x30, 0x52, 0x05, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xe1, 0x07, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xe0, 0x11, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, @@ -1844,153 +1908,233 @@ var file_bidderapi_v1_bidderapi_proto_rawDesc = []byte{ 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x69, 0x64, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x42, - 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xc9, 0x03, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xf4, 0x04, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x38, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x86, 0x01, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6e, 0x92, 0x41, 0x6b, 0x32, - 0x69, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x50, 0x6f, 0x73, 0x73, 0x69, - 0x62, 0x6c, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3a, 0x20, 0x27, 0x70, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x27, 0x2c, - 0x20, 0x27, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x65, 0x74, 0x74, - 0x6c, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x27, 0x2c, - 0x20, 0x27, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x27, 0x2e, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x34, 0x92, 0x41, 0x31, 0x32, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x61, 0x62, 0x6f, - 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x73, 0x12, 0x48, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x2e, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x06, - 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3c, 0x92, 0x41, - 0x39, 0x32, 0x37, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x61, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x52, 0x06, 0x72, 0x65, 0x66, 0x75, - 0x6e, 0x64, 0x1a, 0x87, 0x01, 0x0a, 0x07, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, - 0x0a, 0x03, 0x62, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x69, - 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x64, 0x52, 0x03, - 0x62, 0x69, 0x64, 0x12, 0x57, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0xda, 0x01, 0x0a, - 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x59, 0x0a, - 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x42, 0x36, 0x92, 0x41, 0x33, 0x32, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x69, 0x73, - 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x04, 0x62, 0x69, 0x64, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, - 0x42, 0x31, 0x92, 0x41, 0x2e, 0x32, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62, - 0x69, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x2e, 0x52, 0x04, 0x62, 0x69, 0x64, 0x73, 0x32, 0xbe, 0x09, 0x0a, 0x06, 0x42, 0x69, - 0x64, 0x64, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x69, 0x64, 0x12, - 0x11, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x69, 0x64, 0x1a, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x19, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x72, 0x2f, 0x62, 0x69, 0x64, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x07, 0x44, 0x65, 0x70, + 0x7e, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x53, 0x92, 0x41, 0x50, 0x32, 0x4e, + 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x0f, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x63, 0x0a, 0x12, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x42, 0x34, 0x92, 0x41, 0x31, + 0x32, 0x2f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, + 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, + 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, + 0x2e, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x86, 0x01, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6e, 0x92, 0x41, 0x6b, 0x32, 0x69, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x50, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3a, 0x20, 0x27, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x27, + 0x2c, 0x20, 0x27, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x6f, 0x70, 0x65, + 0x6e, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x27, 0x2c, + 0x20, 0x27, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x27, 0x2c, 0x20, 0x27, 0x66, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x27, 0x2e, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, + 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x34, + 0x92, 0x41, 0x31, 0x32, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, + 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x2e, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x48, 0x0a, + 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, + 0x92, 0x41, 0x2b, 0x32, 0x29, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x69, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x07, + 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x06, 0x72, 0x65, 0x66, 0x75, 0x6e, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3c, 0x92, 0x41, 0x39, 0x32, 0x37, 0x52, 0x65, + 0x66, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x77, + 0x65, 0x69, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x52, 0x06, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x1a, 0xdb, 0x09, + 0x0a, 0x07, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x9a, 0x01, 0x0a, 0x0a, 0x74, 0x78, + 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x7b, + 0x92, 0x41, 0x78, 0x32, 0x64, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, + 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, 0x66, + 0x41, 0x2d, 0x46, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0x52, 0x09, 0x74, 0x78, 0x6e, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x92, 0x01, 0x0a, 0x15, 0x72, 0x65, 0x76, 0x65, 0x72, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x78, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x5e, 0x92, 0x41, 0x5b, 0x32, 0x47, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x78, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, + 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x76, + 0x65, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x65, 0x64, 0x2e, 0x8a, 0x01, 0x0f, 0x5b, 0x61, 0x2d, 0x66, 0x41, 0x2d, 0x46, 0x30, 0x2d, + 0x39, 0x5d, 0x7b, 0x36, 0x34, 0x7d, 0x52, 0x13, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x54, 0x78, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x0c, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x42, 0x46, 0x92, 0x41, 0x43, 0x32, 0x41, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, + 0x64, 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x98, 0x01, 0x0a, 0x0a, 0x62, 0x69, 0x64, 0x5f, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x79, 0x92, 0x41, 0x76, + 0x32, 0x6b, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, 0x48, 0x20, + 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, + 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, + 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x8a, 0x01, 0x06, + 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x52, 0x09, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x64, 0x0a, 0x15, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, + 0x42, 0x30, 0x92, 0x41, 0x2d, 0x32, 0x2b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, + 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, 0x69, 0x6e, + 0x67, 0x2e, 0x52, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x5e, 0x0a, 0x13, 0x64, 0x65, 0x63, 0x61, 0x79, + 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x42, 0x2e, 0x92, 0x41, 0x2b, 0x32, 0x29, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x20, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x65, 0x63, 0x61, 0x79, + 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x11, 0x64, 0x65, 0x63, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x6a, 0x0a, 0x0a, 0x62, 0x69, 0x64, 0x5f, 0x64, + 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x4b, 0x92, 0x41, 0x48, + 0x32, 0x46, 0x48, 0x65, 0x78, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x09, 0x62, 0x69, 0x64, 0x44, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x12, 0xc7, 0x01, 0x0a, 0x0c, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0xa3, 0x01, 0x92, 0x41, 0x9f, + 0x01, 0x32, 0x93, 0x01, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x54, + 0x48, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x79, + 0x20, 0x66, 0x61, 0x69, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x20, 0x49, 0x66, 0x20, 0x7a, 0x65, 0x72, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, + 0x65, 0x63, 0x61, 0x79, 0x65, 0x64, 0x20, 0x62, 0x69, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6c, + 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x8a, 0x01, 0x06, 0x5b, 0x30, 0x2d, 0x39, 0x5d, 0x2b, + 0x52, 0x0b, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x57, 0x0a, + 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x57, + 0x69, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x43, 0x92, 0x41, 0x40, 0x0a, 0x3e, 0x2a, 0x08, 0x42, + 0x69, 0x64, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x32, 0x32, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x20, 0x62, 0x69, 0x64, + 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x73, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x1a, 0xda, 0x01, 0x0a, 0x0c, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x59, 0x0a, 0x0c, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x42, 0x36, 0x92, 0x41, 0x33, 0x32, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x69, 0x73, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x6f, 0x0a, 0x04, 0x62, 0x69, 0x64, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x42, + 0x31, 0x92, 0x41, 0x2e, 0x32, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x69, + 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x2e, 0x52, 0x04, 0x62, 0x69, 0x64, 0x73, 0x32, 0xbe, 0x09, 0x0a, 0x06, 0x42, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x69, 0x64, 0x12, 0x11, + 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, + 0x64, 0x1a, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x19, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, + 0x65, 0x72, 0x2f, 0x62, 0x69, 0x64, 0x30, 0x01, 0x12, 0x6b, 0x0a, 0x07, 0x44, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, + 0x64, 0x64, 0x65, 0x72, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x7d, 0x12, 0x78, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x62, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, 0x12, 0x78, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x20, - 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x5f, - 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, - 0x12, 0x8c, 0x01, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x26, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, - 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, - 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, - 0x80, 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x1a, 0x27, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, - 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, - 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x28, 0x2e, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, - 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, - 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x6c, 0x0a, 0x0a, - 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1f, 0x2e, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, - 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, - 0x65, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x66, 0x0a, 0x08, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x13, 0x2f, - 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x12, 0x7f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x1f, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x76, 0x31, - 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x64, 0x5f, - 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x7d, 0x12, 0x75, 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, - 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x42, 0xaa, 0x02, 0x92, 0x41, 0x72, - 0x12, 0x70, 0x0a, 0x0a, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, - 0x0a, 0x1b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, - 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x20, 0x2f, + 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2f, 0x7b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x7d, 0x12, + 0x8c, 0x01, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x26, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1e, + 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x80, + 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x1a, 0x27, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x61, 0x75, + 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, + 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x28, 0x2e, 0x62, 0x69, 0x64, 0x64, + 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x6f, 0x6d, 0x57, + 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x3a, 0x01, 0x2a, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x62, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x66, + 0x72, 0x6f, 0x6d, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x6c, 0x0a, 0x0a, 0x47, + 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1f, 0x2e, 0x62, 0x69, 0x64, 0x64, + 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, + 0x74, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x66, 0x0a, 0x08, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x1d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x13, 0x2f, 0x76, + 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x12, 0x7f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x1f, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x76, 0x31, 0x2f, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x7d, 0x12, 0x75, 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x53, 0x6c, 0x61, 0x73, 0x68, + 0x65, 0x64, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x42, 0xaa, 0x02, 0x92, 0x41, 0x72, 0x12, + 0x70, 0x0a, 0x0a, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, 0x0a, + 0x1b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, 0x74, + 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, + 0x45, 0x4e, 0x53, 0x45, 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, - 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, - 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x69, 0x64, - 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, - 0x0c, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, - 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x42, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, - 0x61, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x69, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x62, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x69, 0x64, 0x64, + 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, 0x0c, + 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x42, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x42, 0x69, + 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, + 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2046,35 +2190,33 @@ var file_bidderapi_v1_bidderapi_proto_depIdxs = []int32{ 20, // 12: bidderapi.v1.WithdrawFromWindowsRequest.window_numbers:type_name -> google.protobuf.UInt64Value 10, // 13: bidderapi.v1.WithdrawFromWindowsResponse.withdraw_responses:type_name -> bidderapi.v1.WithdrawResponse 19, // 14: bidderapi.v1.GetBidInfoResponse.block_bid_info:type_name -> bidderapi.v1.GetBidInfoResponse.BlockBidInfo - 14, // 15: bidderapi.v1.GetBidInfoResponse.CommitmentWithStatus.commitment:type_name -> bidderapi.v1.Commitment - 13, // 16: bidderapi.v1.GetBidInfoResponse.BidInfo.bid:type_name -> bidderapi.v1.Bid - 17, // 17: bidderapi.v1.GetBidInfoResponse.BidInfo.commitments:type_name -> bidderapi.v1.GetBidInfoResponse.CommitmentWithStatus - 18, // 18: bidderapi.v1.GetBidInfoResponse.BlockBidInfo.bids:type_name -> bidderapi.v1.GetBidInfoResponse.BidInfo - 13, // 19: bidderapi.v1.Bidder.SendBid:input_type -> bidderapi.v1.Bid - 0, // 20: bidderapi.v1.Bidder.Deposit:input_type -> bidderapi.v1.DepositRequest - 0, // 21: bidderapi.v1.Bidder.AutoDeposit:input_type -> bidderapi.v1.DepositRequest - 4, // 22: bidderapi.v1.Bidder.CancelAutoDeposit:input_type -> bidderapi.v1.CancelAutoDepositRequest - 7, // 23: bidderapi.v1.Bidder.AutoDepositStatus:input_type -> bidderapi.v1.EmptyMessage - 11, // 24: bidderapi.v1.Bidder.WithdrawFromWindows:input_type -> bidderapi.v1.WithdrawFromWindowsRequest - 8, // 25: bidderapi.v1.Bidder.GetDeposit:input_type -> bidderapi.v1.GetDepositRequest - 9, // 26: bidderapi.v1.Bidder.Withdraw:input_type -> bidderapi.v1.WithdrawRequest - 15, // 27: bidderapi.v1.Bidder.GetBidInfo:input_type -> bidderapi.v1.GetBidInfoRequest - 7, // 28: bidderapi.v1.Bidder.ClaimSlashedFunds:input_type -> bidderapi.v1.EmptyMessage - 14, // 29: bidderapi.v1.Bidder.SendBid:output_type -> bidderapi.v1.Commitment - 1, // 30: bidderapi.v1.Bidder.Deposit:output_type -> bidderapi.v1.DepositResponse - 2, // 31: bidderapi.v1.Bidder.AutoDeposit:output_type -> bidderapi.v1.AutoDepositResponse - 5, // 32: bidderapi.v1.Bidder.CancelAutoDeposit:output_type -> bidderapi.v1.CancelAutoDepositResponse - 3, // 33: bidderapi.v1.Bidder.AutoDepositStatus:output_type -> bidderapi.v1.AutoDepositStatusResponse - 12, // 34: bidderapi.v1.Bidder.WithdrawFromWindows:output_type -> bidderapi.v1.WithdrawFromWindowsResponse - 1, // 35: bidderapi.v1.Bidder.GetDeposit:output_type -> bidderapi.v1.DepositResponse - 10, // 36: bidderapi.v1.Bidder.Withdraw:output_type -> bidderapi.v1.WithdrawResponse - 16, // 37: bidderapi.v1.Bidder.GetBidInfo:output_type -> bidderapi.v1.GetBidInfoResponse - 21, // 38: bidderapi.v1.Bidder.ClaimSlashedFunds:output_type -> google.protobuf.StringValue - 29, // [29:39] is the sub-list for method output_type - 19, // [19:29] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 17, // 15: bidderapi.v1.GetBidInfoResponse.BidInfo.commitments:type_name -> bidderapi.v1.GetBidInfoResponse.CommitmentWithStatus + 18, // 16: bidderapi.v1.GetBidInfoResponse.BlockBidInfo.bids:type_name -> bidderapi.v1.GetBidInfoResponse.BidInfo + 13, // 17: bidderapi.v1.Bidder.SendBid:input_type -> bidderapi.v1.Bid + 0, // 18: bidderapi.v1.Bidder.Deposit:input_type -> bidderapi.v1.DepositRequest + 0, // 19: bidderapi.v1.Bidder.AutoDeposit:input_type -> bidderapi.v1.DepositRequest + 4, // 20: bidderapi.v1.Bidder.CancelAutoDeposit:input_type -> bidderapi.v1.CancelAutoDepositRequest + 7, // 21: bidderapi.v1.Bidder.AutoDepositStatus:input_type -> bidderapi.v1.EmptyMessage + 11, // 22: bidderapi.v1.Bidder.WithdrawFromWindows:input_type -> bidderapi.v1.WithdrawFromWindowsRequest + 8, // 23: bidderapi.v1.Bidder.GetDeposit:input_type -> bidderapi.v1.GetDepositRequest + 9, // 24: bidderapi.v1.Bidder.Withdraw:input_type -> bidderapi.v1.WithdrawRequest + 15, // 25: bidderapi.v1.Bidder.GetBidInfo:input_type -> bidderapi.v1.GetBidInfoRequest + 7, // 26: bidderapi.v1.Bidder.ClaimSlashedFunds:input_type -> bidderapi.v1.EmptyMessage + 14, // 27: bidderapi.v1.Bidder.SendBid:output_type -> bidderapi.v1.Commitment + 1, // 28: bidderapi.v1.Bidder.Deposit:output_type -> bidderapi.v1.DepositResponse + 2, // 29: bidderapi.v1.Bidder.AutoDeposit:output_type -> bidderapi.v1.AutoDepositResponse + 5, // 30: bidderapi.v1.Bidder.CancelAutoDeposit:output_type -> bidderapi.v1.CancelAutoDepositResponse + 3, // 31: bidderapi.v1.Bidder.AutoDepositStatus:output_type -> bidderapi.v1.AutoDepositStatusResponse + 12, // 32: bidderapi.v1.Bidder.WithdrawFromWindows:output_type -> bidderapi.v1.WithdrawFromWindowsResponse + 1, // 33: bidderapi.v1.Bidder.GetDeposit:output_type -> bidderapi.v1.DepositResponse + 10, // 34: bidderapi.v1.Bidder.Withdraw:output_type -> bidderapi.v1.WithdrawResponse + 16, // 35: bidderapi.v1.Bidder.GetBidInfo:output_type -> bidderapi.v1.GetBidInfoResponse + 21, // 36: bidderapi.v1.Bidder.ClaimSlashedFunds:output_type -> google.protobuf.StringValue + 27, // [27:37] is the sub-list for method output_type + 17, // [17:27] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_bidderapi_v1_bidderapi_proto_init() } diff --git a/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml b/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml index 9c694b70f..c53d1fd68 100644 --- a/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml +++ b/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml @@ -266,13 +266,48 @@ definitions: GetBidInfoResponseBidInfo: type: object properties: - bid: - $ref: '#/definitions/bidderapiv1Bid' + txnHashes: + type: array + items: + type: string + pattern: '[a-fA-F0-9]{64}' + description: Hex string encoding of the hashes of the transactions that the bidder wants to include in the block. + revertableTxnHashes: + type: array + items: + type: string + pattern: '[a-fA-F0-9]{64}' + description: Optional array of tx hashes that are allowed to revert or be discarded. + blockNumber: + type: string + format: int64 + description: Block number that the bidder wants to include the transaction in. + bidAmount: + type: string + description: Amount of ETH that the bidder is willing to pay to the provider for including the transaction in the block. + pattern: '[0-9]+' + decayStartTimestamp: + type: string + format: int64 + description: Timestamp at which the bid starts decaying. + decayEndTimestamp: + type: string + format: int64 + description: Timestamp at which the bid ends decaying. + bidDigest: + type: string + description: Hex string encoding of digest of the bid message signed by the bidder. + slashAmount: + type: string + description: Amount of ETH that will be slashed from the provider if they fail to include the transaction. If zero, the decayed bid amount is used for slashing. + pattern: '[0-9]+' commitments: type: array items: type: object $ref: '#/definitions/GetBidInfoResponseCommitmentWithStatus' + description: Information about a bid including its commitments. + title: Bid Info GetBidInfoResponseBlockBidInfo: type: object properties: @@ -289,8 +324,13 @@ definitions: GetBidInfoResponseCommitmentWithStatus: type: object properties: - commitment: - $ref: '#/definitions/bidderapiv1Commitment' + providerAddress: + type: string + description: Hex string encoding of the address of the provider that signed the commitment. + dispatchTimestamp: + type: string + format: int64 + description: Timestamp at which the commitment is published. status: type: string description: 'Status of the commitment. Possible values: ''pending'', ''stored'', ''opened'', ''settled'', ''slashed'', ''failed''.' diff --git a/p2p/pkg/node/node.go b/p2p/pkg/node/node.go index cd656c067..8271db6e1 100644 --- a/p2p/pkg/node/node.go +++ b/p2p/pkg/node/node.go @@ -470,12 +470,14 @@ func NewNode(opts *Options) (*Node, error) { return nil, err } } + + preconfStore := preconfstore.New(store) tracker := preconftracker.NewTracker( chainID, peerType, opts.KeySigner.GetAddress(), evtMgr, - preconfstore.New(store), + preconfStore, commitmentDA, monitor, notificationsSvc, @@ -563,6 +565,7 @@ func NewNode(opts *Options) (*Node, error) { bidderRegistry, opts.KeySigner.GetAddress(), monitor, + preconfStore, optsGetter, validator, ) @@ -678,11 +681,13 @@ func NewNode(opts *Options) (*Node, error) { preconfProto, bidderRegistry, blockTrackerSession, + providerRegistry, validator, monitor, optsGetter, autoDeposit, autodepositorStore, + preconfStore, opts.OracleWindowOffset, opts.BidderBidTimeout, opts.Logger.With("component", "bidderapi"), diff --git a/p2p/pkg/rpc/bidder/service.go b/p2p/pkg/rpc/bidder/service.go index 80a644f73..e3ab8eef8 100644 --- a/p2p/pkg/rpc/bidder/service.go +++ b/p2p/pkg/rpc/bidder/service.go @@ -13,8 +13,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" bidderregistry "github.com/primev/mev-commit/contracts-abi/clients/BidderRegistry" + providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry" bidderapiv1 "github.com/primev/mev-commit/p2p/gen/go/bidderapi/v1" preconfirmationv1 "github.com/primev/mev-commit/p2p/gen/go/preconfirmation/v1" + preconfstore "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/wrapperspb" @@ -26,11 +28,13 @@ type Service struct { blocksPerWindow uint64 sender PreconfSender registryContract BidderRegistryContract + providerRegistry ProviderRegistryContract blockTrackerContract BlockTrackerContract watcher TxWatcher optsGetter OptsGetter autoDepositTracker AutoDepositTracker store DepositStore + cs CommitmentStore oracleWindowOffset *big.Int logger *slog.Logger metrics *metrics @@ -44,11 +48,13 @@ func NewService( sender PreconfSender, registryContract BidderRegistryContract, blockTrackerContract BlockTrackerContract, + providerRegistry ProviderRegistryContract, validator *protovalidate.Validator, watcher TxWatcher, optsGetter OptsGetter, autoDepositTracker AutoDepositTracker, store DepositStore, + cs CommitmentStore, oracleWindowOffset *big.Int, bidderBidTimeout time.Duration, logger *slog.Logger, @@ -59,6 +65,8 @@ func NewService( sender: sender, registryContract: registryContract, blockTrackerContract: blockTrackerContract, + providerRegistry: providerRegistry, + cs: cs, watcher: watcher, optsGetter: optsGetter, logger: logger, @@ -91,6 +99,17 @@ type BidderRegistryContract interface { ParseBidderWithdrawal(types.Log) (*bidderregistry.BidderregistryBidderWithdrawal, error) } +type ProviderRegistryContract interface { + BidderSlashedAmount(*bind.CallOpts, common.Address) (*big.Int, error) + WithdrawSlashedAmount(*bind.TransactOpts) (*types.Transaction, error) + ParseBidderWithdrawSlashedAmount(log types.Log) (*providerregistry.ProviderregistryBidderWithdrawSlashedAmount, error) +} + +type CommitmentStore interface { + GetCommitments(blockNumber int64) ([]*preconfstore.Commitment, error) + GetAllCommitments() ([]*preconfstore.Commitment, error) +} + type BlockTrackerContract interface { GetCurrentWindow() (*big.Int, error) } @@ -658,3 +677,133 @@ func (s *Service) AutoDepositStatus( IsAutodepositEnabled: isAutodepositEnabled, }, nil } + +func (s *Service) ClaimSlashedFunds( + ctx context.Context, + _ *bidderapiv1.EmptyMessage, +) (*wrapperspb.StringValue, error) { + opts, err := s.optsGetter(ctx) + if err != nil { + s.logger.Error("getting transact opts", "error", err) + return nil, status.Errorf(codes.Internal, "getting transact opts: %v", err) + } + + amount, err := s.providerRegistry.BidderSlashedAmount(&bind.CallOpts{ + From: s.owner, + Context: ctx, + }, s.owner) + if err != nil { + s.logger.Error("getting slashed amount", "error", err) + return nil, status.Errorf(codes.Internal, "getting slashed amount: %v", err) + } + + if amount.Cmp(big.NewInt(0)) == 0 { + s.logger.Info("no slashed amount to claim") + return &wrapperspb.StringValue{Value: "0"}, nil + } + + tx, err := s.providerRegistry.WithdrawSlashedAmount(opts) + if err != nil { + s.logger.Error("withdrawing slashed amount", "error", err) + return nil, status.Errorf(codes.Internal, "withdrawing slashed amount: %v", err) + } + + receipt, err := s.watcher.WaitForReceipt(ctx, tx) + if err != nil { + s.logger.Error("waiting for receipt", "error", err) + return nil, status.Errorf(codes.Internal, "waiting for receipt: %v", err) + } + + if receipt.Status != types.ReceiptStatusSuccessful { + s.logger.Error("receipt status", "status", receipt.Status) + return nil, status.Errorf(codes.Internal, "receipt status: %v", receipt.Status) + } + + for _, log := range receipt.Logs { + if withdrawal, err := s.providerRegistry.ParseBidderWithdrawSlashedAmount(*log); err == nil { + s.logger.Info("slashed amount withdrawal successful", "amount", withdrawal.Amount.String()) + return &wrapperspb.StringValue{Value: withdrawal.Amount.String()}, nil + } + } + + s.logger.Error( + "withdraw slashed amount successful but missing log", + "txHash", receipt.TxHash.Hex(), + "logs", receipt.Logs, + ) + + s.logger.Error("withdraw slashed amount successful but missing log", "txHash", receipt.TxHash.Hex(), "logs", receipt.Logs) + return nil, status.Errorf(codes.Internal, "missing log for slashed amount withdrawal") +} + +const ( + defaultLimit = 100 +) + +func (s *Service) GetBidInfo( + ctx context.Context, + req *bidderapiv1.GetBidInfoRequest, +) (*bidderapiv1.GetBidInfoResponse, error) { + var ( + cmts []*preconfstore.Commitment + err error + page, limit = int(req.Page), int(req.Limit) + ) + + if req.BlockNumber != 0 { + cmts, err = s.cs.GetCommitments(req.BlockNumber) + } else { + cmts, err = s.cs.GetAllCommitments() + } + if err != nil { + return nil, status.Errorf(codes.Internal, "getting commitments: %v", err) + } + if len(cmts) == 0 { + return &bidderapiv1.GetBidInfoResponse{}, nil + } + if limit == 0 { + limit = defaultLimit + } + cmts = cmts[min(page*limit, len(cmts)):min((page+1)*limit, len(cmts))] + blockBids := make([]*bidderapiv1.GetBidInfoResponse_BlockBidInfo, 0) +LOOP: + for _, c := range cmts { + if len(blockBids) == 0 || blockBids[len(blockBids)-1].BlockNumber != c.Bid.BlockNumber { + blockBids = append(blockBids, &bidderapiv1.GetBidInfoResponse_BlockBidInfo{ + BlockNumber: c.Bid.BlockNumber, + Bids: make([]*bidderapiv1.GetBidInfoResponse_BidInfo, 0), + }) + } + cmtWithStatus := &bidderapiv1.GetBidInfoResponse_CommitmentWithStatus{ + ProviderAddress: common.Bytes2Hex(c.ProviderAddress), + DispatchTimestamp: c.PreConfirmation.DispatchTimestamp, + Status: string(c.Status), + Details: c.Details, + Payment: c.Payment, + Refund: c.Refund, + } + for idx, b := range blockBids[len(blockBids)-1].Bids { + if common.Bytes2Hex(c.Bid.Digest) == b.BidDigest { + blockBids[len(blockBids)-1].Bids[idx].Commitments = append(blockBids[len(blockBids)-1].Bids[idx].Commitments, cmtWithStatus) + continue LOOP + } + } + blockBids[len(blockBids)-1].Bids = append(blockBids[len(blockBids)-1].Bids, &bidderapiv1.GetBidInfoResponse_BidInfo{ + BidDigest: common.Bytes2Hex(c.Bid.Digest), + TxnHashes: strings.Split(c.Bid.TxHash, ","), + RevertableTxnHashes: strings.Split(c.Bid.RevertingTxHashes, ","), + BlockNumber: c.Bid.BlockNumber, + BidAmount: c.Bid.BidAmount, + SlashAmount: c.Bid.SlashAmount, + DecayStartTimestamp: c.Bid.DecayStartTimestamp, + DecayEndTimestamp: c.Bid.DecayEndTimestamp, + Commitments: []*bidderapiv1.GetBidInfoResponse_CommitmentWithStatus{ + cmtWithStatus, + }, + }) + } + + return &bidderapiv1.GetBidInfoResponse{ + BlockBidInfo: blockBids, + }, nil +} diff --git a/p2p/pkg/rpc/bidder/service_test.go b/p2p/pkg/rpc/bidder/service_test.go index 8f4575d79..42f4c27d1 100644 --- a/p2p/pkg/rpc/bidder/service_test.go +++ b/p2p/pkg/rpc/bidder/service_test.go @@ -18,9 +18,11 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" bidderregistry "github.com/primev/mev-commit/contracts-abi/clients/BidderRegistry" + providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry" bidderapiv1 "github.com/primev/mev-commit/p2p/gen/go/bidderapi/v1" preconfpb "github.com/primev/mev-commit/p2p/gen/go/preconfirmation/v1" autodepositorstore "github.com/primev/mev-commit/p2p/pkg/autodepositor/store" + preconfstore "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" bidderapi "github.com/primev/mev-commit/p2p/pkg/rpc/bidder" inmemstorage "github.com/primev/mev-commit/p2p/pkg/storage/inmem" "github.com/primev/mev-commit/x/util" @@ -199,7 +201,48 @@ func (btc *testBlockTrackerContract) GetCurrentWindow() (*big.Int, error) { return big.NewInt(int64(btc.lastBlockNumber / btc.blocksPerWindow)), nil } +type testStore struct { + commitments []*preconfstore.Commitment +} + +func (t *testStore) GetAllCommitments() ([]*preconfstore.Commitment, error) { + return t.commitments, nil +} + +type testProviderRegistry struct { + claim *big.Int +} + +func (t *testProviderRegistry) WithdrawSlashedAmount(_ *bind.TransactOpts) (*types.Transaction, error) { + return types.NewTransaction(1, common.Address{}, nil, 0, nil, nil), nil +} + +func (t *testProviderRegistry) BidderSlashedAmount(_ *bind.CallOpts, _ common.Address) (*big.Int, error) { + return t.claim, nil +} + +func (t *testProviderRegistry) ParseBidderWithdrawSlashedAmount(_log types.Log) (*providerregistry.ProviderregistryBidderWithdrawSlashedAmount, error) { + return &providerregistry.ProviderregistryBidderWithdrawSlashedAmount{ + Amount: t.claim, + }, nil +} + +func (t *testStore) GetCommitments(blockNum int64) ([]*preconfstore.Commitment, error) { + cmts := make([]*preconfstore.Commitment, 0) + for _, c := range t.commitments { + if c.Bid.BlockNumber == blockNum { + cmts = append(cmts, c) + } + } + return cmts, nil +} + func startServer(t *testing.T) bidderapiv1.BidderClient { + cs := &testStore{} + return startServerWithStore(t, cs) +} + +func startServerWithStore(t *testing.T, cs *testStore) bidderapiv1.BidderClient { lis := bufconn.Listen(bufferSize) logger := util.NewTestLogger(os.Stdout) @@ -212,6 +255,9 @@ func startServer(t *testing.T) bidderapiv1.BidderClient { registryContract := &testRegistryContract{ deposit: big.NewInt(1000000000000000000), } + providerRegistry := &testProviderRegistry{ + claim: big.NewInt(1000000000000000000), + } sender := &testSender{noOfPreconfs: 2} blockTrackerContract := &testBlockTrackerContract{lastBlockNumber: blocksPerWindow + 1, blocksPerWindow: blocksPerWindow, blockNumberToWinner: make(map[uint64]common.Address)} testAutoDepositTracker := &testAutoDepositTracker{deposits: make(map[uint64]bool)} @@ -223,6 +269,7 @@ func startServer(t *testing.T) bidderapiv1.BidderClient { sender, registryContract, blockTrackerContract, + providerRegistry, validator, &testTxWatcher{}, func(ctx context.Context) (*bind.TransactOpts, error) { @@ -233,6 +280,7 @@ func startServer(t *testing.T) bidderapiv1.BidderClient { }, testAutoDepositTracker, store, + cs, oracleWindowOffset, 15*time.Second, logger, @@ -544,3 +592,238 @@ func TestSendBid(t *testing.T) { }) } } + +func TestClaimSlashedFunds(t *testing.T) { + t.Parallel() + + client := startServer(t) + + t.Run("claim slashed funds", func(t *testing.T) { + resp, err := client.ClaimSlashedFunds(context.Background(), &bidderapiv1.EmptyMessage{}) + if err != nil { + t.Fatalf("error claiming slashed funds: %v", err) + } + if resp.Value != "1000000000000000000" { + t.Fatalf("expected amount to be 1000000000000000000, got %v", resp.Value) + } + }) +} + +func TestGetBidInfo(t *testing.T) { + t.Parallel() + + t.Run("get bid info", func(t *testing.T) { + testCommitment := &preconfstore.Commitment{ + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0x1234567890abcdef,0x1234567890abcdef", + BlockNumber: 1, + BidAmount: "1000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + Digest: []byte("digest"), + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x1234").Bytes(), + }, + Status: preconfstore.CommitmentStatusOpened, + Details: "test details", + Payment: "900000000000000000", + Refund: "100000000000000000", + } + + store := &testStore{ + commitments: []*preconfstore.Commitment{testCommitment}, + } + + client := startServerWithStore(t, store) + + resp, err := client.GetBidInfo(context.Background(), &bidderapiv1.GetBidInfoRequest{ + BlockNumber: 1, + }) + if err != nil { + t.Fatalf("error getting bid info: %v", err) + } + if len(resp.BlockBidInfo) != 1 { + t.Fatalf("expected 1 bid info, got %v", len(resp.BlockBidInfo)) + } + bidInfo := resp.BlockBidInfo[0] + if bidInfo.BlockNumber != 1 { + t.Fatalf("expected block number to be 1, got %v", bidInfo.BlockNumber) + } + if len(bidInfo.Bids) != 1 { + t.Fatalf("expected 1 bid, got %v", len(bidInfo.Bids)) + } + bid := bidInfo.Bids[0] + if len(bid.TxnHashes) != 2 { + t.Fatalf("expected 2 transaction hashes, got %v", len(bid.TxnHashes)) + } + if bid.TxnHashes[0] != "0x1234567890abcdef" || bid.TxnHashes[1] != "0x1234567890abcdef" { + t.Fatalf("expected transaction hashes to be 0x1234567890abcdef,0x1234567890abcdef, got %v", bid.TxnHashes) + } + if bid.BidAmount != "1000000000000000000" { + t.Fatalf("expected bid amount to be 1000000000000000000, got %v", bid.BidAmount) + } + if bid.DecayStartTimestamp != 123456789 { + t.Fatalf("expected decay start timestamp to be 123456789, got %v", bid.DecayStartTimestamp) + } + if bid.DecayEndTimestamp != 123457896 { + t.Fatalf("expected decay end timestamp to be 123457896, got %v", bid.DecayEndTimestamp) + } + if bid.BidDigest != common.Bytes2Hex([]byte("digest")) { + t.Fatalf("expected bid digest to be 'digest', got %v", bid.BidDigest) + } + if len(bid.Commitments) != 1 { + t.Fatalf("expected 1 commitment, got %v", len(bid.Commitments)) + } + commitment := bid.Commitments[0] + if commitment.Details != "test details" { + t.Fatalf("expected commitment details to be 'test details', got %v", commitment.Details) + } + if commitment.Status != string(preconfstore.CommitmentStatusOpened) { + t.Fatalf("expected commitment status to be opened, got %v", commitment.Status) + } + if commitment.Payment != "900000000000000000" { + t.Fatalf("expected commitment payment to be 900000000000000000, got %v", commitment.Payment) + } + if commitment.Refund != "100000000000000000" { + t.Fatalf("expected commitment refund to be 100000000000000000, got %v", commitment.Refund) + } + if commitment.ProviderAddress != strings.TrimPrefix(common.HexToAddress("0x1234").Hex(), "0x") { + t.Fatalf("expected provider address to be 0x1234, got %v", commitment.ProviderAddress) + } + }) + + t.Run("get bid info multiple commitments", func(t *testing.T) { + testCommitments := []*preconfstore.Commitment{ + { + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0x1234567890abcdef,0x1234567890abcdef", + BlockNumber: 1, + BidAmount: "1000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + Digest: []byte("digest1"), + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x1234").Bytes(), + }, + Status: preconfstore.CommitmentStatusOpened, + Details: "test details", + Payment: "900000000000000000", + Refund: "100000000000000000", + }, + { + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0xabcdef1234567890,0xabcdef1234567890", + BlockNumber: 2, + BidAmount: "2000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + Digest: []byte("digest2"), + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x5678").Bytes(), + }, + Status: preconfstore.CommitmentStatusSettled, + Details: "another test details", + Payment: "1800000000000000000", + Refund: "200000000000000000", + }, + { + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0xabcdef1234567890,0xabcdef1234567890", + BlockNumber: 2, + BidAmount: "2000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + Digest: []byte("digest2"), + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x1278").Bytes(), + }, + Status: preconfstore.CommitmentStatusFailed, + Details: "yet another test details", + Payment: "2700000000000000000", + Refund: "300000000000000000", + }, + } + + store := &testStore{ + commitments: testCommitments, + } + + client := startServerWithStore(t, store) + resp, err := client.GetBidInfo(context.Background(), &bidderapiv1.GetBidInfoRequest{}) + if err != nil { + t.Fatalf("error getting bid info: %v", err) + } + + if len(resp.BlockBidInfo) != 2 { + t.Fatalf("expected 2 bid info, got %v", len(resp.BlockBidInfo)) + } + + for _, bidInfo := range resp.BlockBidInfo { + if bidInfo.BlockNumber == 1 { + if len(bidInfo.Bids) != 1 { + t.Fatalf("expected 1 bid for block 1, got %v", len(bidInfo.Bids)) + } + bid := bidInfo.Bids[0] + if len(bid.TxnHashes) != 2 || bid.TxnHashes[0] != "0x1234567890abcdef" || bid.TxnHashes[1] != "0x1234567890abcdef" { + t.Fatalf("unexpected transaction hashes for block 1, got %v", bid.TxnHashes) + } + if len(bid.Commitments) != 1 { + t.Fatalf("expected 1 commitment for block 1, got %v", len(bid.Commitments)) + } + commitment := bid.Commitments[0] + if commitment.Details != "test details" { + t.Fatalf("expected commitment details to be 'test details', got %v", commitment.Details) + } + if commitment.Status != string(preconfstore.CommitmentStatusOpened) { + t.Fatalf("expected commitment status to be opened, got %v", commitment.Status) + } + if commitment.Payment != "900000000000000000" { + t.Fatalf("expected commitment payment to be 900000000000000000, got %v", commitment.Payment) + } + if commitment.Refund != "100000000000000000" { + t.Fatalf("expected commitment refund to be 100000000000000000, got %v", commitment.Refund) + } + if commitment.ProviderAddress != strings.TrimPrefix(common.HexToAddress("0x1234").Hex(), "0x") { + t.Fatalf("expected provider address to be 0x1234, got %v", commitment.ProviderAddress) + } + } else if bidInfo.BlockNumber == 2 { + if len(bidInfo.Bids) != 1 { + t.Fatalf("expected 1 bid for block 2, got %v", len(bidInfo.Bids)) + } + bid := bidInfo.Bids[0] + if len(bid.Commitments) != 2 { + t.Fatalf("expected 2 commitments for block 2, got %v", len(bid.Commitments)) + } + for _, commitment := range bid.Commitments { + if commitment.Details != "another test details" && commitment.Details != "yet another test details" { + t.Fatalf("unexpected commitment details for block 2, got %v", commitment.Details) + } + if commitment.Status != string(preconfstore.CommitmentStatusSettled) && commitment.Status != string(preconfstore.CommitmentStatusFailed) { + t.Fatalf("unexpected commitment status for block 2, got %v", commitment.Status) + } + if commitment.Payment != "1800000000000000000" && commitment.Payment != "2700000000000000000" { + t.Fatalf("unexpected commitment payment for block 2, got %v", commitment.Payment) + } + if commitment.Refund != "200000000000000000" && commitment.Refund != "300000000000000000" { + t.Fatalf("unexpected commitment refund for block 2, got %v", commitment.Refund) + } + if commitment.ProviderAddress != strings.TrimPrefix(common.HexToAddress("0x5678").Hex(), "0x") && + commitment.ProviderAddress != strings.TrimPrefix(common.HexToAddress("0x1278").Hex(), "0x") { + fmt.Println(strings.TrimPrefix(common.HexToAddress("0x1278").Hex(), "0x")) + t.Fatalf("unexpected provider address for block 2, got %v", commitment.ProviderAddress) + } + } + } else { + t.Fatalf("unexpected block number %v", bidInfo.BlockNumber) + } + } + }) +} diff --git a/p2p/pkg/rpc/provider/service.go b/p2p/pkg/rpc/provider/service.go index b2e8288cd..d4f0b53ef 100644 --- a/p2p/pkg/rpc/provider/service.go +++ b/p2p/pkg/rpc/provider/service.go @@ -18,6 +18,7 @@ import ( providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry" preconfpb "github.com/primev/mev-commit/p2p/gen/go/preconfirmation/v1" providerapiv1 "github.com/primev/mev-commit/p2p/gen/go/providerapi/v1" + preconfstore "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -37,6 +38,7 @@ type Service struct { registryContract ProviderRegistryContract bidderRegistryContract BidderRegistryContract watcher Watcher + cs CommitmentStore optsGetter OptsGetter metrics *metrics validator *protovalidate.Validator @@ -69,6 +71,11 @@ type Watcher interface { WaitForReceipt(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) } +type CommitmentStore interface { + GetCommitments(blockNumber int64) ([]*preconfstore.Commitment, error) + GetAllCommitments() ([]*preconfstore.Commitment, error) +} + type OptsGetter func(ctx context.Context) (*bind.TransactOpts, error) func NewService( @@ -77,6 +84,7 @@ func NewService( bidderRegistryContract BidderRegistryContract, owner common.Address, watcher Watcher, + cs CommitmentStore, optsGetter OptsGetter, validator *protovalidate.Validator, ) *Service { @@ -88,6 +96,7 @@ func NewService( owner: owner, logger: logger, watcher: watcher, + cs: cs, optsGetter: optsGetter, metrics: newMetrics(), validator: validator, @@ -492,3 +501,66 @@ func (s *Service) GetProviderReward( s.logger.Info("retrieved provider reward amount", "amount", amount.String()) return &providerapiv1.RewardResponse{Amount: amount.String()}, nil } + +const ( + defaultPage = 0 + defaultLimit = 100 +) + +func (s *Service) GetCommitmentInfo( + ctx context.Context, + req *providerapiv1.GetCommitmentInfoRequest, +) (*providerapiv1.CommitmentInfoResponse, error) { + var ( + cmts []*preconfstore.Commitment + err error + page, limit = int(req.Page), int(req.Limit) + ) + + if req.BlockNumber != 0 { + cmts, err = s.cs.GetCommitments(req.BlockNumber) + } else { + cmts, err = s.cs.GetAllCommitments() + } + if err != nil { + return nil, status.Errorf(codes.Internal, "getting commitments: %v", err) + } + if len(cmts) == 0 { + return &providerapiv1.CommitmentInfoResponse{ + Commitments: []*providerapiv1.CommitmentInfoResponse_BlockCommitments{}, + }, nil + } + + if limit == 0 { + limit = defaultLimit + } + cmts = cmts[min(page*limit, len(cmts)):min((page+1)*limit, len(cmts))] + blockCommitments := make([]*providerapiv1.CommitmentInfoResponse_BlockCommitments, 0) + for _, c := range cmts { + if len(blockCommitments) == 0 || blockCommitments[len(blockCommitments)-1].BlockNumber != c.Bid.BlockNumber { + blockCommitments = append(blockCommitments, &providerapiv1.CommitmentInfoResponse_BlockCommitments{ + BlockNumber: c.Bid.BlockNumber, + Commitments: make([]*providerapiv1.CommitmentInfoResponse_Commitment, 0), + }) + } + blockCommitments[len(blockCommitments)-1].Commitments = append(blockCommitments[len(blockCommitments)-1].Commitments, &providerapiv1.CommitmentInfoResponse_Commitment{ + TxnHashes: strings.Split(c.Bid.TxHash, ","), + RevertableTxnHashes: strings.Split(c.Bid.RevertingTxHashes, ","), + Amount: c.Bid.BidAmount, + BlockNumber: c.Bid.BlockNumber, + ProviderAddress: common.Bytes2Hex(c.ProviderAddress), + DecayStartTimestamp: c.Bid.DecayStartTimestamp, + DecayEndTimestamp: c.Bid.DecayEndTimestamp, + DispatchTimestamp: c.PreConfirmation.DispatchTimestamp, + SlashAmount: c.Bid.SlashAmount, + Status: string(c.Status), + Details: c.Details, + Payment: c.Payment, + Refund: c.Refund, + }) + } + + return &providerapiv1.CommitmentInfoResponse{ + Commitments: blockCommitments, + }, nil +} diff --git a/p2p/pkg/rpc/provider/service_test.go b/p2p/pkg/rpc/provider/service_test.go index 6a076bddc..f59d1c443 100644 --- a/p2p/pkg/rpc/provider/service_test.go +++ b/p2p/pkg/rpc/provider/service_test.go @@ -22,6 +22,7 @@ import ( providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry" preconfpb "github.com/primev/mev-commit/p2p/gen/go/preconfirmation/v1" providerapiv1 "github.com/primev/mev-commit/p2p/gen/go/providerapi/v1" + preconfstore "github.com/primev/mev-commit/p2p/pkg/preconfirmation/store" providerapi "github.com/primev/mev-commit/p2p/pkg/rpc/provider" "github.com/primev/mev-commit/x/util" "google.golang.org/grpc" @@ -147,7 +148,30 @@ func (t *testWatcher) WaitForReceipt(ctx context.Context, tx *types.Transaction) }, nil } +type testStore struct { + commitments []*preconfstore.Commitment +} + +func (t *testStore) GetAllCommitments() ([]*preconfstore.Commitment, error) { + return t.commitments, nil +} + +func (t *testStore) GetCommitments(blockNum int64) ([]*preconfstore.Commitment, error) { + cmts := make([]*preconfstore.Commitment, 0) + for _, c := range t.commitments { + if c.Bid.BlockNumber == blockNum { + cmts = append(cmts, c) + } + } + return cmts, nil +} + func startServer(t *testing.T) (providerapiv1.ProviderClient, *providerapi.Service) { + ts := &testStore{} + return startServerWithStore(t, ts) +} + +func startServerWithStore(t *testing.T, ts *testStore) (providerapiv1.ProviderClient, *providerapi.Service) { buffer := 101024 * 1024 lis := bufconn.Listen(buffer) @@ -174,6 +198,7 @@ func startServer(t *testing.T) (providerapiv1.ProviderClient, *providerapi.Servi bidderRegistryContract, owner, &testWatcher{}, + ts, func(context.Context) (*bind.TransactOpts, error) { return &bind.TransactOpts{ From: owner, @@ -634,3 +659,186 @@ func TestRequestWithdrawal(t *testing.T) { } }) } + +func TestGetCommitmentInfo(t *testing.T) { + t.Parallel() + + t.Run("get commitment info", func(t *testing.T) { + // Create a test commitment + testCommitment := &preconfstore.Commitment{ + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0x1234567890abcdef,0x1234567890abcdef", + BlockNumber: 1, + BidAmount: "1000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x1234").Bytes(), + }, + Status: preconfstore.CommitmentStatusOpened, + Details: "test details", + Payment: "900000000000000000", + Refund: "100000000000000000", + } + + store := &testStore{ + commitments: []*preconfstore.Commitment{testCommitment}, + } + + client, _ := startServerWithStore(t, store) + + resp, err := client.GetCommitmentInfo(context.Background(), &providerapiv1.GetCommitmentInfoRequest{ + BlockNumber: 1, + }) + if err != nil { + t.Fatalf("error getting commitment info: %v", err) + } + if len(resp.Commitments) != 1 { + t.Fatalf("expected 1 commitment, got %d", len(resp.Commitments)) + } + if resp.Commitments[0].BlockNumber != 1 { + t.Fatalf("expected block number to be 1, got %d", resp.Commitments[0].BlockNumber) + } + if len(resp.Commitments[0].Commitments) != 1 { + t.Fatalf("expected 1 commitment in response, got %d", len(resp.Commitments[0].Commitments)) + } + if len(resp.Commitments[0].Commitments[0].TxnHashes) != 2 { + t.Fatalf("expected 2 tx hashes, got %d", len(resp.Commitments[0].Commitments[0].TxnHashes)) + } + if resp.Commitments[0].Commitments[0].TxnHashes[0] != "0x1234567890abcdef" { + t.Fatalf("expected first tx hash to be 0x1234567890abcdef, got %s", resp.Commitments[0].Commitments[0].TxnHashes[0]) + } + if resp.Commitments[0].Commitments[0].TxnHashes[1] != "0x1234567890abcdef" { + t.Fatalf("expected second tx hash to be 0x1234567890abcdef, got %s", resp.Commitments[0].Commitments[0].TxnHashes[1]) + } + if resp.Commitments[0].Commitments[0].Amount != "1000000000000000000" { + t.Fatalf("expected bid amount to be 1000000000000000000, got %s", resp.Commitments[0].Commitments[0].Amount) + } + if resp.Commitments[0].Commitments[0].DispatchTimestamp != 123456889 { + t.Fatalf("expected dispatch timestamp to be 123456889, got %d", resp.Commitments[0].Commitments[0].DispatchTimestamp) + } + if resp.Commitments[0].Commitments[0].ProviderAddress != strings.TrimPrefix(common.HexToAddress("0x1234").String(), "0x") { + t.Fatalf("expected provider address to be %s, got %s", common.HexToAddress("0x1234").String(), resp.Commitments[0].Commitments[0].ProviderAddress) + } + if resp.Commitments[0].Commitments[0].Status != string(preconfstore.CommitmentStatusOpened) { + t.Fatalf("expected commitment status to be 'opened', got %s", resp.Commitments[0].Commitments[0].Status) + } + if resp.Commitments[0].Commitments[0].Details != "test details" { + t.Fatalf("expected commitment details to be 'test details', got %s", resp.Commitments[0].Commitments[0].Details) + } + if resp.Commitments[0].Commitments[0].Payment != "900000000000000000" { + t.Fatalf("expected payment to be 900000000000000000, got %s", resp.Commitments[0].Commitments[0].Payment) + } + if resp.Commitments[0].Commitments[0].Refund != "100000000000000000" { + t.Fatalf("expected refund to be 100000000000000000, got %s", resp.Commitments[0].Commitments[0].Refund) + } + }) + + t.Run("get all commitments", func(t *testing.T) { + testCommitments := []*preconfstore.Commitment{ + { + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0x1234567890abcdef,0x1234567890abcdef", + BlockNumber: 1, + BidAmount: "1000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x1234").Bytes(), + }, + Status: preconfstore.CommitmentStatusOpened, + Details: "test details", + Payment: "900000000000000000", + Refund: "100000000000000000", + }, + { + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0xabcdef1234567890,0xabcdef1234567890", + BlockNumber: 2, + BidAmount: "2000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x5678").Bytes(), + }, + Status: preconfstore.CommitmentStatusSettled, + Details: "another test details", + Payment: "1800000000000000000", + Refund: "200000000000000000", + }, + { + PreConfirmation: &preconfpb.PreConfirmation{ + Bid: &preconfpb.Bid{ + TxHash: "0xabcdef1234567890,0xabcdef1234567890", + BlockNumber: 3, + BidAmount: "3000000000000000000", + DecayStartTimestamp: 123456789, + DecayEndTimestamp: 123457896, + }, + DispatchTimestamp: 123456889, + ProviderAddress: common.HexToAddress("0x9abc").Bytes(), + }, + Status: preconfstore.CommitmentStatusFailed, + Details: "yet another test details", + Payment: "2700000000000000000", + Refund: "300000000000000000", + }, + } + + store := &testStore{ + commitments: testCommitments, + } + + client, _ := startServerWithStore(t, store) + resp, err := client.GetCommitmentInfo(context.Background(), &providerapiv1.GetCommitmentInfoRequest{}) + if err != nil { + t.Fatalf("error getting all commitments: %v", err) + } + + if len(resp.Commitments) != 3 { + t.Fatalf("expected 3 commitments, got %d", len(resp.Commitments)) + } + + for i, commitment := range resp.Commitments { + if len(commitment.Commitments) != 1 { + t.Fatalf("expected 1 commitment in response, got %d", len(commitment.Commitments)) + } + if commitment.BlockNumber != int64(i+1) { + t.Fatalf("expected block number to be %d, got %d", i+1, commitment.BlockNumber) + } + if commitment.Commitments[0].BlockNumber != int64(i+1) { + t.Fatalf("expected block number to be %d, got %d", i+1, commitment.Commitments[0].BlockNumber) + } + if commitment.Commitments[0].TxnHashes[0] != "0x1234567890abcdef" && commitment.Commitments[0].TxnHashes[0] != "0xabcdef1234567890" { + t.Fatalf("expected tx hash to be 0x1234567890abcdef or 0xabcdef1234567890, got %s", commitment.Commitments[0].TxnHashes[0]) + } + if commitment.Commitments[0].Amount != testCommitments[i].PreConfirmation.Bid.BidAmount { + t.Fatalf("expected bid amount to be %s, got %s", testCommitments[i].PreConfirmation.Bid.BidAmount, commitment.Commitments[0].Amount) + } + if commitment.Commitments[0].DispatchTimestamp != testCommitments[i].PreConfirmation.DispatchTimestamp { + t.Fatalf("expected dispatch timestamp to be %d, got %d", testCommitments[i].PreConfirmation.DispatchTimestamp, commitment.Commitments[0].DispatchTimestamp) + } + if commitment.Commitments[0].ProviderAddress != strings.TrimPrefix(common.Bytes2Hex(testCommitments[i].PreConfirmation.ProviderAddress), "0x") { + t.Fatalf("expected provider address to be 0x1234, 0x5678 or 0x9abc, got %s", commitment.Commitments[0].ProviderAddress) + } + if commitment.Commitments[0].Status != string(testCommitments[i].Status) { + t.Fatalf("expected commitment status to be '%s', got '%s'", testCommitments[i].Status, commitment.Commitments[0].Status) + } + if commitment.Commitments[0].Details != testCommitments[i].Details { + t.Fatalf("expected commitment details to be '%s', got '%s'", testCommitments[i].Details, commitment.Commitments[0].Details) + } + if commitment.Commitments[0].Payment != testCommitments[i].Payment { + t.Fatalf("expected payment to be %s, got %s", testCommitments[i].Payment, commitment.Commitments[0].Payment) + } + if commitment.Commitments[0].Refund != testCommitments[i].Refund { + t.Fatalf("expected refund to be %s, got %s", testCommitments[i].Refund, commitment.Commitments[0].Refund) + } + } + }) +} diff --git a/p2p/rpc/bidderapi/v1/bidderapi.proto b/p2p/rpc/bidderapi/v1/bidderapi.proto index ffc0e8dc8..554364047 100644 --- a/p2p/rpc/bidderapi/v1/bidderapi.proto +++ b/p2p/rpc/bidderapi/v1/bidderapi.proto @@ -433,23 +433,61 @@ message GetBidInfoRequest { message GetBidInfoResponse { message CommitmentWithStatus { - Commitment commitment = 1; - string status = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + string provider_address = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Hex string encoding of the address of the provider that signed the commitment." + }]; + int64 dispatch_timestamp = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Timestamp at which the commitment is published." + }]; + string status = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { description: "Status of the commitment. Possible values: 'pending', 'stored', 'opened', 'settled', 'slashed', 'failed'." }]; - string details = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + string details = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { description: "Additional details about the commitment status." }]; - string payment = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + string payment = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { description: "Payment amount in wei for the commitment." }]; - string refund = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + string refund = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { description: "Refund amount in wei for the commitment, if applicable." }]; }; message BidInfo { - Bid bid = 1; - repeated CommitmentWithStatus commitments = 2; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { + json_schema: { + title: "Bid Info" + description: "Information about a bid including its commitments." + } + }; + repeated string txn_hashes = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Hex string encoding of the hashes of the transactions that the bidder wants to include in the block." + pattern: "[a-fA-F0-9]{64}" + }]; + repeated string revertable_txn_hashes = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Optional array of tx hashes that are allowed to revert or be discarded." + pattern: "[a-fA-F0-9]{64}" + }]; + int64 block_number = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Block number that the bidder wants to include the transaction in." + }]; + string bid_amount = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Amount of ETH that the bidder is willing to pay to the provider for including the transaction in the block." + pattern: "[0-9]+" + }]; + int64 decay_start_timestamp = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Timestamp at which the bid starts decaying." + }]; + int64 decay_end_timestamp = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Timestamp at which the bid ends decaying." + }]; + string bid_digest = 7 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Hex string encoding of digest of the bid message signed by the bidder." + }]; + string slash_amount = 8 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + description: "Amount of ETH that will be slashed from the provider if they fail to include the transaction. If zero, the decayed bid amount is used for slashing." + pattern: "[0-9]+" + }]; + repeated CommitmentWithStatus commitments = 9; }; message BlockBidInfo { int64 block_number = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { From cf4f140395636cc3772cbbe0c78532473d303aa2 Mon Sep 17 00:00:00 2001 From: Alok Date: Tue, 27 May 2025 22:08:46 +0530 Subject: [PATCH 07/14] feat: preconf flow tracking --- p2p/pkg/preconfirmation/store/store.go | 2 +- p2p/pkg/preconfirmation/tracker/tracker.go | 2 +- p2p/pkg/rpc/bidder/service_test.go | 7 ++++--- p2p/pkg/rpc/provider/service_test.go | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index ad4bca9bc..89ee1fe56 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -42,7 +42,7 @@ var ( } parseBlockNumFromCommitmentKey = func(key string) (int64, error) { splits := strings.Split(key, "/") - if len(splits) != 4 || strings.HasPrefix(commitmentNS, splits[0]) == false { + if len(splits) != 4 || !strings.HasPrefix(commitmentNS, splits[0]) { return 0, fmt.Errorf("invalid commitment key format: %s", key) } blockNum, err := strconv.Atoi(splits[1]) diff --git a/p2p/pkg/preconfirmation/tracker/tracker.go b/p2p/pkg/preconfirmation/tracker/tracker.go index 9148661ae..95eaf70fa 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker.go +++ b/p2p/pkg/preconfirmation/tracker/tracker.go @@ -493,7 +493,7 @@ func (t *Tracker) openCommitments( return err } - var settled, failed, alreadyOpened int = 0, 0, 0 + var settled, failed, alreadyOpened = 0, 0, 0 for _, commitment := range commitments { switch commitment.Status { diff --git a/p2p/pkg/rpc/bidder/service_test.go b/p2p/pkg/rpc/bidder/service_test.go index 42f4c27d1..4e2d0b4d0 100644 --- a/p2p/pkg/rpc/bidder/service_test.go +++ b/p2p/pkg/rpc/bidder/service_test.go @@ -767,7 +767,8 @@ func TestGetBidInfo(t *testing.T) { } for _, bidInfo := range resp.BlockBidInfo { - if bidInfo.BlockNumber == 1 { + switch bidInfo.BlockNumber { + case 1: if len(bidInfo.Bids) != 1 { t.Fatalf("expected 1 bid for block 1, got %v", len(bidInfo.Bids)) } @@ -794,7 +795,7 @@ func TestGetBidInfo(t *testing.T) { if commitment.ProviderAddress != strings.TrimPrefix(common.HexToAddress("0x1234").Hex(), "0x") { t.Fatalf("expected provider address to be 0x1234, got %v", commitment.ProviderAddress) } - } else if bidInfo.BlockNumber == 2 { + case 2: if len(bidInfo.Bids) != 1 { t.Fatalf("expected 1 bid for block 2, got %v", len(bidInfo.Bids)) } @@ -821,7 +822,7 @@ func TestGetBidInfo(t *testing.T) { t.Fatalf("unexpected provider address for block 2, got %v", commitment.ProviderAddress) } } - } else { + default: t.Fatalf("unexpected block number %v", bidInfo.BlockNumber) } } diff --git a/p2p/pkg/rpc/provider/service_test.go b/p2p/pkg/rpc/provider/service_test.go index f59d1c443..012581f60 100644 --- a/p2p/pkg/rpc/provider/service_test.go +++ b/p2p/pkg/rpc/provider/service_test.go @@ -818,13 +818,13 @@ func TestGetCommitmentInfo(t *testing.T) { if commitment.Commitments[0].TxnHashes[0] != "0x1234567890abcdef" && commitment.Commitments[0].TxnHashes[0] != "0xabcdef1234567890" { t.Fatalf("expected tx hash to be 0x1234567890abcdef or 0xabcdef1234567890, got %s", commitment.Commitments[0].TxnHashes[0]) } - if commitment.Commitments[0].Amount != testCommitments[i].PreConfirmation.Bid.BidAmount { - t.Fatalf("expected bid amount to be %s, got %s", testCommitments[i].PreConfirmation.Bid.BidAmount, commitment.Commitments[0].Amount) + if commitment.Commitments[0].Amount != testCommitments[i].Bid.BidAmount { + t.Fatalf("expected bid amount to be %s, got %s", testCommitments[i].Bid.BidAmount, commitment.Commitments[0].Amount) } if commitment.Commitments[0].DispatchTimestamp != testCommitments[i].PreConfirmation.DispatchTimestamp { t.Fatalf("expected dispatch timestamp to be %d, got %d", testCommitments[i].PreConfirmation.DispatchTimestamp, commitment.Commitments[0].DispatchTimestamp) } - if commitment.Commitments[0].ProviderAddress != strings.TrimPrefix(common.Bytes2Hex(testCommitments[i].PreConfirmation.ProviderAddress), "0x") { + if commitment.Commitments[0].ProviderAddress != strings.TrimPrefix(common.Bytes2Hex(testCommitments[i].ProviderAddress), "0x") { t.Fatalf("expected provider address to be 0x1234, 0x5678 or 0x9abc, got %s", commitment.Commitments[0].ProviderAddress) } if commitment.Commitments[0].Status != string(testCommitments[i].Status) { From 5b8a22e8f4bc032998770141248e7e90b84f983e Mon Sep 17 00:00:00 2001 From: Alok Nerurkar Date: Wed, 28 May 2025 02:18:35 +0530 Subject: [PATCH 08/14] fix: revert commitment opening restrictions --- oracle/pkg/updater/updater.go | 27 ++++- oracle/pkg/updater/updater_test.go | 8 +- p2p/pkg/preconfirmation/store/store.go | 3 + p2p/pkg/preconfirmation/tracker/tracker.go | 23 +++- .../preconfirmation/tracker/tracker_test.go | 100 ++++++++++++++++++ 5 files changed, 153 insertions(+), 8 deletions(-) diff --git a/oracle/pkg/updater/updater.go b/oracle/pkg/updater/updater.go index 04eb4d370..7af116382 100644 --- a/oracle/pkg/updater/updater.go +++ b/oracle/pkg/updater/updater.go @@ -9,6 +9,7 @@ import ( "math/big" "strings" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/common" @@ -16,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/log" lru "github.com/hashicorp/golang-lru/v2" "github.com/lib/pq" + blocktracker "github.com/primev/mev-commit/contracts-abi/clients/BlockTracker" preconf "github.com/primev/mev-commit/contracts-abi/clients/PreconfManager" "github.com/primev/mev-commit/x/contracts/events" "github.com/primev/mev-commit/x/contracts/txmonitor" @@ -109,6 +111,7 @@ type Updater struct { l1BlockCache *lru.Cache[uint64, map[string]TxMetadata] unopenedCmts chan *preconf.PreconfmanagerUnopenedCommitmentStored openedCmts chan *preconf.PreconfmanagerOpenedCommitmentStored + currentWindow atomic.Int64 metrics *metrics receiptBatcher txmonitor.BatchReceiptGetter } @@ -168,7 +171,14 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { }, ) - sub, err := u.evtMgr.Subscribe(ev1, ev2) + ev3 := events.NewEventHandler( + "NewWindow", + func(update *blocktracker.BlocktrackerNewWindow) { + u.currentWindow.Store(update.Window.Int64()) + }, + ) + + sub, err := u.evtMgr.Subscribe(ev1, ev2, ev3) if err != nil { u.logger.Error("failed to subscribe to events", "error", err) close(doneChan) @@ -301,6 +311,18 @@ func (u *Updater) handleOpenedCommitment( return err } + if u.currentWindow.Load() > 2 && winner.Window < u.currentWindow.Load()-2 { + u.logger.Info( + "commitment is too old", + "commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]), + "winner", winner.Winner, + "window", winner.Window, + "currentWindow", u.currentWindow.Load(), + ) + u.metrics.CommitmentsTooOldCount.Inc() + return nil + } + if common.BytesToAddress(winner.Winner).Cmp(update.Committer) != 0 { // The winner is not the committer of the commitment u.logger.Info( @@ -343,8 +365,7 @@ func (u *Updater) handleOpenedCommitment( // Ensure Bundle is atomic and present in the block for i := 0; i < len(commitmentTxnHashes); i++ { txnDetails, found := txns[commitmentTxnHashes[i]] - if !found || txnDetails.PosInBlock != (txns[commitmentTxnHashes[0]].PosInBlock)+i || - (!txnDetails.Succeeded && !revertableTxnsMap[commitmentTxnHashes[i]]) { + if !found || txnDetails.PosInBlock != (txns[commitmentTxnHashes[0]].PosInBlock)+i || (!txnDetails.Succeeded && !revertableTxnsMap[commitmentTxnHashes[i]]) { u.logger.Info( "bundle does not satisfy committed requirements", "commitmentIdx", common.Bytes2Hex(update.CommitmentIndex[:]), diff --git a/oracle/pkg/updater/updater_test.go b/oracle/pkg/updater/updater_test.go index b6f76177a..cff14edfb 100644 --- a/oracle/pkg/updater/updater_test.go +++ b/oracle/pkg/updater/updater_test.go @@ -1223,7 +1223,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { t.Fatal(err) } - if i > 5 && i < 8 { + if i < 8 { continue } @@ -1239,7 +1239,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { if !bytes.Equal(commitment.commitmentIdx[:], c.CommitmentIndex[:]) { t.Fatal("wrong commitment index") } - if commitment.blockNum.Cmp(big.NewInt(10)) != 0 && commitment.blockNum.Cmp(big.NewInt(5)) != 0 { + if commitment.blockNum.Cmp(big.NewInt(10)) != 0 { t.Fatal("wrong block number", commitment.blockNum) } if commitment.builder != c.Committer { @@ -1263,7 +1263,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { if settlement.txHash != c.TxnHash { t.Fatal("wrong txn hash") } - if settlement.blockNum != 10 && settlement.blockNum != 5 { + if settlement.blockNum != 10 { t.Fatal("wrong block number") } if !bytes.Equal(settlement.builder, c.Committer.Bytes()) { @@ -1278,7 +1278,7 @@ func TestUpdaterIgnoreCommitments(t *testing.T) { if settlement.decayPercentage != 50*updater.PRECISION { t.Fatal("wrong decay percentage") } - if settlement.window != 5 && settlement.window != 1 { + if settlement.window != 5 { t.Fatal("wrong window") } } diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index 89ee1fe56..7ea8de280 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -249,6 +249,9 @@ func (s *Store) SetCommitmentIndexByDigest(cDigest, cIndex [32]byte) (retErr err commitmentKey := commitmentKey(cmt.Bid.BlockNumber, cmt.Bid.BidAmount, cmt.Commitment) + s.mu.Lock() + defer s.mu.Unlock() + var writer storage.Writer if w, ok := s.st.(storage.Batcher); ok { batch := w.Batch() diff --git a/p2p/pkg/preconfirmation/tracker/tracker.go b/p2p/pkg/preconfirmation/tracker/tracker.go index 95eaf70fa..fa07178e8 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker.go +++ b/p2p/pkg/preconfirmation/tracker/tracker.go @@ -7,6 +7,7 @@ import ( "fmt" "log/slog" "math/big" + "slices" "time" "github.com/consensys/gnark-crypto/ecc/bn254" @@ -29,7 +30,10 @@ import ( "golang.org/x/sync/errgroup" ) -const blockHistoryLimit = 10000 +const ( + blockHistoryLimit = 10000 + allowedDelayToOpenCommitment = 10 +) type Tracker struct { ctxChainIDData []byte @@ -220,6 +224,23 @@ func (t *Tracker) Start(ctx context.Context) <-chan struct{} { continue } t.logger.Debug("stored block winners", "count", len(winners)) + oldBlockNos := make([]int64, 0) + winners = slices.DeleteFunc(winners, func(item *store.BlockWinner) bool { + // the last block is the latest, so if any of the previous blocks are + // older than the allowed delay, we should not open the commitments + if winners[len(winners)-1].BlockNumber-item.BlockNumber > allowedDelayToOpenCommitment { + oldBlockNos = append(oldBlockNos, item.BlockNumber) + return true + } + return false + }) + // cleanup old state + for _, oldBlockNo := range oldBlockNos { + if err := t.store.ClearBlockNumber(oldBlockNo); err != nil { + t.logger.Error("failed to delete commitments by block number", "blockNumber", oldBlockNo, "error", err) + } + t.logger.Info("old block commitments deleted", "blockNumber", oldBlockNo) + } if t.peerType == p2p.PeerTypeBidder { if len(winners) > 2 { // Bidders should process the block 2 behind the current one. Ideally the diff --git a/p2p/pkg/preconfirmation/tracker/tracker_test.go b/p2p/pkg/preconfirmation/tracker/tracker_test.go index 247dc7fdb..12347a38c 100644 --- a/p2p/pkg/preconfirmation/tracker/tracker_test.go +++ b/p2p/pkg/preconfirmation/tracker/tracker_test.go @@ -470,6 +470,106 @@ func TestTracker(t *testing.T) { <-doneChan } +func TestTrackerIgnoreOldBlocks(t *testing.T) { + t.Parallel() + + pcABI, err := abi.JSON(strings.NewReader(preconf.PreconfmanagerABI)) + if err != nil { + t.Fatal(err) + } + + btABI, err := abi.JSON(strings.NewReader(blocktracker.BlocktrackerABI)) + if err != nil { + t.Fatal(err) + } + + brABI, err := abi.JSON(strings.NewReader(bidderregistry.BidderregistryABI)) + if err != nil { + t.Fatal(err) + } + + orABI, err := abi.JSON(strings.NewReader(oracle.OracleABI)) + if err != nil { + t.Fatal(err) + } + + evtMgr := events.NewListener( + util.NewTestLogger(os.Stdout), + &btABI, + &pcABI, + &brABI, + &orABI, + ) + + st := store.New(inmemstorage.New()) + + for _, b := range []int64{1, 12, 13} { + if err := st.AddWinner(&store.BlockWinner{ + BlockNumber: b, + Winner: common.HexToAddress("0x1234"), + }); err != nil { + t.Fatal(err) + } + } + + watcher := &mockWatcher{} + + contract := &testPreconfContract{ + openedCommitments: make(chan openedCommitment, 10), + } + + notifier := &mockNotifier{ + evt: make(chan *notifications.Notification, 10), + } + + sk, pk, err := crypto.GenerateKeyPairBN254() + if err != nil { + t.Fatal(err) + } + tracker := preconftracker.NewTracker( + big.NewInt(5), + p2p.PeerTypeProvider, + common.HexToAddress("0x1234"), + evtMgr, + st, + contract, + watcher, + notifier, + pk, + sk, + func(context.Context) (*bind.TransactOpts, error) { + return &bind.TransactOpts{ + From: common.HexToAddress("0x1234"), + }, nil + }, + util.NewTestLogger(os.Stdout), + ) + + ctx, cancel := context.WithCancel(context.Background()) + doneChan := tracker.Start(ctx) + + startTime := time.Now() + for { + winners, err := st.BlockWinners() + if err != nil { + t.Fatal(err) + } + + if len(winners) == 0 { + break + } + + time.Sleep(100 * time.Millisecond) + if time.Since(startTime) > 5*time.Second { + t.Fatal("timed out waiting for block winners to be cleared") + } + } + + cancel() + + <-doneChan +} + type openedCommitment struct { encryptedCommitmentIndex [32]byte bid *big.Int From d1916874ed9965dd679bde17122204f50b325d42 Mon Sep 17 00:00:00 2001 From: Alok Date: Wed, 28 May 2025 14:03:42 +0530 Subject: [PATCH 09/14] feat: preconf flow tracking --- contracts-abi/config/config.go | 2 ++ .../playbooks/templates/jobs/mev-commit.nomad.j2 | 1 + p2p/cmd/main.go | 15 +++++++++++++++ p2p/pkg/node/node.go | 9 +++++++++ 4 files changed, 27 insertions(+) diff --git a/contracts-abi/config/config.go b/contracts-abi/config/config.go index 1bba5502e..b86631ccb 100644 --- a/contracts-abi/config/config.go +++ b/contracts-abi/config/config.go @@ -23,12 +23,14 @@ var DefaultsContracts = map[string]Contracts{ BlockTracker: MevCommitChainContracts.BlockTracker, ProviderRegistry: MevCommitChainContracts.ProviderRegistry, BidderRegistry: MevCommitChainContracts.BidderRegistry, + Oracle: MevCommitChainContracts.Oracle, }, TestnetChainID.String(): { PreconfManager: TestnetContracts.PreconfManager, BlockTracker: TestnetContracts.BlockTracker, ProviderRegistry: TestnetContracts.ProviderRegistry, BidderRegistry: TestnetContracts.BidderRegistry, + Oracle: TestnetContracts.Oracle, }, } diff --git a/infrastructure/nomad/playbooks/templates/jobs/mev-commit.nomad.j2 b/infrastructure/nomad/playbooks/templates/jobs/mev-commit.nomad.j2 index fd2bb804f..3f2014235 100644 --- a/infrastructure/nomad/playbooks/templates/jobs/mev-commit.nomad.j2 +++ b/infrastructure/nomad/playbooks/templates/jobs/mev-commit.nomad.j2 @@ -171,6 +171,7 @@ job "{{ job.name }}" { export MEV_COMMIT_BIDDER_REGISTRY_ADDR="$(jq -r '.BidderRegistry' ${CONTRACTS_FILE})" export MEV_COMMIT_BLOCK_TRACKER_ADDR="$(jq -r '.BlockTracker' ${CONTRACTS_FILE})" export MEV_COMMIT_PRECONF_ADDR="$(jq -r '.PreconfManager' ${CONTRACTS_FILE})" + export MEV_COMMIT_ORACLE_ADDR="$(jq -r '.Oracle' ${CONTRACTS_FILE})" {{- range nomadService "beacon-emulator" }} {{ if contains "http" .Tags }} export MEV_COMMIT_VALIDATOR_ROUTER_ADDR="0x251Fbc993f58cBfDA8Ad7b0278084F915aCE7fc3" diff --git a/p2p/cmd/main.go b/p2p/cmd/main.go index a854dceeb..2c44b4e65 100644 --- a/p2p/cmd/main.go +++ b/p2p/cmd/main.go @@ -286,6 +286,19 @@ var ( Category: categoryContracts, }) + optionOracleAddr = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "oracle-contract", + Usage: "Address of the oracle contract", + EnvVars: []string{"MEV_COMMIT_ORACLE_ADDR"}, + Action: func(ctx *cli.Context, s string) error { + if s != "" && !common.IsHexAddress(s) { + return fmt.Errorf("invalid oracle address: %s", s) + } + return nil + }, + Category: categoryContracts, + }) + optionAutodepositAmount = altsrc.NewStringFlag(&cli.StringFlag{ Name: "autodeposit-amount", Usage: "Amount to auto deposit in each window in wei", @@ -490,6 +503,7 @@ func main() { optionPreconfStoreAddr, optionBlockTrackerAddr, optionValidatorRouterAddr, + optionOracleAddr, optionAutodepositAmount, optionAutodepositEnabled, optionSettlementRPCEndpoint, @@ -675,6 +689,7 @@ func launchNodeWithConfig(c *cli.Context) (err error) { BidderRegistryContract: c.String(optionBidderRegistryAddr.Name), BlockTrackerContract: c.String(optionBlockTrackerAddr.Name), ValidatorRouterContract: c.String(optionValidatorRouterAddr.Name), + OracleContract: c.String(optionOracleAddr.Name), AutodepositAmount: autodepositAmount, RPCEndpoint: c.String(optionSettlementRPCEndpoint.Name), WSRPCEndpoint: c.String(optionSettlementWSRPCEndpoint.Name), diff --git a/p2p/pkg/node/node.go b/p2p/pkg/node/node.go index 8271db6e1..afb918e2e 100644 --- a/p2p/pkg/node/node.go +++ b/p2p/pkg/node/node.go @@ -24,6 +24,7 @@ import ( "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" bidderregistry "github.com/primev/mev-commit/contracts-abi/clients/BidderRegistry" blocktracker "github.com/primev/mev-commit/contracts-abi/clients/BlockTracker" + oracle "github.com/primev/mev-commit/contracts-abi/clients/Oracle" preconf "github.com/primev/mev-commit/contracts-abi/clients/PreconfManager" providerregistry "github.com/primev/mev-commit/contracts-abi/clients/ProviderRegistry" validatorrouter "github.com/primev/mev-commit/contracts-abi/clients/ValidatorOptInRouter" @@ -111,6 +112,7 @@ type Options struct { BlockTrackerContract string ProviderRegistryContract string BidderRegistryContract string + OracleContract string ValidatorRouterContract string AutodepositAmount *big.Int RPCEndpoint string @@ -178,6 +180,7 @@ func NewNode(opts *Options) (*Node, error) { setDefault(&opts.BlockTrackerContract, defaults.BlockTracker) setDefault(&opts.ProviderRegistryContract, defaults.ProviderRegistry) setDefault(&opts.BidderRegistryContract, defaults.BidderRegistry) + setDefault(&opts.OracleContract, defaults.Oracle) } if defaults, ok := contracts.DefaultsL1Contracts[chainID.String()]; ok { setDefault(&opts.ValidatorRouterContract, defaults.ValidatorOptInRouter) @@ -905,6 +908,12 @@ func getContractABIs(opts *Options) (map[common.Address]*abi.ABI, error) { } abis[common.HexToAddress(opts.ValidatorRouterContract)] = &vrABI + orABI, err := abi.JSON(strings.NewReader(oracle.OracleABI)) + if err != nil { + return nil, err + } + abis[common.HexToAddress(opts.OracleContract)] = &orABI + return abis, nil } From 45065d37f12f170384681fc5432a79bd2ab39521 Mon Sep 17 00:00:00 2001 From: Alok Date: Thu, 29 May 2025 17:14:04 +0530 Subject: [PATCH 10/14] feat: preconf flow tracking --- p2p/pkg/node/node.go | 6 ++++++ p2p/pkg/stakemanager/stakemanager.go | 1 + 2 files changed, 7 insertions(+) diff --git a/p2p/pkg/node/node.go b/p2p/pkg/node/node.go index afb918e2e..7189c2ae3 100644 --- a/p2p/pkg/node/node.go +++ b/p2p/pkg/node/node.go @@ -914,6 +914,12 @@ func getContractABIs(opts *Options) (map[common.Address]*abi.ABI, error) { } abis[common.HexToAddress(opts.OracleContract)] = &orABI + prABI, err := abi.JSON(strings.NewReader(providerregistry.ProviderregistryABI)) + if err != nil { + return nil, err + } + abis[common.HexToAddress(opts.ProviderRegistryContract)] = &prABI + return abis, nil } diff --git a/p2p/pkg/stakemanager/stakemanager.go b/p2p/pkg/stakemanager/stakemanager.go index 60ec36202..b8819d0d7 100644 --- a/p2p/pkg/stakemanager/stakemanager.go +++ b/p2p/pkg/stakemanager/stakemanager.go @@ -91,6 +91,7 @@ func (sm *StakeManager) Start(ctx context.Context) <-chan struct{} { sub, err := sm.evtMgr.Subscribe(ev1, ev2, ev3, ev4, ev5) if err != nil { close(doneChan) + sm.logger.Error("failed to subscribe to events", "error", err) return doneChan } From ba959d9519ca880178391573f6ce2ecfefbd6efe Mon Sep 17 00:00:00 2001 From: Alok Date: Thu, 29 May 2025 18:54:06 +0530 Subject: [PATCH 11/14] feat: preconf flow tracking --- p2p/gen/go/bidderapi/v1/bidderapi.pb.go | 59 +++++++++---------- p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go | 26 ++------ .../bidderapi/v1/bidderapi.swagger.yaml | 6 +- p2p/rpc/bidderapi/v1/bidderapi.proto | 8 +-- 4 files changed, 38 insertions(+), 61 deletions(-) diff --git a/p2p/gen/go/bidderapi/v1/bidderapi.pb.go b/p2p/gen/go/bidderapi/v1/bidderapi.pb.go index 27116c5ee..644b703a5 100644 --- a/p2p/gen/go/bidderapi/v1/bidderapi.pb.go +++ b/p2p/gen/go/bidderapi/v1/bidderapi.pb.go @@ -2039,7 +2039,7 @@ var file_bidderapi_v1_bidderapi_proto_rawDesc = []byte{ 0x31, 0x92, 0x41, 0x2e, 0x32, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x69, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x2e, 0x52, 0x04, 0x62, 0x69, 0x64, 0x73, 0x32, 0xbe, 0x09, 0x0a, 0x06, 0x42, 0x69, 0x64, + 0x72, 0x2e, 0x52, 0x04, 0x62, 0x69, 0x64, 0x73, 0x32, 0xaf, 0x09, 0x0a, 0x06, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x69, 0x64, 0x12, 0x11, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x64, 0x1a, 0x18, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, @@ -2100,41 +2100,40 @@ var file_bidderapi_v1_bidderapi_proto_rawDesc = []byte{ 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x12, 0x7f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x77, 0x12, 0x70, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x76, 0x31, 0x2f, + 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x64, 0x5f, 0x69, - 0x6e, 0x66, 0x6f, 0x2f, 0x7b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x7d, 0x12, 0x75, 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x53, 0x6c, 0x61, 0x73, 0x68, - 0x65, 0x64, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x62, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x73, 0x6c, 0x61, 0x73, - 0x68, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x42, 0xaa, 0x02, 0x92, 0x41, 0x72, 0x12, - 0x70, 0x0a, 0x0a, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, 0x0a, - 0x1b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, 0x74, - 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, 0x43, - 0x45, 0x4e, 0x53, 0x45, 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x6f, 0x12, 0x75, 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x65, 0x64, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, + 0x72, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x73, 0x6c, 0x61, + 0x73, 0x68, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x42, 0xaa, 0x02, 0x92, 0x41, 0x72, + 0x12, 0x70, 0x0a, 0x0a, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x20, 0x41, 0x50, 0x49, 0x2a, 0x55, + 0x0a, 0x1b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x12, 0x36, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x62, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x69, 0x64, 0x64, - 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, 0x0c, - 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x42, - 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x42, 0x69, - 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, - 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x69, 0x74, 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x4c, 0x49, + 0x43, 0x45, 0x4e, 0x53, 0x45, 0x32, 0x0b, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0e, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x76, 0x2f, 0x6d, 0x65, 0x76, 0x2d, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, + 0x62, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, + 0x0c, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, + 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x42, + 0x69, 0x64, 0x64, 0x65, 0x72, 0x61, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x42, 0x69, 0x64, 0x64, 0x65, 0x72, + 0x61, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go b/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go index 03f084c65..860960af6 100644 --- a/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go +++ b/p2p/gen/go/bidderapi/v1/bidderapi.pb.gw.go @@ -299,23 +299,14 @@ func local_request_Bidder_Withdraw_0(ctx context.Context, marshaler runtime.Mars return msg, metadata, err } -var filter_Bidder_GetBidInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{"block_number": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +var filter_Bidder_GetBidInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} func request_Bidder_GetBidInfo_0(ctx context.Context, marshaler runtime.Marshaler, client BidderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( protoReq GetBidInfoRequest metadata runtime.ServerMetadata - err error ) io.Copy(io.Discard, req.Body) - val, ok := pathParams["block_number"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "block_number") - } - protoReq.BlockNumber, err = runtime.Int64(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "block_number", err) - } if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -330,16 +321,7 @@ func local_request_Bidder_GetBidInfo_0(ctx context.Context, marshaler runtime.Ma var ( protoReq GetBidInfoRequest metadata runtime.ServerMetadata - err error ) - val, ok := pathParams["block_number"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "block_number") - } - protoReq.BlockNumber, err = runtime.Int64(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "block_number", err) - } if err := req.ParseForm(); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -527,7 +509,7 @@ func RegisterBidderHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/bidderapi.v1.Bidder/GetBidInfo", runtime.WithHTTPPathPattern("/v1/bidder/get_bid_info/{block_number}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/bidderapi.v1.Bidder/GetBidInfo", runtime.WithHTTPPathPattern("/v1/bidder/get_bid_info")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -741,7 +723,7 @@ func RegisterBidderHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/bidderapi.v1.Bidder/GetBidInfo", runtime.WithHTTPPathPattern("/v1/bidder/get_bid_info/{block_number}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/bidderapi.v1.Bidder/GetBidInfo", runtime.WithHTTPPathPattern("/v1/bidder/get_bid_info")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -783,7 +765,7 @@ var ( pattern_Bidder_WithdrawFromWindows_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "withdraw_from_windows"}, "")) pattern_Bidder_GetDeposit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "get_deposit"}, "")) pattern_Bidder_Withdraw_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "withdraw"}, "")) - pattern_Bidder_GetBidInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "bidder", "get_bid_info", "block_number"}, "")) + pattern_Bidder_GetBidInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "get_bid_info"}, "")) pattern_Bidder_ClaimSlashedFunds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "bidder", "claim_slashed_funds"}, "")) ) diff --git a/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml b/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml index c53d1fd68..131c67841 100644 --- a/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml +++ b/p2p/gen/openapi/bidderapi/v1/bidderapi.swagger.yaml @@ -164,7 +164,7 @@ paths: required: false type: string format: uint64 - /v1/bidder/get_bid_info/{blockNumber}: + /v1/bidder/get_bid_info: get: summary: GetBidInfo description: |- @@ -183,8 +183,8 @@ paths: parameters: - name: blockNumber description: Optional block number for querying bid info. If not specified, all known block numbers are returned in ascending order. - in: path - required: true + in: query + required: false type: string format: int64 - name: page diff --git a/p2p/rpc/bidderapi/v1/bidderapi.proto b/p2p/rpc/bidderapi/v1/bidderapi.proto index 554364047..46b87124c 100644 --- a/p2p/rpc/bidderapi/v1/bidderapi.proto +++ b/p2p/rpc/bidderapi/v1/bidderapi.proto @@ -101,18 +101,14 @@ service Bidder { // GetBidInfo is called by the bidder to get the bid information. If block number is not specified, // all known block numbers are returned in the ascending order. rpc GetBidInfo(GetBidInfoRequest) returns (GetBidInfoResponse) { - option (google.api.http) = { - get: "/v1/bidder/get_bid_info/{block_number}" - }; + option (google.api.http) = {get: "/v1/bidder/get_bid_info"}; } // ClaimSlashedFunds // // ClaimSlashedFunds is called by the bidder to claim slashed funds from the provider. The response // will show the amount claimed if any in wei. rpc ClaimSlashedFunds(EmptyMessage) returns (google.protobuf.StringValue) { - option (google.api.http) = { - post: "/v1/bidder/claim_slashed_funds" - }; + option (google.api.http) = {post: "/v1/bidder/claim_slashed_funds"}; } } From 00e68fa92c5203e4751b224cdf7403a962af4f3a Mon Sep 17 00:00:00 2001 From: Alok Date: Thu, 29 May 2025 20:24:23 +0530 Subject: [PATCH 12/14] feat: preconf flow tracking --- p2p/pkg/preconfirmation/store/store.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/p2p/pkg/preconfirmation/store/store.go b/p2p/pkg/preconfirmation/store/store.go index 7ea8de280..943955d88 100644 --- a/p2p/pkg/preconfirmation/store/store.go +++ b/p2p/pkg/preconfirmation/store/store.go @@ -391,11 +391,10 @@ func (s *Store) ClearCommitmentIndexes(uptoBlock int64) error { keys = append(keys, indexToDigestKey(commitment.CommitmentIndex)) } return false - } else { - // DB is expected to be sorted by block number, so we can stop here - // since all subsequent keys will also be greater than or equal to `uptoBlock`. - return true } + // DB is expected to be sorted by block number, so we can stop here + // since all subsequent keys will also be greater than or equal to `uptoBlock`. + return true }) s.mu.RUnlock() if err != nil { From 86634b7ac0a34cb8e6b6d29371d28560b84178b9 Mon Sep 17 00:00:00 2001 From: Alok Nerurkar Date: Fri, 30 May 2025 00:43:52 +0530 Subject: [PATCH 13/14] fix: dispatch timestamp for provider --- p2p/pkg/rpc/provider/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p2p/pkg/rpc/provider/service.go b/p2p/pkg/rpc/provider/service.go index d4f0b53ef..79841ebb2 100644 --- a/p2p/pkg/rpc/provider/service.go +++ b/p2p/pkg/rpc/provider/service.go @@ -551,7 +551,7 @@ func (s *Service) GetCommitmentInfo( ProviderAddress: common.Bytes2Hex(c.ProviderAddress), DecayStartTimestamp: c.Bid.DecayStartTimestamp, DecayEndTimestamp: c.Bid.DecayEndTimestamp, - DispatchTimestamp: c.PreConfirmation.DispatchTimestamp, + DispatchTimestamp: c.EncryptedPreConfirmation.DispatchTimestamp, SlashAmount: c.Bid.SlashAmount, Status: string(c.Status), Details: c.Details, From 79448ad4286a7586a5da35b03c4a601b6de2e51d Mon Sep 17 00:00:00 2001 From: Alok Nerurkar Date: Fri, 30 May 2025 01:03:08 +0530 Subject: [PATCH 14/14] fix: dispatch timestamp for provider --- p2p/pkg/rpc/provider/service_test.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/p2p/pkg/rpc/provider/service_test.go b/p2p/pkg/rpc/provider/service_test.go index 012581f60..b6b0461a9 100644 --- a/p2p/pkg/rpc/provider/service_test.go +++ b/p2p/pkg/rpc/provider/service_test.go @@ -666,6 +666,9 @@ func TestGetCommitmentInfo(t *testing.T) { t.Run("get commitment info", func(t *testing.T) { // Create a test commitment testCommitment := &preconfstore.Commitment{ + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + DispatchTimestamp: 123456889, + }, PreConfirmation: &preconfpb.PreConfirmation{ Bid: &preconfpb.Bid{ TxHash: "0x1234567890abcdef,0x1234567890abcdef", @@ -674,8 +677,7 @@ func TestGetCommitmentInfo(t *testing.T) { DecayStartTimestamp: 123456789, DecayEndTimestamp: 123457896, }, - DispatchTimestamp: 123456889, - ProviderAddress: common.HexToAddress("0x1234").Bytes(), + ProviderAddress: common.HexToAddress("0x1234").Bytes(), }, Status: preconfstore.CommitmentStatusOpened, Details: "test details", @@ -739,6 +741,9 @@ func TestGetCommitmentInfo(t *testing.T) { t.Run("get all commitments", func(t *testing.T) { testCommitments := []*preconfstore.Commitment{ { + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + DispatchTimestamp: 123456889, + }, PreConfirmation: &preconfpb.PreConfirmation{ Bid: &preconfpb.Bid{ TxHash: "0x1234567890abcdef,0x1234567890abcdef", @@ -747,8 +752,7 @@ func TestGetCommitmentInfo(t *testing.T) { DecayStartTimestamp: 123456789, DecayEndTimestamp: 123457896, }, - DispatchTimestamp: 123456889, - ProviderAddress: common.HexToAddress("0x1234").Bytes(), + ProviderAddress: common.HexToAddress("0x1234").Bytes(), }, Status: preconfstore.CommitmentStatusOpened, Details: "test details", @@ -756,6 +760,9 @@ func TestGetCommitmentInfo(t *testing.T) { Refund: "100000000000000000", }, { + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + DispatchTimestamp: 123456889, + }, PreConfirmation: &preconfpb.PreConfirmation{ Bid: &preconfpb.Bid{ TxHash: "0xabcdef1234567890,0xabcdef1234567890", @@ -764,8 +771,7 @@ func TestGetCommitmentInfo(t *testing.T) { DecayStartTimestamp: 123456789, DecayEndTimestamp: 123457896, }, - DispatchTimestamp: 123456889, - ProviderAddress: common.HexToAddress("0x5678").Bytes(), + ProviderAddress: common.HexToAddress("0x5678").Bytes(), }, Status: preconfstore.CommitmentStatusSettled, Details: "another test details", @@ -773,6 +779,9 @@ func TestGetCommitmentInfo(t *testing.T) { Refund: "200000000000000000", }, { + EncryptedPreConfirmation: &preconfpb.EncryptedPreConfirmation{ + DispatchTimestamp: 123456889, + }, PreConfirmation: &preconfpb.PreConfirmation{ Bid: &preconfpb.Bid{ TxHash: "0xabcdef1234567890,0xabcdef1234567890", @@ -781,8 +790,7 @@ func TestGetCommitmentInfo(t *testing.T) { DecayStartTimestamp: 123456789, DecayEndTimestamp: 123457896, }, - DispatchTimestamp: 123456889, - ProviderAddress: common.HexToAddress("0x9abc").Bytes(), + ProviderAddress: common.HexToAddress("0x9abc").Bytes(), }, Status: preconfstore.CommitmentStatusFailed, Details: "yet another test details", @@ -821,8 +829,8 @@ func TestGetCommitmentInfo(t *testing.T) { if commitment.Commitments[0].Amount != testCommitments[i].Bid.BidAmount { t.Fatalf("expected bid amount to be %s, got %s", testCommitments[i].Bid.BidAmount, commitment.Commitments[0].Amount) } - if commitment.Commitments[0].DispatchTimestamp != testCommitments[i].PreConfirmation.DispatchTimestamp { - t.Fatalf("expected dispatch timestamp to be %d, got %d", testCommitments[i].PreConfirmation.DispatchTimestamp, commitment.Commitments[0].DispatchTimestamp) + if commitment.Commitments[0].DispatchTimestamp != testCommitments[i].EncryptedPreConfirmation.DispatchTimestamp { + t.Fatalf("expected dispatch timestamp to be %d, got %d", testCommitments[i].EncryptedPreConfirmation.DispatchTimestamp, commitment.Commitments[0].DispatchTimestamp) } if commitment.Commitments[0].ProviderAddress != strings.TrimPrefix(common.Bytes2Hex(testCommitments[i].ProviderAddress), "0x") { t.Fatalf("expected provider address to be 0x1234, 0x5678 or 0x9abc, got %s", commitment.Commitments[0].ProviderAddress)