diff --git a/cmd/utils/hierarchical_coordinator.go b/cmd/utils/hierarchical_coordinator.go index c9e1c36b93..2251a8f6f5 100644 --- a/cmd/utils/hierarchical_coordinator.go +++ b/cmd/utils/hierarchical_coordinator.go @@ -155,8 +155,7 @@ func (hc *HierarchicalCoordinator) startNode(logPath string, quaiBackend quai.Co if quaiBackend.ProcessingState(location) && location.Context() == common.ZONE_CTX { // Subscribe to the new topics after setting the api backend - hc.p2p.Subscribe(location, &types.WorkObjectHeader{}) - hc.p2p.Subscribe(location, &types.Transactions{}) + hc.p2p.Subscribe(location, &types.WorkObjectShareView{}) } if location.Context() == common.PRIME_CTX || location.Context() == common.REGION_CTX || quaiBackend.ProcessingState(location) { diff --git a/consensus/blake3pow/consensus.go b/consensus/blake3pow/consensus.go index 0c4021fa91..4b03bd4193 100644 --- a/consensus/blake3pow/consensus.go +++ b/consensus/blake3pow/consensus.go @@ -272,10 +272,6 @@ func (blake3pow *Blake3pow) VerifyUncles(chain consensus.ChainReader, block *typ if diff := new(big.Int).Sub(uncle.Number(), parentNumber); diff.Cmp(big.NewInt(1)) != 0 { return consensus.ErrInvalidNumber } - - if !blake3pow.CheckIfValidWorkShare(uncle) { - return errors.New("invalid workshare included") - } } } return nil diff --git a/consensus/progpow/consensus.go b/consensus/progpow/consensus.go index 8820e4e291..4efc013645 100644 --- a/consensus/progpow/consensus.go +++ b/consensus/progpow/consensus.go @@ -273,11 +273,6 @@ func (progpow *Progpow) VerifyUncles(chain consensus.ChainReader, block *types.W if diff := new(big.Int).Sub(uncle.Number(), parentNumber); diff.Cmp(big.NewInt(1)) != 0 { return consensus.ErrInvalidNumber } - - if !progpow.CheckIfValidWorkShare(uncle) { - return errors.New("invalid workshare included") - } - } } return nil diff --git a/core/core.go b/core/core.go index f6d7da0e29..fe9f4c5b1d 100644 --- a/core/core.go +++ b/core/core.go @@ -50,6 +50,7 @@ const ( c_normalListBackoffThreshold = 5 // Max multiple on the c_normalListProcCounter c_maxRemoteTxQueue = 50000 c_remoteTxProcPeriod = 2 // Time between remote tx pool processing + c_asyncWorkShareTimer = 100 * time.Millisecond ) type blockNumberAndRetryCounter struct { @@ -541,6 +542,10 @@ func (c *Core) TxPool() *TxPool { return c.sl.txPool } +func (c *Core) GetTxsFromBroadcastSet(hash common.Hash) (types.Transactions, error) { + return c.sl.GetTxsFromBroadcastSet(hash) +} + func (c *Core) Stop() { // Delete the append queue c.appendQueue.Purge() @@ -651,6 +656,10 @@ func (c *Core) ConstructLocalMinedBlock(woHeader *types.WorkObject) (*types.Work return c.sl.ConstructLocalMinedBlock(woHeader) } +func (c *Core) GetPendingBlockBody(woHeader *types.WorkObjectHeader) *types.WorkObject { + return c.sl.GetPendingBlockBody(woHeader) +} + func (c *Core) SubRelayPendingHeader(slPendingHeader types.PendingHeader, newEntropy *big.Int, location common.Location, subReorg bool, order int) { c.sl.SubRelayPendingHeader(slPendingHeader, newEntropy, location, subReorg, order) } @@ -994,10 +1003,6 @@ func (c *Core) TxLookupLimit() uint64 { return 0 } -func (c *Core) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscription { - return c.sl.txPool.SubscribeNewTxsEvent(ch) -} - func (c *Core) SetExtra(extra []byte) error { return c.sl.miner.SetExtra(extra) } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 330f80b460..80f5d5fc41 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -750,7 +750,7 @@ func WriteWorkObjectBody(db ethdb.KeyValueWriter, hash common.Hash, workObject * key := workObjectBodyKey(hash) WriteHeaderNumber(db, hash, workObject.NumberU64(nodeCtx)) - protoWorkObjectBody, err := workObject.Body().ProtoEncode() + protoWorkObjectBody, err := workObject.Body().ProtoEncode(woType) if err != nil { db.Logger().WithField("err", err).Fatal("Failed to proto encode work object body") } @@ -1044,7 +1044,7 @@ func (b badWorkObject) ProtoEncode() *ProtoBadWorkObject { if err != nil { log.Global.WithField("err", err).Fatal("Failed to proto encode header") } - protoWorkObjectBody, err := b.woBody.ProtoEncode() + protoWorkObjectBody, err := b.woBody.ProtoEncode(types.BlockObject) if err != nil { log.Global.WithField("err", err).Fatal("Failed to proto encode body") } diff --git a/core/slice.go b/core/slice.go index eda899be43..24e9c73062 100644 --- a/core/slice.go +++ b/core/slice.go @@ -152,6 +152,7 @@ func NewSlice(db ethdb.Database, config *Config, txConfig *TxPoolConfig, txLooku if nodeCtx == common.ZONE_CTX && sl.ProcessingState() { go sl.asyncPendingHeaderLoop() + go sl.asyncWorkShareUpdateLoop() } return sl, nil @@ -1323,7 +1324,7 @@ func (sl *Slice) ConstructLocalMinedBlock(wo *types.WorkObject) (*types.WorkObje nodeCtx := sl.NodeLocation().Context() var pendingBlockBody *types.WorkObject if nodeCtx == common.ZONE_CTX { - pendingBlockBody = sl.GetPendingBlockBody(wo) + pendingBlockBody = sl.GetPendingBlockBody(wo.WorkObjectHeader()) if pendingBlockBody == nil { sl.logger.WithFields(log.Fields{"wo.Hash": wo.Hash(), "wo.Header": wo.HeaderHash(), @@ -1413,8 +1414,10 @@ func (sl *Slice) combinePendingHeader(header *types.WorkObject, slPendingHeader } if inSlice { - combinedPendingHeader.Header().SetEtxRollupHash(header.EtxRollupHash()) combinedPendingHeader.WorkObjectHeader().SetDifficulty(header.Difficulty()) + combinedPendingHeader.WorkObjectHeader().SetTxHash(header.TxHash()) + + combinedPendingHeader.Header().SetEtxRollupHash(header.EtxRollupHash()) combinedPendingHeader.Header().SetUncledS(header.Header().UncledS()) combinedPendingHeader.Header().SetUncleHash(header.UncleHash()) combinedPendingHeader.Header().SetTxHash(header.Header().TxHash()) @@ -1578,7 +1581,7 @@ func (sl *Slice) NewGenesisPendingHeader(domPendingHeader *types.WorkObject, dom return nil } -func (sl *Slice) GetPendingBlockBody(wo *types.WorkObject) *types.WorkObject { +func (sl *Slice) GetPendingBlockBody(wo *types.WorkObjectHeader) *types.WorkObject { blockBody, _ := sl.miner.worker.GetPendingBlockBody(wo) return blockBody } @@ -1877,6 +1880,48 @@ func (sl *Slice) GetSlicesRunning() []common.Location { return sl.hc.SlicesRunning() } +func (sl *Slice) asyncWorkShareUpdateLoop() { + defer func() { + if r := recover(); r != nil { + sl.logger.WithFields(log.Fields{ + "error": r, + "stacktrace": string(debug.Stack()), + }).Error("Go-Quai Panicked") + } + }() + asyncTimer := time.NewTicker(c_asyncWorkShareTimer) + defer asyncTimer.Stop() + for { + select { + case <-asyncTimer.C: + // Every time we read the broadcast set, get the next set of transactions and + // update the phcache + // Get the latest transactions to be broadcasted from the pool + sl.txPool.broadcastSetMu.RLock() + if len(sl.txPool.broadcastSet) > 0 { + txs := sl.txPool.broadcastSet + hash := types.DeriveSha(txs, trie.NewStackTrie(nil)) + bestPh, exists := sl.readPhCache(sl.bestPhKey) + if exists { + bestPh.WorkObject().WorkObjectHeader().SetLocation(sl.NodeLocation()) + bestPh.WorkObject().WorkObjectHeader().SetTxHash(hash) + sl.writePhCache(sl.bestPhKey, bestPh) + sl.miner.worker.pendingHeaderFeed.Send(bestPh.WorkObject()) + } + sl.txPool.broadcastSetCache.Add(hash, txs) + } + sl.txPool.broadcastSetMu.RUnlock() + case <-sl.quit: + return + } + } +} + +func (sl *Slice) GetTxsFromBroadcastSet(hash common.Hash) (types.Transactions, error) { + sl.txPool.broadcastSet = types.Transactions{} + return sl.txPool.GetTxsFromBroadcastSet(hash) +} + ////// Expansion related logic const ( diff --git a/core/tx_pool.go b/core/tx_pool.go index 229c2c4689..4b1f3f9a1c 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -59,6 +59,10 @@ const ( // c_reorgCounterThreshold determines the frequency of the timing prints // around important functions in txpool c_reorgCounterThreshold = 200 + + // c_broadcastSetCacheSize is the maxminum number of latest broadcastSets that we keep in + // the pool + c_broadcastSetCacheSize = 10 ) var ( @@ -194,7 +198,7 @@ var DefaultTxPoolConfig = TxPoolConfig{ GlobalQueue: 2048, QiPoolSize: 10024, Lifetime: 3 * time.Hour, - ReorgFrequency: 2 * time.Second, + ReorgFrequency: 1 * time.Second, } // sanitize checks the provided user configurations and changes anything that's @@ -286,7 +290,6 @@ type TxPool struct { chainconfig *params.ChainConfig chain blockChain gasPrice *big.Int - txFeed event.Feed scope event.SubscriptionScope signer types.Signer mu sync.RWMutex @@ -310,6 +313,10 @@ type TxPool struct { localTxsCount int // count of txs in last 1 min. Purely for logging purpose remoteTxsCount int // count of txs in last 1 min. Purely for logging purpose + broadcastSetCache *lru.Cache[common.Hash, types.Transactions] + broadcastSetMu sync.RWMutex + broadcastSet types.Transactions + reOrgCounter int // keeps track of the number of times the runReorg is called, it is reset every c_reorgCounterThreshold times chainHeadCh chan ChainHeadEvent @@ -379,6 +386,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block reqResetCh: make(chan *txpoolResetRequest), reqPromoteCh: make(chan *accountSet), queueTxEventCh: make(chan *types.Transaction), + broadcastSet: make(types.Transactions, 0), reorgDoneCh: make(chan chan struct{}), reorgShutdownCh: make(chan struct{}), gasPrice: new(big.Int).SetUint64(config.PriceLimit), @@ -388,6 +396,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block logger: logger, } pool.senders, _ = lru.New[common.Hash, common.InternalAddress](int(config.MaxSenders)) + pool.broadcastSetCache, _ = lru.New[common.Hash, types.Transactions](c_broadcastSetCacheSize) pool.locals = newAccountSet(pool.signer) for _, addr := range config.Locals { logger.WithField("address", addr).Debug("Setting new local account") @@ -524,12 +533,6 @@ func (pool *TxPool) Stop() { pool.logger.Info("Transaction pool stopped") } -// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and -// starts sending event to the given channel. -func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscription { - return pool.scope.Track(pool.txFeed.Subscribe(ch)) -} - // GasPrice returns the current gas price enforced by the transaction pool. func (pool *TxPool) GasPrice() *big.Int { pool.mu.RLock() @@ -636,6 +639,14 @@ func (pool *TxPool) QiPoolPending() map[common.Hash]*types.TxWithMinerFee { return qiTxs } +func (pool *TxPool) GetTxsFromBroadcastSet(hash common.Hash) (types.Transactions, error) { + txs, ok := pool.broadcastSetCache.Get(hash) + if !ok { + return types.Transactions{}, fmt.Errorf("cannot find the txs in the broadcast set for txhash [%s]", hash) + } + return txs, nil +} + // Pending retrieves all currently processable transactions, grouped by origin // account and sorted by nonce. The returned transaction set is a copy and can be // freely modified by calling code. @@ -1573,16 +1584,19 @@ func (pool *TxPool) runReorg(done chan struct{}, cancel chan struct{}, reset *tx } events[internal].Put(tx) } + var txs []*types.Transaction if len(events) > 0 { - var txs []*types.Transaction for _, set := range events { txs = append(txs, set.Flatten()...) } - pool.txFeed.Send(NewTxsEvent{txs}) } if len(queuedQiTxs) > 0 { - pool.txFeed.Send(NewTxsEvent{queuedQiTxs}) + txs = append(txs, queuedQiTxs...) } + pool.broadcastSetMu.Lock() + pool.broadcastSet = append(pool.broadcastSet, txs...) + pool.broadcastSetMu.Unlock() + if pool.reOrgCounter == c_reorgCounterThreshold { pool.logger.WithField("time", common.PrettyDuration(time.Since(start))).Debug("Time taken to runReorg in txpool") pool.reOrgCounter = 0 diff --git a/core/types/block.go b/core/types/block.go index efac566fa5..118422df19 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -836,6 +836,9 @@ func (h *Header) EmptyReceipts() bool { // CopyHeader creates a deep copy of a block header to prevent side effects from // modifying a header variable. func CopyHeader(h *Header) *Header { + if h == nil { + return nil + } cpy := *h cpy.parentHash = make([]common.Hash, common.HierarchyDepth-1) cpy.manifestHash = make([]common.Hash, common.HierarchyDepth) diff --git a/core/types/proto_block.pb.go b/core/types/proto_block.pb.go index c3276f6ba1..4163fb066b 100644 --- a/core/types/proto_block.pb.go +++ b/core/types/proto_block.pb.go @@ -1152,6 +1152,53 @@ func (x *ProtoWorkObjectHeaderView) GetWorkObject() *ProtoWorkObject { return nil } +type ProtoWorkObjectShareView struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + WorkObject *ProtoWorkObject `protobuf:"bytes,1,opt,name=work_object,json=workObject,proto3,oneof" json:"work_object,omitempty"` +} + +func (x *ProtoWorkObjectShareView) Reset() { + *x = ProtoWorkObjectShareView{} + if protoimpl.UnsafeEnabled { + mi := &file_core_types_proto_block_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProtoWorkObjectShareView) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProtoWorkObjectShareView) ProtoMessage() {} + +func (x *ProtoWorkObjectShareView) ProtoReflect() protoreflect.Message { + mi := &file_core_types_proto_block_proto_msgTypes[13] + 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 ProtoWorkObjectShareView.ProtoReflect.Descriptor instead. +func (*ProtoWorkObjectShareView) Descriptor() ([]byte, []int) { + return file_core_types_proto_block_proto_rawDescGZIP(), []int{13} +} + +func (x *ProtoWorkObjectShareView) GetWorkObject() *ProtoWorkObject { + if x != nil { + return x.WorkObject + } + return nil +} + type ProtoAccessTuple struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1164,7 +1211,7 @@ type ProtoAccessTuple struct { func (x *ProtoAccessTuple) Reset() { *x = ProtoAccessTuple{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[13] + mi := &file_core_types_proto_block_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1177,7 +1224,7 @@ func (x *ProtoAccessTuple) String() string { func (*ProtoAccessTuple) ProtoMessage() {} func (x *ProtoAccessTuple) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[13] + mi := &file_core_types_proto_block_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1190,7 +1237,7 @@ func (x *ProtoAccessTuple) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoAccessTuple.ProtoReflect.Descriptor instead. func (*ProtoAccessTuple) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{13} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{14} } func (x *ProtoAccessTuple) GetAddress() []byte { @@ -1224,7 +1271,7 @@ type ProtoReceiptForStorage struct { func (x *ProtoReceiptForStorage) Reset() { *x = ProtoReceiptForStorage{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[14] + mi := &file_core_types_proto_block_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1237,7 +1284,7 @@ func (x *ProtoReceiptForStorage) String() string { func (*ProtoReceiptForStorage) ProtoMessage() {} func (x *ProtoReceiptForStorage) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[14] + mi := &file_core_types_proto_block_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1250,7 +1297,7 @@ func (x *ProtoReceiptForStorage) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoReceiptForStorage.ProtoReflect.Descriptor instead. func (*ProtoReceiptForStorage) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{14} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{15} } func (x *ProtoReceiptForStorage) GetPostStateOrStatus() []byte { @@ -1313,7 +1360,7 @@ type ProtoReceiptsForStorage struct { func (x *ProtoReceiptsForStorage) Reset() { *x = ProtoReceiptsForStorage{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[15] + mi := &file_core_types_proto_block_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1326,7 +1373,7 @@ func (x *ProtoReceiptsForStorage) String() string { func (*ProtoReceiptsForStorage) ProtoMessage() {} func (x *ProtoReceiptsForStorage) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[15] + mi := &file_core_types_proto_block_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1339,7 +1386,7 @@ func (x *ProtoReceiptsForStorage) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoReceiptsForStorage.ProtoReflect.Descriptor instead. func (*ProtoReceiptsForStorage) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{15} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{16} } func (x *ProtoReceiptsForStorage) GetReceipts() []*ProtoReceiptForStorage { @@ -1362,7 +1409,7 @@ type ProtoLogForStorage struct { func (x *ProtoLogForStorage) Reset() { *x = ProtoLogForStorage{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[16] + mi := &file_core_types_proto_block_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1375,7 +1422,7 @@ func (x *ProtoLogForStorage) String() string { func (*ProtoLogForStorage) ProtoMessage() {} func (x *ProtoLogForStorage) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[16] + mi := &file_core_types_proto_block_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1388,7 +1435,7 @@ func (x *ProtoLogForStorage) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoLogForStorage.ProtoReflect.Descriptor instead. func (*ProtoLogForStorage) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{16} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{17} } func (x *ProtoLogForStorage) GetAddress() *common.ProtoAddress { @@ -1423,7 +1470,7 @@ type ProtoLogsForStorage struct { func (x *ProtoLogsForStorage) Reset() { *x = ProtoLogsForStorage{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[17] + mi := &file_core_types_proto_block_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1436,7 +1483,7 @@ func (x *ProtoLogsForStorage) String() string { func (*ProtoLogsForStorage) ProtoMessage() {} func (x *ProtoLogsForStorage) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[17] + mi := &file_core_types_proto_block_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1449,7 +1496,7 @@ func (x *ProtoLogsForStorage) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoLogsForStorage.ProtoReflect.Descriptor instead. func (*ProtoLogsForStorage) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{17} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{18} } func (x *ProtoLogsForStorage) GetLogs() []*ProtoLogForStorage { @@ -1471,7 +1518,7 @@ type ProtoPendingHeader struct { func (x *ProtoPendingHeader) Reset() { *x = ProtoPendingHeader{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[18] + mi := &file_core_types_proto_block_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1484,7 +1531,7 @@ func (x *ProtoPendingHeader) String() string { func (*ProtoPendingHeader) ProtoMessage() {} func (x *ProtoPendingHeader) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[18] + mi := &file_core_types_proto_block_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1497,7 +1544,7 @@ func (x *ProtoPendingHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoPendingHeader.ProtoReflect.Descriptor instead. func (*ProtoPendingHeader) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{18} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{19} } func (x *ProtoPendingHeader) GetWo() *ProtoWorkObject { @@ -1526,7 +1573,7 @@ type ProtoTermini struct { func (x *ProtoTermini) Reset() { *x = ProtoTermini{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[19] + mi := &file_core_types_proto_block_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1539,7 +1586,7 @@ func (x *ProtoTermini) String() string { func (*ProtoTermini) ProtoMessage() {} func (x *ProtoTermini) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[19] + mi := &file_core_types_proto_block_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1552,7 +1599,7 @@ func (x *ProtoTermini) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoTermini.ProtoReflect.Descriptor instead. func (*ProtoTermini) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{19} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{20} } func (x *ProtoTermini) GetDomTermini() []*common.ProtoHash { @@ -1580,7 +1627,7 @@ type ProtoEtxSet struct { func (x *ProtoEtxSet) Reset() { *x = ProtoEtxSet{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[20] + mi := &file_core_types_proto_block_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1593,7 +1640,7 @@ func (x *ProtoEtxSet) String() string { func (*ProtoEtxSet) ProtoMessage() {} func (x *ProtoEtxSet) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[20] + mi := &file_core_types_proto_block_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1606,7 +1653,7 @@ func (x *ProtoEtxSet) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoEtxSet.ProtoReflect.Descriptor instead. func (*ProtoEtxSet) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{20} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{21} } func (x *ProtoEtxSet) GetEtxHashes() []byte { @@ -1628,7 +1675,7 @@ type ProtoPendingEtxs struct { func (x *ProtoPendingEtxs) Reset() { *x = ProtoPendingEtxs{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[21] + mi := &file_core_types_proto_block_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1641,7 +1688,7 @@ func (x *ProtoPendingEtxs) String() string { func (*ProtoPendingEtxs) ProtoMessage() {} func (x *ProtoPendingEtxs) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[21] + mi := &file_core_types_proto_block_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1654,7 +1701,7 @@ func (x *ProtoPendingEtxs) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoPendingEtxs.ProtoReflect.Descriptor instead. func (*ProtoPendingEtxs) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{21} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{22} } func (x *ProtoPendingEtxs) GetHeader() *ProtoWorkObject { @@ -1683,7 +1730,7 @@ type ProtoPendingEtxsRollup struct { func (x *ProtoPendingEtxsRollup) Reset() { *x = ProtoPendingEtxsRollup{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[22] + mi := &file_core_types_proto_block_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1696,7 +1743,7 @@ func (x *ProtoPendingEtxsRollup) String() string { func (*ProtoPendingEtxsRollup) ProtoMessage() {} func (x *ProtoPendingEtxsRollup) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[22] + mi := &file_core_types_proto_block_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1709,7 +1756,7 @@ func (x *ProtoPendingEtxsRollup) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoPendingEtxsRollup.ProtoReflect.Descriptor instead. func (*ProtoPendingEtxsRollup) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{22} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{23} } func (x *ProtoPendingEtxsRollup) GetHeader() *ProtoWorkObject { @@ -1737,7 +1784,7 @@ type ProtoTxIns struct { func (x *ProtoTxIns) Reset() { *x = ProtoTxIns{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[23] + mi := &file_core_types_proto_block_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1750,7 +1797,7 @@ func (x *ProtoTxIns) String() string { func (*ProtoTxIns) ProtoMessage() {} func (x *ProtoTxIns) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[23] + mi := &file_core_types_proto_block_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1763,7 +1810,7 @@ func (x *ProtoTxIns) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoTxIns.ProtoReflect.Descriptor instead. func (*ProtoTxIns) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{23} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{24} } func (x *ProtoTxIns) GetTxIns() []*ProtoTxIn { @@ -1784,7 +1831,7 @@ type ProtoTxOuts struct { func (x *ProtoTxOuts) Reset() { *x = ProtoTxOuts{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[24] + mi := &file_core_types_proto_block_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1797,7 +1844,7 @@ func (x *ProtoTxOuts) String() string { func (*ProtoTxOuts) ProtoMessage() {} func (x *ProtoTxOuts) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[24] + mi := &file_core_types_proto_block_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1810,7 +1857,7 @@ func (x *ProtoTxOuts) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoTxOuts.ProtoReflect.Descriptor instead. func (*ProtoTxOuts) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{24} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{25} } func (x *ProtoTxOuts) GetTxOuts() []*ProtoTxOut { @@ -1832,7 +1879,7 @@ type ProtoTxIn struct { func (x *ProtoTxIn) Reset() { *x = ProtoTxIn{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[25] + mi := &file_core_types_proto_block_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1845,7 +1892,7 @@ func (x *ProtoTxIn) String() string { func (*ProtoTxIn) ProtoMessage() {} func (x *ProtoTxIn) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[25] + mi := &file_core_types_proto_block_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1858,7 +1905,7 @@ func (x *ProtoTxIn) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoTxIn.ProtoReflect.Descriptor instead. func (*ProtoTxIn) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{25} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{26} } func (x *ProtoTxIn) GetPreviousOutPoint() *ProtoOutPoint { @@ -1887,7 +1934,7 @@ type ProtoOutPoint struct { func (x *ProtoOutPoint) Reset() { *x = ProtoOutPoint{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[26] + mi := &file_core_types_proto_block_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1900,7 +1947,7 @@ func (x *ProtoOutPoint) String() string { func (*ProtoOutPoint) ProtoMessage() {} func (x *ProtoOutPoint) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[26] + mi := &file_core_types_proto_block_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1913,7 +1960,7 @@ func (x *ProtoOutPoint) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoOutPoint.ProtoReflect.Descriptor instead. func (*ProtoOutPoint) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{26} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{27} } func (x *ProtoOutPoint) GetHash() *common.ProtoHash { @@ -1943,7 +1990,7 @@ type ProtoTxOut struct { func (x *ProtoTxOut) Reset() { *x = ProtoTxOut{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[27] + mi := &file_core_types_proto_block_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1956,7 +2003,7 @@ func (x *ProtoTxOut) String() string { func (*ProtoTxOut) ProtoMessage() {} func (x *ProtoTxOut) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[27] + mi := &file_core_types_proto_block_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1969,7 +2016,7 @@ func (x *ProtoTxOut) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoTxOut.ProtoReflect.Descriptor instead. func (*ProtoTxOut) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{27} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{28} } func (x *ProtoTxOut) GetDenomination() uint32 { @@ -2006,7 +2053,7 @@ type ProtoOutPointAndDenomination struct { func (x *ProtoOutPointAndDenomination) Reset() { *x = ProtoOutPointAndDenomination{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[28] + mi := &file_core_types_proto_block_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2019,7 +2066,7 @@ func (x *ProtoOutPointAndDenomination) String() string { func (*ProtoOutPointAndDenomination) ProtoMessage() {} func (x *ProtoOutPointAndDenomination) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[28] + mi := &file_core_types_proto_block_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2032,7 +2079,7 @@ func (x *ProtoOutPointAndDenomination) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoOutPointAndDenomination.ProtoReflect.Descriptor instead. func (*ProtoOutPointAndDenomination) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{28} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{29} } func (x *ProtoOutPointAndDenomination) GetHash() *common.ProtoHash { @@ -2067,7 +2114,7 @@ type ProtoAddressOutPoints struct { func (x *ProtoAddressOutPoints) Reset() { *x = ProtoAddressOutPoints{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[29] + mi := &file_core_types_proto_block_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2080,7 +2127,7 @@ func (x *ProtoAddressOutPoints) String() string { func (*ProtoAddressOutPoints) ProtoMessage() {} func (x *ProtoAddressOutPoints) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[29] + mi := &file_core_types_proto_block_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2093,7 +2140,7 @@ func (x *ProtoAddressOutPoints) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoAddressOutPoints.ProtoReflect.Descriptor instead. func (*ProtoAddressOutPoints) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{29} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{30} } func (x *ProtoAddressOutPoints) GetOutPoints() map[string]*ProtoOutPointAndDenomination { @@ -2114,7 +2161,7 @@ type ProtoOutPointsMap struct { func (x *ProtoOutPointsMap) Reset() { *x = ProtoOutPointsMap{} if protoimpl.UnsafeEnabled { - mi := &file_core_types_proto_block_proto_msgTypes[30] + mi := &file_core_types_proto_block_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2127,7 +2174,7 @@ func (x *ProtoOutPointsMap) String() string { func (*ProtoOutPointsMap) ProtoMessage() {} func (x *ProtoOutPointsMap) ProtoReflect() protoreflect.Message { - mi := &file_core_types_proto_block_proto_msgTypes[30] + mi := &file_core_types_proto_block_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2140,7 +2187,7 @@ func (x *ProtoOutPointsMap) ProtoReflect() protoreflect.Message { // Deprecated: Use ProtoOutPointsMap.ProtoReflect.Descriptor instead. func (*ProtoOutPointsMap) Descriptor() ([]byte, []int) { - return file_core_types_proto_block_proto_rawDescGZIP(), []int{30} + return file_core_types_proto_block_proto_rawDescGZIP(), []int{31} } func (x *ProtoOutPointsMap) GetEntries() map[string]*ProtoAddressOutPoints { @@ -2456,165 +2503,172 @@ var file_core_types_proto_block_proto_rawDesc = []byte{ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0e, - 0x0a, 0x0c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x60, - 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x75, 0x70, - 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x0b, - 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x48, 0x61, 0x73, 0x68, 0x52, 0x0a, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, - 0x22, 0xdf, 0x02, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, - 0x74, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x70, - 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x70, 0x6f, 0x73, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x13, - 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, - 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, - 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, - 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3f, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x6c, 0x6f, 0x67, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x73, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x04, 0x65, 0x74, 0x78, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x04, 0x65, 0x74, 0x78, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, - 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, - 0x65, 0x64, 0x22, 0x54, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x65, 0x63, 0x65, 0x69, - 0x70, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, - 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x65, 0x63, - 0x65, 0x69, 0x70, 0x74, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x08, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, - 0x2e, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x29, 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, - 0x73, 0x68, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x44, - 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x73, 0x46, 0x6f, 0x72, 0x53, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x4c, 0x6f, 0x67, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x04, - 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x02, 0x77, - 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, - 0x00, 0x52, 0x02, 0x77, 0x6f, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x07, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x48, 0x01, - 0x52, 0x07, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, - 0x5f, 0x77, 0x6f, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x22, - 0x76, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x12, - 0x32, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0a, 0x64, 0x6f, 0x6d, 0x54, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x69, 0x12, 0x32, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x69, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0a, 0x73, 0x75, 0x62, - 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x22, 0x40, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x45, 0x74, 0x78, 0x53, 0x65, 0x74, 0x12, 0x22, 0x0a, 0x0a, 0x65, 0x74, 0x78, 0x5f, 0x68, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x09, 0x65, 0x74, - 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, - 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x74, 0x78, 0x73, 0x12, 0x33, - 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x04, 0x65, 0x74, 0x78, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0a, 0x0c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x68, + 0x0a, 0x18, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x56, 0x69, 0x65, 0x77, 0x12, 0x3c, 0x0a, 0x0b, 0x77, 0x6f, + 0x72, 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, + 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x60, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0a, + 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x22, 0xdf, 0x02, 0x0a, 0x16, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x46, 0x6f, 0x72, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x11, 0x70, 0x6f, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4f, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x47, + 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, + 0x73, 0x68, 0x12, 0x3f, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4c, + 0x6f, 0x67, 0x73, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x04, 0x6c, + 0x6f, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x04, 0x65, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x01, 0x52, 0x04, 0x65, - 0x74, 0x78, 0x73, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x16, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x74, 0x78, 0x73, 0x52, - 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x12, 0x33, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, - 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x0b, 0x65, 0x74, - 0x78, 0x73, 0x5f, 0x72, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x01, 0x52, 0x0a, 0x65, 0x74, 0x78, - 0x73, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x5f, 0x72, - 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x22, 0x35, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, - 0x49, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x06, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x54, 0x78, 0x49, 0x6e, 0x52, 0x05, 0x74, 0x78, 0x49, 0x6e, 0x73, 0x22, 0x39, 0x0a, 0x0b, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x74, - 0x78, 0x5f, 0x6f, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x52, - 0x06, 0x74, 0x78, 0x4f, 0x75, 0x74, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x54, 0x78, 0x49, 0x6e, 0x12, 0x47, 0x0a, 0x12, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, - 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, - 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, - 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1c, - 0x0a, 0x07, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, - 0x01, 0x52, 0x06, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x15, 0x0a, 0x13, - 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x22, - 0x69, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x12, 0x2a, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x04, 0x65, 0x74, 0x78, + 0x73, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x54, 0x0a, 0x17, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x46, 0x6f, 0x72, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x46, 0x6f, + 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, + 0x74, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x46, + 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x74, 0x6f, 0x70, + 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x74, 0x6f, + 0x70, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x44, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x4c, 0x6f, 0x67, 0x73, 0x46, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, + 0x2d, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4c, 0x6f, 0x67, 0x46, 0x6f, + 0x72, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x88, + 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x02, 0x77, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, + 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x02, 0x77, 0x6f, 0x88, + 0x01, 0x01, 0x12, 0x32, 0x0a, 0x07, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x48, 0x01, 0x52, 0x07, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x69, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x77, 0x6f, 0x42, 0x0a, 0x0a, + 0x08, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x22, 0x76, 0x0a, 0x0c, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, + 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, - 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x01, 0x52, 0x05, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x93, 0x01, 0x0a, 0x0a, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x12, 0x27, 0x0a, 0x0c, 0x64, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x48, - 0x00, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, - 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x48, 0x01, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, - 0x01, 0x12, 0x17, 0x0a, 0x04, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, - 0x02, 0x52, 0x04, 0x6c, 0x6f, 0x63, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x64, - 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, - 0x22, 0xb2, 0x01, 0x0a, 0x1c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x2a, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, - 0x73, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, - 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x01, 0x52, 0x05, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x64, 0x65, 0x6e, 0x6f, - 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x02, - 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, + 0x68, 0x52, 0x0a, 0x64, 0x6f, 0x6d, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x12, 0x32, 0x0a, + 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x69, 0x22, 0x40, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x45, 0x74, 0x78, 0x53, 0x65, 0x74, + 0x12, 0x22, 0x0a, 0x0a, 0x65, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x09, 0x65, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x88, 0x01, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x45, 0x74, 0x78, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, + 0x04, 0x65, 0x74, 0x78, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x01, 0x52, 0x04, 0x65, 0x74, 0x78, 0x73, 0x88, 0x01, 0x01, + 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x07, 0x0a, 0x05, 0x5f, + 0x65, 0x74, 0x78, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x74, 0x78, 0x73, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x12, + 0x33, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, + 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x88, 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x0b, 0x65, 0x74, 0x78, 0x73, 0x5f, 0x72, 0x6f, 0x6c, + 0x6c, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x48, 0x01, 0x52, 0x0a, 0x65, 0x74, 0x78, 0x73, 0x52, 0x6f, 0x6c, 0x6c, 0x75, + 0x70, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, + 0x0e, 0x0a, 0x0c, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x5f, 0x72, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x22, + 0x35, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x49, 0x6e, 0x73, 0x12, 0x27, 0x0a, + 0x06, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x49, 0x6e, 0x52, + 0x05, 0x74, 0x78, 0x49, 0x6e, 0x73, 0x22, 0x39, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, + 0x78, 0x4f, 0x75, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x6f, 0x75, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x52, 0x06, 0x74, 0x78, 0x4f, 0x75, 0x74, + 0x73, 0x22, 0x95, 0x01, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x49, 0x6e, 0x12, + 0x47, 0x0a, 0x12, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x5f, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x01, 0x52, 0x06, 0x70, 0x75, 0x62, + 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, + 0x6f, 0x75, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x0a, 0x0a, + 0x08, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x69, 0x0a, 0x0d, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x48, 0x00, 0x52, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x01, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xc6, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, - 0x4a, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x09, 0x6f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x61, 0x0a, 0x0e, 0x4f, - 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xae, - 0x01, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x4d, 0x61, 0x70, 0x12, 0x3f, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x2e, - 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x58, 0x0a, 0x0c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x75, 0x74, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, - 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, - 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x69, 0x65, - 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x71, 0x75, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x64, 0x65, 0x78, 0x22, 0x93, 0x01, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, + 0x4f, 0x75, 0x74, 0x12, 0x27, 0x0a, 0x0c, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0c, 0x64, 0x65, 0x6e, + 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x01, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x02, 0x52, 0x04, 0x6c, 0x6f, 0x63, + 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0xb2, 0x01, 0x0a, 0x1c, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x44, + 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x48, 0x00, 0x52, 0x04, + 0x68, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x01, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x88, + 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x02, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x6f, + 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x0f, + 0x0a, 0x0d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0xc6, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x6f, 0x75, 0x74, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x2e, 0x4f, 0x75, 0x74, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x61, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, + 0x64, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xae, 0x01, 0x0a, 0x11, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x3f, + 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4f, 0x75, 0x74, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x4d, 0x61, 0x70, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x1a, + 0x58, 0x0a, 0x0c, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, + 0x2d, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x69, 0x65, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x71, + 0x75, 0x61, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2629,7 +2683,7 @@ func file_core_types_proto_block_proto_rawDescGZIP() []byte { return file_core_types_proto_block_proto_rawDescData } -var file_core_types_proto_block_proto_msgTypes = make([]protoimpl.MessageInfo, 33) +var file_core_types_proto_block_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_core_types_proto_block_proto_goTypes = []interface{}{ (*ProtoHeader)(nil), // 0: block.ProtoHeader (*ProtoTransaction)(nil), // 1: block.ProtoTransaction @@ -2644,106 +2698,108 @@ var file_core_types_proto_block_proto_goTypes = []interface{}{ (*ProtoWorkObjects)(nil), // 10: block.ProtoWorkObjects (*ProtoWorkObjectBlockView)(nil), // 11: block.ProtoWorkObjectBlockView (*ProtoWorkObjectHeaderView)(nil), // 12: block.ProtoWorkObjectHeaderView - (*ProtoAccessTuple)(nil), // 13: block.ProtoAccessTuple - (*ProtoReceiptForStorage)(nil), // 14: block.ProtoReceiptForStorage - (*ProtoReceiptsForStorage)(nil), // 15: block.ProtoReceiptsForStorage - (*ProtoLogForStorage)(nil), // 16: block.ProtoLogForStorage - (*ProtoLogsForStorage)(nil), // 17: block.ProtoLogsForStorage - (*ProtoPendingHeader)(nil), // 18: block.ProtoPendingHeader - (*ProtoTermini)(nil), // 19: block.ProtoTermini - (*ProtoEtxSet)(nil), // 20: block.ProtoEtxSet - (*ProtoPendingEtxs)(nil), // 21: block.ProtoPendingEtxs - (*ProtoPendingEtxsRollup)(nil), // 22: block.ProtoPendingEtxsRollup - (*ProtoTxIns)(nil), // 23: block.ProtoTxIns - (*ProtoTxOuts)(nil), // 24: block.ProtoTxOuts - (*ProtoTxIn)(nil), // 25: block.ProtoTxIn - (*ProtoOutPoint)(nil), // 26: block.ProtoOutPoint - (*ProtoTxOut)(nil), // 27: block.ProtoTxOut - (*ProtoOutPointAndDenomination)(nil), // 28: block.ProtoOutPointAndDenomination - (*ProtoAddressOutPoints)(nil), // 29: block.ProtoAddressOutPoints - (*ProtoOutPointsMap)(nil), // 30: block.ProtoOutPointsMap - nil, // 31: block.ProtoAddressOutPoints.OutPointsEntry - nil, // 32: block.ProtoOutPointsMap.EntriesEntry - (*common.ProtoHash)(nil), // 33: common.ProtoHash - (*common.ProtoLocation)(nil), // 34: common.ProtoLocation - (*common.ProtoHashes)(nil), // 35: common.ProtoHashes - (*common.ProtoAddress)(nil), // 36: common.ProtoAddress + (*ProtoWorkObjectShareView)(nil), // 13: block.ProtoWorkObjectShareView + (*ProtoAccessTuple)(nil), // 14: block.ProtoAccessTuple + (*ProtoReceiptForStorage)(nil), // 15: block.ProtoReceiptForStorage + (*ProtoReceiptsForStorage)(nil), // 16: block.ProtoReceiptsForStorage + (*ProtoLogForStorage)(nil), // 17: block.ProtoLogForStorage + (*ProtoLogsForStorage)(nil), // 18: block.ProtoLogsForStorage + (*ProtoPendingHeader)(nil), // 19: block.ProtoPendingHeader + (*ProtoTermini)(nil), // 20: block.ProtoTermini + (*ProtoEtxSet)(nil), // 21: block.ProtoEtxSet + (*ProtoPendingEtxs)(nil), // 22: block.ProtoPendingEtxs + (*ProtoPendingEtxsRollup)(nil), // 23: block.ProtoPendingEtxsRollup + (*ProtoTxIns)(nil), // 24: block.ProtoTxIns + (*ProtoTxOuts)(nil), // 25: block.ProtoTxOuts + (*ProtoTxIn)(nil), // 26: block.ProtoTxIn + (*ProtoOutPoint)(nil), // 27: block.ProtoOutPoint + (*ProtoTxOut)(nil), // 28: block.ProtoTxOut + (*ProtoOutPointAndDenomination)(nil), // 29: block.ProtoOutPointAndDenomination + (*ProtoAddressOutPoints)(nil), // 30: block.ProtoAddressOutPoints + (*ProtoOutPointsMap)(nil), // 31: block.ProtoOutPointsMap + nil, // 32: block.ProtoAddressOutPoints.OutPointsEntry + nil, // 33: block.ProtoOutPointsMap.EntriesEntry + (*common.ProtoHash)(nil), // 34: common.ProtoHash + (*common.ProtoLocation)(nil), // 35: common.ProtoLocation + (*common.ProtoHashes)(nil), // 36: common.ProtoHashes + (*common.ProtoAddress)(nil), // 37: common.ProtoAddress } var file_core_types_proto_block_proto_depIdxs = []int32{ - 33, // 0: block.ProtoHeader.parent_hash:type_name -> common.ProtoHash - 33, // 1: block.ProtoHeader.uncle_hash:type_name -> common.ProtoHash - 33, // 2: block.ProtoHeader.evm_root:type_name -> common.ProtoHash - 33, // 3: block.ProtoHeader.tx_hash:type_name -> common.ProtoHash - 33, // 4: block.ProtoHeader.etx_hash:type_name -> common.ProtoHash - 33, // 5: block.ProtoHeader.etx_rollup_hash:type_name -> common.ProtoHash - 33, // 6: block.ProtoHeader.manifest_hash:type_name -> common.ProtoHash - 33, // 7: block.ProtoHeader.receipt_hash:type_name -> common.ProtoHash - 34, // 8: block.ProtoHeader.location:type_name -> common.ProtoLocation - 33, // 9: block.ProtoHeader.mix_hash:type_name -> common.ProtoHash - 33, // 10: block.ProtoHeader.utxo_root:type_name -> common.ProtoHash - 33, // 11: block.ProtoHeader.etx_set_root:type_name -> common.ProtoHash - 33, // 12: block.ProtoHeader.etx_eligible_slices:type_name -> common.ProtoHash - 33, // 13: block.ProtoHeader.prime_terminus:type_name -> common.ProtoHash - 33, // 14: block.ProtoHeader.interlink_root_hash:type_name -> common.ProtoHash + 34, // 0: block.ProtoHeader.parent_hash:type_name -> common.ProtoHash + 34, // 1: block.ProtoHeader.uncle_hash:type_name -> common.ProtoHash + 34, // 2: block.ProtoHeader.evm_root:type_name -> common.ProtoHash + 34, // 3: block.ProtoHeader.tx_hash:type_name -> common.ProtoHash + 34, // 4: block.ProtoHeader.etx_hash:type_name -> common.ProtoHash + 34, // 5: block.ProtoHeader.etx_rollup_hash:type_name -> common.ProtoHash + 34, // 6: block.ProtoHeader.manifest_hash:type_name -> common.ProtoHash + 34, // 7: block.ProtoHeader.receipt_hash:type_name -> common.ProtoHash + 35, // 8: block.ProtoHeader.location:type_name -> common.ProtoLocation + 34, // 9: block.ProtoHeader.mix_hash:type_name -> common.ProtoHash + 34, // 10: block.ProtoHeader.utxo_root:type_name -> common.ProtoHash + 34, // 11: block.ProtoHeader.etx_set_root:type_name -> common.ProtoHash + 34, // 12: block.ProtoHeader.etx_eligible_slices:type_name -> common.ProtoHash + 34, // 13: block.ProtoHeader.prime_terminus:type_name -> common.ProtoHash + 34, // 14: block.ProtoHeader.interlink_root_hash:type_name -> common.ProtoHash 5, // 15: block.ProtoTransaction.access_list:type_name -> block.ProtoAccessList - 33, // 16: block.ProtoTransaction.originating_tx_hash:type_name -> common.ProtoHash - 23, // 17: block.ProtoTransaction.tx_ins:type_name -> block.ProtoTxIns - 24, // 18: block.ProtoTransaction.tx_outs:type_name -> block.ProtoTxOuts - 33, // 19: block.ProtoTransaction.parent_hash:type_name -> common.ProtoHash - 33, // 20: block.ProtoTransaction.mix_hash:type_name -> common.ProtoHash + 34, // 16: block.ProtoTransaction.originating_tx_hash:type_name -> common.ProtoHash + 24, // 17: block.ProtoTransaction.tx_ins:type_name -> block.ProtoTxIns + 25, // 18: block.ProtoTransaction.tx_outs:type_name -> block.ProtoTxOuts + 34, // 19: block.ProtoTransaction.parent_hash:type_name -> common.ProtoHash + 34, // 20: block.ProtoTransaction.mix_hash:type_name -> common.ProtoHash 1, // 21: block.ProtoTransactions.transactions:type_name -> block.ProtoTransaction 0, // 22: block.ProtoHeaders.headers:type_name -> block.ProtoHeader - 33, // 23: block.ProtoManifest.manifest:type_name -> common.ProtoHash - 13, // 24: block.ProtoAccessList.access_tuples:type_name -> block.ProtoAccessTuple - 33, // 25: block.ProtoWorkObjectHeader.header_hash:type_name -> common.ProtoHash - 33, // 26: block.ProtoWorkObjectHeader.parent_hash:type_name -> common.ProtoHash - 33, // 27: block.ProtoWorkObjectHeader.tx_hash:type_name -> common.ProtoHash - 34, // 28: block.ProtoWorkObjectHeader.location:type_name -> common.ProtoLocation - 33, // 29: block.ProtoWorkObjectHeader.mix_hash:type_name -> common.ProtoHash + 34, // 23: block.ProtoManifest.manifest:type_name -> common.ProtoHash + 14, // 24: block.ProtoAccessList.access_tuples:type_name -> block.ProtoAccessTuple + 34, // 25: block.ProtoWorkObjectHeader.header_hash:type_name -> common.ProtoHash + 34, // 26: block.ProtoWorkObjectHeader.parent_hash:type_name -> common.ProtoHash + 34, // 27: block.ProtoWorkObjectHeader.tx_hash:type_name -> common.ProtoHash + 35, // 28: block.ProtoWorkObjectHeader.location:type_name -> common.ProtoLocation + 34, // 29: block.ProtoWorkObjectHeader.mix_hash:type_name -> common.ProtoHash 6, // 30: block.ProtoWorkObjectHeaders.wo_headers:type_name -> block.ProtoWorkObjectHeader 0, // 31: block.ProtoWorkObjectBody.header:type_name -> block.ProtoHeader 2, // 32: block.ProtoWorkObjectBody.transactions:type_name -> block.ProtoTransactions 7, // 33: block.ProtoWorkObjectBody.uncles:type_name -> block.ProtoWorkObjectHeaders 2, // 34: block.ProtoWorkObjectBody.ext_transactions:type_name -> block.ProtoTransactions 4, // 35: block.ProtoWorkObjectBody.manifest:type_name -> block.ProtoManifest - 35, // 36: block.ProtoWorkObjectBody.interlink_hashes:type_name -> common.ProtoHashes + 36, // 36: block.ProtoWorkObjectBody.interlink_hashes:type_name -> common.ProtoHashes 6, // 37: block.ProtoWorkObject.wo_header:type_name -> block.ProtoWorkObjectHeader 8, // 38: block.ProtoWorkObject.wo_body:type_name -> block.ProtoWorkObjectBody 1, // 39: block.ProtoWorkObject.tx:type_name -> block.ProtoTransaction 9, // 40: block.ProtoWorkObjects.work_objects:type_name -> block.ProtoWorkObject 9, // 41: block.ProtoWorkObjectBlockView.work_object:type_name -> block.ProtoWorkObject 9, // 42: block.ProtoWorkObjectHeaderView.work_object:type_name -> block.ProtoWorkObject - 33, // 43: block.ProtoAccessTuple.storage_key:type_name -> common.ProtoHash - 33, // 44: block.ProtoReceiptForStorage.tx_hash:type_name -> common.ProtoHash - 36, // 45: block.ProtoReceiptForStorage.contract_address:type_name -> common.ProtoAddress - 17, // 46: block.ProtoReceiptForStorage.logs:type_name -> block.ProtoLogsForStorage - 2, // 47: block.ProtoReceiptForStorage.etxs:type_name -> block.ProtoTransactions - 14, // 48: block.ProtoReceiptsForStorage.receipts:type_name -> block.ProtoReceiptForStorage - 36, // 49: block.ProtoLogForStorage.address:type_name -> common.ProtoAddress - 33, // 50: block.ProtoLogForStorage.topics:type_name -> common.ProtoHash - 16, // 51: block.ProtoLogsForStorage.logs:type_name -> block.ProtoLogForStorage - 9, // 52: block.ProtoPendingHeader.wo:type_name -> block.ProtoWorkObject - 19, // 53: block.ProtoPendingHeader.termini:type_name -> block.ProtoTermini - 33, // 54: block.ProtoTermini.dom_termini:type_name -> common.ProtoHash - 33, // 55: block.ProtoTermini.sub_termini:type_name -> common.ProtoHash - 9, // 56: block.ProtoPendingEtxs.header:type_name -> block.ProtoWorkObject - 2, // 57: block.ProtoPendingEtxs.etxs:type_name -> block.ProtoTransactions - 9, // 58: block.ProtoPendingEtxsRollup.header:type_name -> block.ProtoWorkObject - 2, // 59: block.ProtoPendingEtxsRollup.etxs_rollup:type_name -> block.ProtoTransactions - 25, // 60: block.ProtoTxIns.tx_ins:type_name -> block.ProtoTxIn - 27, // 61: block.ProtoTxOuts.tx_outs:type_name -> block.ProtoTxOut - 26, // 62: block.ProtoTxIn.previous_out_point:type_name -> block.ProtoOutPoint - 33, // 63: block.ProtoOutPoint.hash:type_name -> common.ProtoHash - 33, // 64: block.ProtoOutPointAndDenomination.hash:type_name -> common.ProtoHash - 31, // 65: block.ProtoAddressOutPoints.out_points:type_name -> block.ProtoAddressOutPoints.OutPointsEntry - 32, // 66: block.ProtoOutPointsMap.entries:type_name -> block.ProtoOutPointsMap.EntriesEntry - 28, // 67: block.ProtoAddressOutPoints.OutPointsEntry.value:type_name -> block.ProtoOutPointAndDenomination - 29, // 68: block.ProtoOutPointsMap.EntriesEntry.value:type_name -> block.ProtoAddressOutPoints - 69, // [69:69] is the sub-list for method output_type - 69, // [69:69] is the sub-list for method input_type - 69, // [69:69] is the sub-list for extension type_name - 69, // [69:69] is the sub-list for extension extendee - 0, // [0:69] is the sub-list for field type_name + 9, // 43: block.ProtoWorkObjectShareView.work_object:type_name -> block.ProtoWorkObject + 34, // 44: block.ProtoAccessTuple.storage_key:type_name -> common.ProtoHash + 34, // 45: block.ProtoReceiptForStorage.tx_hash:type_name -> common.ProtoHash + 37, // 46: block.ProtoReceiptForStorage.contract_address:type_name -> common.ProtoAddress + 18, // 47: block.ProtoReceiptForStorage.logs:type_name -> block.ProtoLogsForStorage + 2, // 48: block.ProtoReceiptForStorage.etxs:type_name -> block.ProtoTransactions + 15, // 49: block.ProtoReceiptsForStorage.receipts:type_name -> block.ProtoReceiptForStorage + 37, // 50: block.ProtoLogForStorage.address:type_name -> common.ProtoAddress + 34, // 51: block.ProtoLogForStorage.topics:type_name -> common.ProtoHash + 17, // 52: block.ProtoLogsForStorage.logs:type_name -> block.ProtoLogForStorage + 9, // 53: block.ProtoPendingHeader.wo:type_name -> block.ProtoWorkObject + 20, // 54: block.ProtoPendingHeader.termini:type_name -> block.ProtoTermini + 34, // 55: block.ProtoTermini.dom_termini:type_name -> common.ProtoHash + 34, // 56: block.ProtoTermini.sub_termini:type_name -> common.ProtoHash + 9, // 57: block.ProtoPendingEtxs.header:type_name -> block.ProtoWorkObject + 2, // 58: block.ProtoPendingEtxs.etxs:type_name -> block.ProtoTransactions + 9, // 59: block.ProtoPendingEtxsRollup.header:type_name -> block.ProtoWorkObject + 2, // 60: block.ProtoPendingEtxsRollup.etxs_rollup:type_name -> block.ProtoTransactions + 26, // 61: block.ProtoTxIns.tx_ins:type_name -> block.ProtoTxIn + 28, // 62: block.ProtoTxOuts.tx_outs:type_name -> block.ProtoTxOut + 27, // 63: block.ProtoTxIn.previous_out_point:type_name -> block.ProtoOutPoint + 34, // 64: block.ProtoOutPoint.hash:type_name -> common.ProtoHash + 34, // 65: block.ProtoOutPointAndDenomination.hash:type_name -> common.ProtoHash + 32, // 66: block.ProtoAddressOutPoints.out_points:type_name -> block.ProtoAddressOutPoints.OutPointsEntry + 33, // 67: block.ProtoOutPointsMap.entries:type_name -> block.ProtoOutPointsMap.EntriesEntry + 29, // 68: block.ProtoAddressOutPoints.OutPointsEntry.value:type_name -> block.ProtoOutPointAndDenomination + 30, // 69: block.ProtoOutPointsMap.EntriesEntry.value:type_name -> block.ProtoAddressOutPoints + 70, // [70:70] is the sub-list for method output_type + 70, // [70:70] is the sub-list for method input_type + 70, // [70:70] is the sub-list for extension type_name + 70, // [70:70] is the sub-list for extension extendee + 0, // [0:70] is the sub-list for field type_name } func init() { file_core_types_proto_block_proto_init() } @@ -2909,7 +2965,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoAccessTuple); i { + switch v := v.(*ProtoWorkObjectShareView); i { case 0: return &v.state case 1: @@ -2921,7 +2977,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoReceiptForStorage); i { + switch v := v.(*ProtoAccessTuple); i { case 0: return &v.state case 1: @@ -2933,7 +2989,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoReceiptsForStorage); i { + switch v := v.(*ProtoReceiptForStorage); i { case 0: return &v.state case 1: @@ -2945,7 +3001,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoLogForStorage); i { + switch v := v.(*ProtoReceiptsForStorage); i { case 0: return &v.state case 1: @@ -2957,7 +3013,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoLogsForStorage); i { + switch v := v.(*ProtoLogForStorage); i { case 0: return &v.state case 1: @@ -2969,7 +3025,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoPendingHeader); i { + switch v := v.(*ProtoLogsForStorage); i { case 0: return &v.state case 1: @@ -2981,7 +3037,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoTermini); i { + switch v := v.(*ProtoPendingHeader); i { case 0: return &v.state case 1: @@ -2993,7 +3049,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoEtxSet); i { + switch v := v.(*ProtoTermini); i { case 0: return &v.state case 1: @@ -3005,7 +3061,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoPendingEtxs); i { + switch v := v.(*ProtoEtxSet); i { case 0: return &v.state case 1: @@ -3017,7 +3073,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoPendingEtxsRollup); i { + switch v := v.(*ProtoPendingEtxs); i { case 0: return &v.state case 1: @@ -3029,7 +3085,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoTxIns); i { + switch v := v.(*ProtoPendingEtxsRollup); i { case 0: return &v.state case 1: @@ -3041,7 +3097,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoTxOuts); i { + switch v := v.(*ProtoTxIns); i { case 0: return &v.state case 1: @@ -3053,7 +3109,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoTxIn); i { + switch v := v.(*ProtoTxOuts); i { case 0: return &v.state case 1: @@ -3065,7 +3121,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoOutPoint); i { + switch v := v.(*ProtoTxIn); i { case 0: return &v.state case 1: @@ -3077,7 +3133,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoTxOut); i { + switch v := v.(*ProtoOutPoint); i { case 0: return &v.state case 1: @@ -3089,7 +3145,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoOutPointAndDenomination); i { + switch v := v.(*ProtoTxOut); i { case 0: return &v.state case 1: @@ -3101,7 +3157,7 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoAddressOutPoints); i { + switch v := v.(*ProtoOutPointAndDenomination); i { case 0: return &v.state case 1: @@ -3113,6 +3169,18 @@ func file_core_types_proto_block_proto_init() { } } file_core_types_proto_block_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProtoAddressOutPoints); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_types_proto_block_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProtoOutPointsMap); i { case 0: return &v.state @@ -3132,21 +3200,22 @@ func file_core_types_proto_block_proto_init() { file_core_types_proto_block_proto_msgTypes[9].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[11].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[12].OneofWrappers = []interface{}{} - file_core_types_proto_block_proto_msgTypes[18].OneofWrappers = []interface{}{} - file_core_types_proto_block_proto_msgTypes[20].OneofWrappers = []interface{}{} + file_core_types_proto_block_proto_msgTypes[13].OneofWrappers = []interface{}{} + file_core_types_proto_block_proto_msgTypes[19].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[21].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[22].OneofWrappers = []interface{}{} - file_core_types_proto_block_proto_msgTypes[25].OneofWrappers = []interface{}{} + file_core_types_proto_block_proto_msgTypes[23].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[26].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[27].OneofWrappers = []interface{}{} file_core_types_proto_block_proto_msgTypes[28].OneofWrappers = []interface{}{} + file_core_types_proto_block_proto_msgTypes[29].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_core_types_proto_block_proto_rawDesc, NumEnums: 0, - NumMessages: 33, + NumMessages: 34, NumExtensions: 0, NumServices: 0, }, diff --git a/core/types/proto_block.proto b/core/types/proto_block.proto index ee8c50707f..9532c47c7f 100644 --- a/core/types/proto_block.proto +++ b/core/types/proto_block.proto @@ -112,6 +112,10 @@ message ProtoWorkObjectHeaderView { optional ProtoWorkObject work_object = 1; } +message ProtoWorkObjectShareView { + optional ProtoWorkObject work_object = 1; +} + message ProtoAccessTuple { bytes address = 1; repeated common.ProtoHash storage_key = 2; @@ -193,4 +197,4 @@ message ProtoAddressOutPoints { message ProtoOutPointsMap { map entries = 1; -} \ No newline at end of file +} diff --git a/core/types/wo.go b/core/types/wo.go index 61f4efb4a8..151dd99bf6 100644 --- a/core/types/wo.go +++ b/core/types/wo.go @@ -62,6 +62,7 @@ const ( HeaderObject PhObject WorkShareObject + WorkShareTxObject ) func (wo *WorkObject) Hash() common.Hash { @@ -743,7 +744,7 @@ func (wo *WorkObject) ProtoEncode(woType WorkObjectView) (*ProtoWorkObject, erro if err != nil { return nil, err } - body, err := wo.woBody.ProtoEncode() + body, err := wo.woBody.ProtoEncode(woType) if err != nil { return nil, err } @@ -786,6 +787,16 @@ func (wo *WorkObjectBlockView) ProtoEncode() (*ProtoWorkObjectBlockView, error) }, nil } +func (wo *WorkObjectShareView) ProtoEncode() (*ProtoWorkObjectShareView, error) { + protoWo, err := wo.WorkObject.ProtoEncode(WorkShareTxObject) + if err != nil { + return nil, err + } + return &ProtoWorkObjectShareView{ + WorkObject: protoWo, + }, nil +} + func (wo *WorkObjectHeaderView) ProtoDecode(data *ProtoWorkObjectHeaderView, location common.Location) error { decodeWo := new(WorkObject) err := decodeWo.ProtoDecode(data.GetWorkObject(), location, HeaderObject) @@ -806,6 +817,16 @@ func (wob *WorkObjectBlockView) ProtoDecode(data *ProtoWorkObjectBlockView, loca return nil } +func (wos *WorkObjectShareView) ProtoDecode(data *ProtoWorkObjectShareView, location common.Location) error { + decodeWo := new(WorkObject) + err := decodeWo.ProtoDecode(data.GetWorkObject(), location, WorkShareTxObject) + if err != nil { + return err + } + wos.WorkObject = decodeWo + return nil +} + func (wo *WorkObject) ProtoDecode(data *ProtoWorkObject, location common.Location, woType WorkObjectView) error { switch woType { case PEtxObject: @@ -825,7 +846,7 @@ func (wo *WorkObject) ProtoDecode(data *ProtoWorkObject, location common.Locatio return err } wo.woBody = new(WorkObjectBody) - err = wo.woBody.ProtoDecode(data.GetWoBody(), location, BlockObject) + err = wo.woBody.ProtoDecode(data.GetWoBody(), location, woType) if err != nil { return err } @@ -983,49 +1004,68 @@ func CopyWorkObjectBody(wb *WorkObjectBody) *WorkObjectBody { return cpy } -func (wb *WorkObjectBody) ProtoEncode() (*ProtoWorkObjectBody, error) { - header, err := wb.header.ProtoEncode() - if err != nil { - return nil, err - } +func (wb *WorkObjectBody) ProtoEncode(woType WorkObjectView) (*ProtoWorkObjectBody, error) { + switch woType { + case WorkShareTxObject: + header, err := wb.header.ProtoEncode() + if err != nil { + return nil, err + } + // Only encode the txs field in the body + protoTransactions, err := wb.transactions.ProtoEncode() + if err != nil { + return nil, err + } + return &ProtoWorkObjectBody{ + Header: header, + Transactions: protoTransactions, + }, nil - protoTransactions, err := wb.transactions.ProtoEncode() - if err != nil { - return nil, err - } + default: + header, err := wb.header.ProtoEncode() + if err != nil { + return nil, err + } - protoExtTransactions, err := wb.extTransactions.ProtoEncode() - if err != nil { - return nil, err - } + protoTransactions, err := wb.transactions.ProtoEncode() + if err != nil { + return nil, err + } - protoUncles := &ProtoWorkObjectHeaders{} - for _, unc := range wb.uncles { - protoUncle, err := unc.ProtoEncode() + protoExtTransactions, err := wb.extTransactions.ProtoEncode() if err != nil { return nil, err } - protoUncles.WoHeaders = append(protoUncles.WoHeaders, protoUncle) - } - protoManifest, err := wb.manifest.ProtoEncode() - if err != nil { - return nil, err - } + protoUncles := &ProtoWorkObjectHeaders{} + for _, unc := range wb.uncles { + protoUncle, err := unc.ProtoEncode() + if err != nil { + return nil, err + } + protoUncles.WoHeaders = append(protoUncles.WoHeaders, protoUncle) + } - protoInterlinkHashes := wb.interlinkHashes.ProtoEncode() + protoManifest, err := wb.manifest.ProtoEncode() + if err != nil { + return nil, err + } - return &ProtoWorkObjectBody{ - Header: header, - Transactions: protoTransactions, - ExtTransactions: protoExtTransactions, - Uncles: protoUncles, - Manifest: protoManifest, - InterlinkHashes: protoInterlinkHashes, - }, nil + protoInterlinkHashes := wb.interlinkHashes.ProtoEncode() + + return &ProtoWorkObjectBody{ + Header: header, + Transactions: protoTransactions, + ExtTransactions: protoExtTransactions, + Uncles: protoUncles, + Manifest: protoManifest, + InterlinkHashes: protoInterlinkHashes, + }, nil + } } func (wb *WorkObjectBody) ProtoDecode(data *ProtoWorkObjectBody, location common.Location, woType WorkObjectView) error { + var err error switch woType { case WorkShareObject: wb.header = &Header{} @@ -1042,7 +1082,7 @@ func (wb *WorkObjectBody) ProtoDecode(data *ProtoWorkObjectBody, location common } wb.uncles[i] = uncle } - default: + case WorkShareTxObject: wb.header = &Header{} err := wb.header.ProtoDecode(data.GetHeader(), location) if err != nil { @@ -1053,6 +1093,20 @@ func (wb *WorkObjectBody) ProtoDecode(data *ProtoWorkObjectBody, location common if err != nil { return err } + default: + // Only decode the header if its specified + if data.Header != nil { + wb.header = &Header{} + err := wb.header.ProtoDecode(data.GetHeader(), location) + if err != nil { + return err + } + } + wb.transactions = Transactions{} + err = wb.transactions.ProtoDecode(data.GetTransactions(), location) + if err != nil { + return err + } wb.extTransactions = Transactions{} err = wb.extTransactions.ProtoDecode(data.GetExtTransactions(), location) if err != nil { @@ -1114,6 +1168,10 @@ type WorkObjectHeaderView struct { *WorkObject } +type WorkObjectShareView struct { + *WorkObject +} + //////////////////////////////////////////////////////////// ////////////// View Conversion/Getter Methods ////////////// //////////////////////////////////////////////////////////// @@ -1137,3 +1195,9 @@ func (wo *WorkObject) ConvertToBlockView() *WorkObjectBlockView { func (wo *WorkObject) ConvertToPEtxView() *WorkObject { return wo.WithBody(wo.Header(), nil, nil, nil, nil, nil) } + +func (wo *WorkObject) ConvertToWorkObjectShareView(txs Transactions) *WorkObjectShareView { + return &WorkObjectShareView{ + WorkObject: wo.WithBody(wo.Header(), txs, nil, nil, nil, nil), + } +} diff --git a/core/worker.go b/core/worker.go index a38b6caad8..844e63b6cf 100644 --- a/core/worker.go +++ b/core/worker.go @@ -49,7 +49,7 @@ const ( staleThreshold = 7 // pendingBlockBodyLimit is maximum number of pending block bodies to be kept in cache. - pendingBlockBodyLimit = 16 + pendingBlockBodyLimit = 100 // c_headerPrintsExpiryTime is how long a header hash is kept in the cache, so that currentInfo // is not printed on a Proc frequency @@ -586,6 +586,7 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool) (*typ } work.txs[0] = coinbaseTx } + } // Create a local environment copy, avoid the data race with snapshot state. @@ -1190,12 +1191,22 @@ func (w *worker) prepareWork(genParams *generateParams, wo *types.WorkObject) (* newWo.Header().SetCoinbase(w.coinbase) } + // Get the latest transactions to be broadcasted from the pool + w.txPool.broadcastSetMu.RLock() + if len(w.txPool.broadcastSet) > 0 { + txs := w.txPool.broadcastSet + hash := types.DeriveSha(txs, trie.NewStackTrie(nil)) + newWo.WorkObjectHeader().SetTxHash(hash) + w.txPool.broadcastSetCache.Add(hash, txs) + } + w.txPool.broadcastSetMu.RUnlock() + // Run the consensus preparation with the default or customized consensus engine. if err := w.engine.Prepare(w.hc, newWo, wo); err != nil { w.logger.WithField("err", err).Error("Failed to prepare header for sealing") return nil, err } - proposedWoHeader := types.NewWorkObjectHeader(newWo.Hash(), newWo.ParentHash(nodeCtx), newWo.Number(nodeCtx), newWo.Difficulty(), types.EmptyRootHash, newWo.Nonce(), newWo.Time(), newWo.Location()) + proposedWoHeader := types.NewWorkObjectHeader(newWo.Hash(), newWo.ParentHash(nodeCtx), newWo.Number(nodeCtx), newWo.Difficulty(), newWo.TxHash(), newWo.Nonce(), newWo.Time(), newWo.Location()) proposedWoBody, err := types.NewWorkObjectBody(newWo.Header(), nil, nil, nil, nil, nil, nil, nodeCtx) if err != nil { return nil, err @@ -1397,7 +1408,7 @@ func (w *worker) AddPendingWorkObjectBody(wo *types.WorkObject) { } // GetPendingBlockBody gets the block body associated with the given header. -func (w *worker) GetPendingBlockBody(woHeader *types.WorkObject) (*types.WorkObject, error) { +func (w *worker) GetPendingBlockBody(woHeader *types.WorkObjectHeader) (*types.WorkObject, error) { body, ok := w.pendingBlockBody.Get(woHeader.SealHash()) if ok { return &body, nil @@ -1431,10 +1442,6 @@ func totalFees(block *types.WorkObject, receipts []*types.Receipt) *big.Float { } func (w *worker) AddWorkShare(workShare *types.WorkObjectHeader) error { - if !w.engine.CheckIfValidWorkShare(workShare) { - return errors.New("workshare is not valid") - } - // Don't add the workshare into the list if its farther than the worksharefilterdist if workShare.NumberU64()+uint64(params.WorkSharesInclusionDepth) < w.hc.CurrentHeader().NumberU64(common.ZONE_CTX) { return nil diff --git a/internal/quaiapi/backend.go b/internal/quaiapi/backend.go index d53cca1bee..0596842c81 100644 --- a/internal/quaiapi/backend.go +++ b/internal/quaiapi/backend.go @@ -85,6 +85,8 @@ type Backend interface { RequestDomToAppendOrFetch(hash common.Hash, entropy *big.Int, order int) NewGenesisPendingHeader(pendingHeader *types.WorkObject, domTerminus common.Hash, hash common.Hash) error GetPendingHeader() (*types.WorkObject, error) + GetPendingBlockBody(workShare *types.WorkObjectHeader) *types.WorkObject + GetTxsFromBroadcastSet(hash common.Hash) (types.Transactions, error) GetManifest(blockHash common.Hash) (types.BlockManifest, error) GetSubManifest(slice common.Location, blockHash common.Hash) (types.BlockManifest, error) AddPendingEtxs(pEtxs types.PendingEtxs) error @@ -102,6 +104,7 @@ type Backend interface { SendWorkShare(workShare *types.WorkObjectHeader) error CheckIfValidWorkShare(workShare *types.WorkObjectHeader) bool SetDomInterface(domInterface core.CoreBackend) + BroadcastWorkShare(workShare *types.WorkObjectShareView, location common.Location) error // Transaction pool API SendTx(ctx context.Context, signedTx *types.Transaction) error @@ -113,7 +116,6 @@ type Backend interface { Stats() (pending int, queued int) TxPoolContent() (map[common.InternalAddress]types.Transactions, map[common.InternalAddress]types.Transactions) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) - SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription // Filter API BloomStatus() (uint64, uint64) @@ -133,7 +135,6 @@ type Backend interface { // P2P apis BroadcastBlock(block *types.WorkObject, location common.Location) error BroadcastHeader(header *types.WorkObject, location common.Location) error - BroadcastWorkShare(workShare *types.WorkObjectHeader, location common.Location) error } func GetAPIs(apiBackend Backend) []rpc.API { diff --git a/internal/quaiapi/quai_api.go b/internal/quaiapi/quai_api.go index d68031c43e..ef32cb963f 100644 --- a/internal/quaiapi/quai_api.go +++ b/internal/quaiapi/quai_api.go @@ -753,11 +753,26 @@ func (s *PublicBlockChainQuaiAPI) ReceiveWorkShare(ctx context.Context, raw json } s.b.Logger().WithField("number", workShare.NumberU64()).Info("Received Work Share") - err := s.b.BroadcastWorkShare(workShare, s.b.NodeLocation()) + pendingBlockBody := s.b.GetPendingBlockBody(workShare) + txs, err := s.b.GetTxsFromBroadcastSet(workShare.TxHash()) if err != nil { - log.Global.WithField("err", err).Error("Error broadcasting work share") - return err + txs = types.Transactions{} + s.b.Logger().Warn("Failed to get txs from the broadcastSetCache", "err", err) + } + if pendingBlockBody == nil { + s.b.Logger().Warn("Could not get the pending Block body", "err", err) + return nil + } + wo := types.NewWorkObject(workShare, pendingBlockBody.Body(), nil) + err = s.b.BroadcastWorkShare(wo.ConvertToWorkObjectShareView(txs), s.b.NodeLocation()) + if err != nil { + s.b.Logger().WithField("err", err).Error("Error broadcasting work share") + } + powHash, err := s.b.Engine().ComputePowHash(workShare) + if err != nil { + s.b.Logger().Error("Error computing the powhash of the workshare") } + s.b.Logger().WithFields(log.Fields{"powHash": powHash, "tx count": len(txs)}).Info("Broadcasted workshares with txs") } return nil } diff --git a/p2p/node/api.go b/p2p/node/api.go index 037aa0541b..7ef719d2cc 100644 --- a/p2p/node/api.go +++ b/p2p/node/api.go @@ -333,7 +333,7 @@ func (p *P2PNode) GetTrieNode(hash common.Hash, location common.Location) *trie. return p.consensus.GetTrieNode(hash, location) } -func (p *P2PNode) handleBroadcast(sourcePeer peer.ID, topic string, data interface{}, nodeLocation common.Location) { +func (p *P2PNode) handleBroadcast(sourcePeer peer.ID, Id string, topic string, data interface{}, nodeLocation common.Location) { if _, ok := acceptableTypes[reflect.TypeOf(data)]; !ok { log.Global.WithFields(log.Fields{ "peer": sourcePeer, @@ -344,8 +344,6 @@ func (p *P2PNode) handleBroadcast(sourcePeer peer.ID, topic string, data interfa } switch v := data.(type) { - case types.WorkObjectHeader: - p.cacheAdd(v.Hash(), &v, nodeLocation) case types.WorkObjectHeaderView: p.cacheAdd(v.Hash(), &v, nodeLocation) case types.WorkObjectBlockView: @@ -354,6 +352,6 @@ func (p *P2PNode) handleBroadcast(sourcePeer peer.ID, topic string, data interfa // If we made it here, pass the data on to the consensus backend if p.consensus != nil { - p.consensus.OnNewBroadcast(sourcePeer, topic, data, nodeLocation) + p.consensus.OnNewBroadcast(sourcePeer, Id, topic, data, nodeLocation) } } diff --git a/p2p/node/node.go b/p2p/node/node.go index 380aae0489..1c4a06cb70 100644 --- a/p2p/node/node.go +++ b/p2p/node/node.go @@ -238,10 +238,9 @@ func (p *P2PNode) Close() error { // acceptableTypes is used to filter out unsupported broadcast types var acceptableTypes = map[reflect.Type]struct{}{ - reflect.TypeOf(types.WorkObjectHeader{}): {}, + reflect.TypeOf(types.WorkObjectShareView{}): {}, reflect.TypeOf(types.WorkObjectBlockView{}): {}, reflect.TypeOf(types.WorkObjectHeaderView{}): {}, - reflect.TypeOf(types.Transactions{}): {}, } func initializeCaches(locations []common.Location) map[string]map[reflect.Type]*lru.Cache[common.Hash, interface{}] { diff --git a/p2p/node/peerManager/peerManager.go b/p2p/node/peerManager/peerManager.go index e94788ab8d..2c547f1c8c 100644 --- a/p2p/node/peerManager/peerManager.go +++ b/p2p/node/peerManager/peerManager.go @@ -250,9 +250,8 @@ func loadPeerDBs() (map[string][]*peerdb.PeerDB, error) { var dataTypes = []interface{}{ &types.WorkObjectHeaderView{}, &types.WorkObjectBlockView{}, + &types.WorkObjectShareView{}, common.Hash{}, - &types.Transactions{}, - &types.WorkObjectHeader{}, } generateLocations := func() []common.Location { diff --git a/p2p/node/pubsubManager/gossipsub.go b/p2p/node/pubsubManager/gossipsub.go index c10662989f..732be9a7e0 100644 --- a/p2p/node/pubsubManager/gossipsub.go +++ b/p2p/node/pubsubManager/gossipsub.go @@ -34,7 +34,7 @@ type PubsubManager struct { genesis common.Hash // Callback function to handle received data - onReceived func(peer.ID, string, interface{}, common.Location) + onReceived func(peer.ID, string, string, interface{}, common.Location) } // creates a new gossipsub instance @@ -71,7 +71,7 @@ func (g *PubsubManager) SetQuaiBackend(consensus quai.ConsensusAPI) { } -func (g *PubsubManager) SetReceiveHandler(receiveCb func(peer.ID, string, interface{}, common.Location)) { +func (g *PubsubManager) SetReceiveHandler(receiveCb func(peer.ID, string, string, interface{}, common.Location)) { g.onReceived = receiveCb } @@ -156,7 +156,7 @@ func (g *PubsubManager) Subscribe(location common.Location, datatype interface{} // handle the received data if g.onReceived != nil { - g.onReceived(msg.ReceivedFrom, *msg.Topic, data, location) + g.onReceived(msg.ReceivedFrom, msg.ID, *msg.Topic, data, location) } } } diff --git a/p2p/node/pubsubManager/utils.go b/p2p/node/pubsubManager/utils.go index fd6336648b..e422f66660 100644 --- a/p2p/node/pubsubManager/utils.go +++ b/p2p/node/pubsubManager/utils.go @@ -19,7 +19,7 @@ const ( C_workObjectType = "blocks" C_transactionType = "transactions" C_headerType = "headers" - C_workObjectHeaderType = "woHeaders" + C_workObjectShareType = "workshare" C_workObjectRequestDegree = 3 C_workObjectHeaderTypeRequestDegree = 3 C_defaultRequestDegree = 3 @@ -46,10 +46,8 @@ func (t *Topic) buildTopicString() string { return strings.Join([]string{baseTopic, C_headerType}, "/") case *types.WorkObjectBlockView: return strings.Join([]string{baseTopic, C_workObjectType}, "/") - case *types.Transactions: - return strings.Join([]string{baseTopic, C_transactionType}, "/") - case *types.WorkObjectHeader: - return strings.Join([]string{baseTopic, C_workObjectHeaderType}, "/") + case *types.WorkObjectShareView: + return strings.Join([]string{baseTopic, C_workObjectShareType}, "/") default: panic(ErrUnsupportedType) } @@ -75,7 +73,7 @@ func (t *Topic) GetRequestDegree() int { func NewTopic(genesis common.Hash, location common.Location, data interface{}) (*Topic, error) { var requestDegree int switch data.(type) { - case *types.WorkObjectHeader, common.Hash, *types.Transactions: + case *types.WorkObjectShareView, common.Hash: requestDegree = C_defaultRequestDegree case *types.WorkObjectHeaderView: requestDegree = C_workObjectHeaderTypeRequestDegree @@ -136,10 +134,8 @@ func TopicFromString(topic string) (*Topic, error) { return NewTopic(genHash, location, &types.WorkObjectHeaderView{}) case C_workObjectType: return NewTopic(genHash, location, &types.WorkObjectBlockView{}) - case C_transactionType: - return NewTopic(genHash, location, &types.Transactions{}) - case C_workObjectHeaderType: - return NewTopic(genHash, location, &types.WorkObjectHeader{}) + case C_workObjectShareType: + return NewTopic(genHash, location, &types.WorkObjectShareView{}) default: return nil, ErrUnsupportedType } diff --git a/p2p/pb/proto_services.go b/p2p/pb/proto_services.go index 06a6368aae..39ea2323a4 100644 --- a/p2p/pb/proto_services.go +++ b/p2p/pb/proto_services.go @@ -8,7 +8,6 @@ import ( "github.com/dominant-strategies/go-quai/common" "github.com/dominant-strategies/go-quai/core/types" - "github.com/dominant-strategies/go-quai/log" ) func DecodeQuaiMessage(data []byte) (*QuaiMessage, error) { @@ -196,45 +195,24 @@ func DecodeQuaiResponse(respMsg *QuaiResponseMessage) (uint32, interface{}, erro // Converts a custom go type to a proto type and marhsals it into a protobuf message func ConvertAndMarshal(data interface{}) ([]byte, error) { switch data := data.(type) { - case *types.WorkObjectHeaderView, *types.WorkObjectBlockView: - switch data := data.(type) { - case *types.WorkObjectHeaderView: - protoBlock, err := data.ProtoEncode() - if err != nil { - return nil, err - } - return proto.Marshal(protoBlock) - case *types.WorkObjectBlockView: - protoBlock, err := data.ProtoEncode() - if err != nil { - return nil, err - } - return proto.Marshal(protoBlock) - default: - return nil, errors.New("unsupported data type") - } - case *types.Transaction: - protoTransaction, err := data.ProtoEncode() + case *types.WorkObjectHeaderView: + protoBlock, err := data.ProtoEncode() if err != nil { return nil, err } - return proto.Marshal(protoTransaction) - case common.Hash: - protoHash := data.ProtoEncode() - return proto.Marshal(protoHash) - case *types.Transactions: - protoTransactions, err := data.ProtoEncode() + return proto.Marshal(protoBlock) + case *types.WorkObjectBlockView: + protoBlock, err := data.ProtoEncode() if err != nil { return nil, err } - return proto.Marshal(protoTransactions) - case *types.WorkObjectHeader: - log.Global.Tracef("marshalling block header: %+v", data) - protoWoHeader, err := data.ProtoEncode() + return proto.Marshal(protoBlock) + case *types.WorkObjectShareView: + protoBlock, err := data.ProtoEncode() if err != nil { return nil, err } - return proto.Marshal(protoWoHeader) + return proto.Marshal(protoBlock) default: return nil, errors.New("unsupported data type") } @@ -272,54 +250,19 @@ func UnmarshalAndConvert(data []byte, sourceLocation common.Location, dataPtr *i } *dataPtr = workObjectHeaderView return nil - case *types.WorkObjectHeader: - protoWorkObjectHeader := &types.ProtoWorkObjectHeader{} - err := proto.Unmarshal(data, protoWorkObjectHeader) - if err != nil { - return err - } - workObjectHeader := types.WorkObjectHeader{} - err = workObjectHeader.ProtoDecode(protoWorkObjectHeader) - if err != nil { - return err - } - *dataPtr = workObjectHeader - return nil - case *types.Header: - protoHeader := &types.ProtoHeader{} - err := proto.Unmarshal(data, protoHeader) - if err != nil { - return err - } - header := types.Header{} - err = header.ProtoDecode(protoHeader, sourceLocation) - if err != nil { - return err - } - *dataPtr = header - return nil - case *types.Transactions: - protoTransactions := &types.ProtoTransactions{} - err := proto.Unmarshal(data, protoTransactions) + case *types.WorkObjectShareView: + protoWorkObject := &types.ProtoWorkObjectShareView{} + err := proto.Unmarshal(data, protoWorkObject) if err != nil { return err } - transactions := types.Transactions{} - err = transactions.ProtoDecode(protoTransactions, sourceLocation) + workObjectShareView := types.WorkObjectShareView{} + workObjectShareView.WorkObject = &types.WorkObject{} + err = workObjectShareView.ProtoDecode(protoWorkObject, sourceLocation) if err != nil { return err } - *dataPtr = transactions - return nil - case common.Hash: - protoHash := &common.ProtoHash{} - err := proto.Unmarshal(data, protoHash) - if err != nil { - return err - } - hash := common.Hash{} - hash.ProtoDecode(protoHash) - *dataPtr = hash + *dataPtr = workObjectShareView return nil default: return errors.New("unsupported data type") diff --git a/params/protocol_params.go b/params/protocol_params.go index e82430a156..49081209b2 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -199,7 +199,7 @@ var ( DifficultyAdjustmentFactor int64 = 40 // This is the factor that divides the log of the change in the difficulty MinQuaiConversionAmount = new(big.Int).Mul(big.NewInt(1), big.NewInt(GWei)) // 0.000000001 Quai MaxWorkShareCount = 16 - WorkSharesThresholdDiff = 3 // Number of bits lower than the target that the default consensus engine uses + WorkSharesThresholdDiff = 5 // Number of bits lower than the target that the default consensus engine uses WorkSharesInclusionDepth = 3 // Number of blocks upto which the work shares can be referenced and this is protocol enforced ) diff --git a/quai/api_backend.go b/quai/api_backend.go index ea46fbf848..7d0b55bb9a 100644 --- a/quai/api_backend.go +++ b/quai/api_backend.go @@ -399,14 +399,6 @@ func (b *QuaiAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transacti return b.quai.core.ContentFrom(addr) } -func (b *QuaiAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - nodeCtx := b.quai.core.NodeCtx() - if nodeCtx != common.ZONE_CTX { - return nil - } - return b.quai.core.SubscribeNewTxsEvent(ch) -} - func (b *QuaiAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { nodeCtx := b.quai.core.NodeCtx() if nodeCtx != common.ZONE_CTX { @@ -494,6 +486,14 @@ func (b *QuaiAPIBackend) ConstructLocalMinedBlock(header *types.WorkObject) (*ty return b.quai.core.ConstructLocalMinedBlock(header) } +func (b *QuaiAPIBackend) GetPendingBlockBody(woHeader *types.WorkObjectHeader) *types.WorkObject { + return b.quai.core.GetPendingBlockBody(woHeader) +} + +func (b *QuaiAPIBackend) GetTxsFromBroadcastSet(hash common.Hash) (types.Transactions, error) { + return b.quai.core.GetTxsFromBroadcastSet(hash) +} + func (b *QuaiAPIBackend) InsertBlock(ctx context.Context, block *types.WorkObject) (int, error) { return b.quai.core.InsertChain([]*types.WorkObject{block}) } @@ -613,6 +613,6 @@ func (b *QuaiAPIBackend) BroadcastHeader(header *types.WorkObject, location comm return b.quai.p2p.Broadcast(location, header.ConvertToHeaderView()) } -func (b *QuaiAPIBackend) BroadcastWorkShare(workShare *types.WorkObjectHeader, location common.Location) error { +func (b *QuaiAPIBackend) BroadcastWorkShare(workShare *types.WorkObjectShareView, location common.Location) error { return b.quai.p2p.Broadcast(location, workShare) } diff --git a/quai/filters/filter.go b/quai/filters/filter.go index d673030c02..1982c4052d 100644 --- a/quai/filters/filter.go +++ b/quai/filters/filter.go @@ -38,7 +38,6 @@ type Backend interface { GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error) GetBloom(blockHash common.Hash) (*types.Bloom, error) - SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription diff --git a/quai/filters/filter_system.go b/quai/filters/filter_system.go index 7de5bd6576..f34aeac9b7 100644 --- a/quai/filters/filter_system.go +++ b/quai/filters/filter_system.go @@ -88,7 +88,6 @@ type EventSystem struct { lastHead *types.Header // Subscriptions - txsSub event.Subscription // Subscription for new transaction event logsSub event.Subscription // Subscription for new log event rmLogsSub event.Subscription // Subscription for removed log event pendingLogsSub event.Subscription // Subscription for pending log event @@ -125,7 +124,6 @@ func NewEventSystem(backend Backend) *EventSystem { nodeCtx := backend.NodeCtx() // Subscribe events if nodeCtx == common.ZONE_CTX && backend.ProcessingState() { - m.txsSub = m.backend.SubscribeNewTxsEvent(m.txsCh) m.logsSub = m.backend.SubscribeLogsEvent(m.logsCh) m.rmLogsSub = m.backend.SubscribeRemovedLogsEvent(m.rmLogsCh) m.pendingLogsSub = m.backend.SubscribePendingLogsEvent(m.pendingLogsCh) @@ -134,7 +132,7 @@ func NewEventSystem(backend Backend) *EventSystem { // Make sure none of the subscriptions are empty if nodeCtx == common.ZONE_CTX && backend.ProcessingState() { - if m.txsSub == nil || m.logsSub == nil || m.rmLogsSub == nil || m.chainSub == nil || m.pendingLogsSub == nil { + if m.logsSub == nil || m.rmLogsSub == nil || m.chainSub == nil || m.pendingLogsSub == nil { backend.Logger().Fatal("Subscribe for event system failed") } } else { @@ -371,7 +369,6 @@ func (es *EventSystem) eventLoop() { // Ensure all subscriptions get cleaned up defer func() { if nodeCtx == common.ZONE_CTX && es.backend.ProcessingState() { - es.txsSub.Unsubscribe() es.logsSub.Unsubscribe() es.rmLogsSub.Unsubscribe() es.pendingLogsSub.Unsubscribe() @@ -456,8 +453,6 @@ func (es *EventSystem) handleZoneEventLoop(index filterIndex) { } close(f.err) // System stopped - case <-es.txsSub.Err(): - return case <-es.logsSub.Err(): return case <-es.rmLogsSub.Err(): diff --git a/quai/filters/filter_system_test.go b/quai/filters/filter_system_test.go index 9587e1a61f..b139d2f23f 100644 --- a/quai/filters/filter_system_test.go +++ b/quai/filters/filter_system_test.go @@ -102,10 +102,6 @@ func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types return logs, nil } -func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - return b.txFeed.Subscribe(ch) -} - func (b *testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { return b.rmLogsFeed.Subscribe(ch) } diff --git a/quai/handler.go b/quai/handler.go index ed678b39fa..61966fb5cd 100644 --- a/quai/handler.go +++ b/quai/handler.go @@ -21,6 +21,8 @@ const ( c_checkNextPrimeBlockInterval = 60 * time.Second // c_txsChanSize is the size of channel listening to the new txs event c_newTxsChanSize = 1000 + // c_newWsChanSize is the size of channel listening to the new workobjectshare event + c_newWsChanSize = 10 // c_recentBlockReqCache is the size of the cache for the recent block requests c_recentBlockReqCache = 1000 // c_recentBlockReqTimeout is the timeout for the recent block requests cache @@ -38,12 +40,12 @@ type handler struct { core *core.Core missingBlockCh chan types.BlockRequest missingBlockSub event.Subscription - txsCh chan core.NewTxsEvent - txsSub event.Subscription wg sync.WaitGroup quitCh chan struct{} logger *log.Logger + txs types.Transactions + recentBlockReqCache *expireLru.LRU[common.Hash, interface{}] // cache the latest requests on a 1 min timer } @@ -54,6 +56,7 @@ func newHandler(p2pBackend NetworkingAPI, core *core.Core, nodeLocation common.L core: core, quitCh: make(chan struct{}), logger: logger, + txs: make(types.Transactions, 0), } handler.recentBlockReqCache = expireLru.NewLRU[common.Hash, interface{}](c_recentBlockReqCache, nil, c_recentBlockReqTimeout) return handler @@ -66,13 +69,6 @@ func (h *handler) Start() { go h.missingBlockLoop() nodeCtx := h.nodeLocation.Context() - if nodeCtx == common.ZONE_CTX && h.core.ProcessingState() { - h.wg.Add(1) - h.txsCh = make(chan core.NewTxsEvent, c_newTxsChanSize) - h.txsSub = h.core.SubscribeNewTxsEvent(h.txsCh) - go h.txBroadcastLoop() - } - if nodeCtx == common.PRIME_CTX { h.wg.Add(1) go h.checkNextPrimeBlock() @@ -81,10 +77,6 @@ func (h *handler) Start() { func (h *handler) Stop() { h.missingBlockSub.Unsubscribe() // quits missingBlockLoop - nodeCtx := h.nodeLocation.Context() - if nodeCtx == common.ZONE_CTX && h.core.ProcessingState() { - h.txsSub.Unsubscribe() // quits the txBroadcastLoop - } close(h.quitCh) h.wg.Wait() } @@ -145,62 +137,6 @@ func (h *handler) missingBlockLoop() { } } -// txBroadcastLoop announces new transactions to connected peers. -func (h *handler) txBroadcastLoop() { - transactions := make(types.Transactions, 0, c_maxTxBatchSize) - broadcastTransactionsTicker := time.NewTicker(c_broadcastTransactionsInterval) - defer broadcastTransactionsTicker.Stop() - defer h.wg.Done() - defer func() { - if r := recover(); r != nil { - h.logger.WithFields(log.Fields{ - "error": r, - "stacktrace": string(debug.Stack()), - }).Fatal("Go-Quai Panicked") - } - }() - for { - select { - case event := <-h.txsCh: - // check if the length of the transactions becomes more than the c_maxTxBatchSize - // In case the txsCh can send - numBatches := (len(transactions) + len(event.Txs)) / c_maxTxBatchSize - if numBatches > 0 { - // create a local cache and add all the txs and broadcast - transactions = append(transactions, event.Txs...) - for i := 0; i < numBatches; i++ { - start := i * c_maxTxBatchSize - end := start + c_maxTxBatchSize - if end > len(transactions) { - end = len(transactions) - } - h.broadcastTransactions(transactions[start:end]) - } - transactions = make(types.Transactions, 0, c_maxTxBatchSize) - } else { - transactions = append(transactions, event.Txs...) - } - case <-broadcastTransactionsTicker.C: - // every ticker, gather all the transactions and broadcast them and - // reset the transactions list - h.broadcastTransactions(transactions) - transactions = make(types.Transactions, 0, c_maxTxBatchSize) - case <-h.txsSub.Err(): - return - } - } -} - -func (h *handler) broadcastTransactions(transactions types.Transactions) { - if len(transactions) == 0 { - return - } - err := h.p2pBackend.Broadcast(h.nodeLocation, &transactions) - if err != nil { - h.logger.Errorf("Error broadcasting transactions: %+v", err) - } -} - // checkNextPrimeBlock runs every c_checkNextPrimeBlockInterval and ask the peer for the next Block func (h *handler) checkNextPrimeBlock() { defer h.wg.Done() diff --git a/quai/interface.go b/quai/interface.go index b7465af73d..39cb1b88a3 100644 --- a/quai/interface.go +++ b/quai/interface.go @@ -23,7 +23,7 @@ type ConsensusAPI interface { // Handle new data propagated from the gossip network. Should return quickly. // Specify the peer which propagated the data to us, as well as the data itself. // Return true if this data should be relayed to peers. False if it should be ignored. - OnNewBroadcast(core.PeerID, string, interface{}, common.Location) bool + OnNewBroadcast(core.PeerID, string, string, interface{}, common.Location) bool // Creates the function that will be used to determine if a message should be propagated. ValidatorFunc() func(ctx context.Context, id peer.ID, msg *pubsub.Message) pubsub.ValidationResult diff --git a/quai/p2p_backend.go b/quai/p2p_backend.go index 5a49981e90..0a8c3d8d4d 100644 --- a/quai/p2p_backend.go +++ b/quai/p2p_backend.go @@ -16,6 +16,8 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ) +const c_maxTxInWorkShare = 200 + // QuaiBackend implements the quai consensus protocol type QuaiBackend struct { p2pBackend NetworkingAPI // Interface for all the P2P methods the libp2p exposes to consensus @@ -77,7 +79,7 @@ func (qbe *QuaiBackend) GetBackend(location common.Location) *quaiapi.Backend { } // Handle consensus data propagated to us from our peers -func (qbe *QuaiBackend) OnNewBroadcast(sourcePeer p2p.PeerID, topic string, data interface{}, nodeLocation common.Location) bool { +func (qbe *QuaiBackend) OnNewBroadcast(sourcePeer p2p.PeerID, Id string, topic string, data interface{}, nodeLocation common.Location) bool { defer types.ObjectPool.Put(data) switch data := data.(type) { case types.WorkObjectBlockView: @@ -104,23 +106,49 @@ func (qbe *QuaiBackend) OnNewBroadcast(sourcePeer p2p.PeerID, topic string, data } // If it was a good broadcast, mark the peer as lively qbe.p2pBackend.MarkLivelyPeer(sourcePeer, topic) - case types.Transactions: + case types.WorkObjectShareView: backend := *qbe.GetBackend(nodeLocation) if backend == nil { log.Global.Error("no backend found") return false } if backend.ProcessingState() { - backend.SendRemoteTxs(data) - } - // TODO: Handle the error here and mark the peers accordingly - case types.WorkObjectHeader: - backend := *qbe.GetBackend(nodeLocation) - if backend == nil { - log.Global.Error("no backend found") - return false + // check if the work share is valid before accepting the transactions + // from the peer + if data.WorkObject == nil { + backend.Logger().Error("work share received from peer has a nil work object") + return false + } + if data.WorkObject.WorkObjectHeader() == nil { + backend.Logger().Error("work share received from peer has a nil work object header") + return false + } + if ok := backend.CheckIfValidWorkShare(data.WorkObject.WorkObjectHeader()); !ok { + backend.Logger().Error("work share received from peer is not valid") + return false + } + // check if the txs in the workObject hash to the tx hash in the body header + if hash := types.DeriveSha(data.WorkObject.Transactions(), trie.NewStackTrie(nil)); hash != data.WorkObject.TxHash() { + backend.Logger().Error("TxHash doesnt match the hash of the transactions in the work object received from peer") + return false + } + + if len(data.WorkObject.Transactions()) > c_maxTxInWorkShare { + backend.Logger().Error("TxHash doesnt match the hash of the transactions in the work object received from peer") + return false + } + + powHash, err := backend.Engine().ComputePowHash(data.WorkObject.WorkObjectHeader()) + if err != nil { + backend.Logger().Error("Error computing the powHash of the work object header received from peer") + return false + } + + backend.Logger().WithFields(log.Fields{"powHash": powHash, "tx count": len(data.WorkObject.Transactions()), "message id": Id}).Info("Received a work share broadcast") + // Unpack the workobjectheader and the transactions + backend.SendWorkShare(data.WorkObject.WorkObjectHeader()) + backend.SendRemoteTxs(data.WorkObject.Transactions()) } - backend.SendWorkShare(&data) // If it was a good broadcast, mark the peer as lively qbe.p2pBackend.MarkLivelyPeer(sourcePeer, topic) default: diff --git a/quaistats/quaistats.go b/quaistats/quaistats.go index ff5e7777ea..01e5a9138d 100644 --- a/quaistats/quaistats.go +++ b/quaistats/quaistats.go @@ -91,7 +91,6 @@ var ( // backend encompasses the bare-minimum functionality needed for quaistats reporting type backend interface { SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription - SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription CurrentHeader() *types.WorkObject TotalLogS(header *types.WorkObject) *big.Int HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.WorkObject, error)