From 466ae5f640bb61d4137e292946fdb6d6c814c114 Mon Sep 17 00:00:00 2001 From: Jonathan Downing Date: Fri, 13 Sep 2024 17:14:46 -0500 Subject: [PATCH] Added lockups for Qi and Quai coinbase --- common/internal_address.go | 5 + common/proto_common.pb.go | 2 +- consensus/blake3pow/consensus.go | 1 + consensus/progpow/consensus.go | 1 + core/genesis.go | 1 + core/rawdb/accessors_chain_test.go | 18 +- core/rawdb/db.pb.go | 2 +- core/slice.go | 3 +- core/state_processor.go | 70 ++- core/types/block.go | 1 + core/types/gen_header_json.go | 4 + core/types/proto_block.pb.go | 541 ++++++++++---------- core/types/proto_block.proto | 1 + core/types/wo.go | 30 +- core/types/wo_test.go | 1 + core/vm/contracts.go | 92 +++- core/vm/evm.go | 2 +- core/worker.go | 137 +++-- p2p/node/peerManager/peerdb/peer_info.pb.go | 2 +- p2p/pb/quai_messages.pb.go | 2 +- params/config.go | 20 +- params/protocol_params.go | 28 +- quaiclient/quaiclient.go | 1 + 23 files changed, 589 insertions(+), 376 deletions(-) diff --git a/common/internal_address.go b/common/internal_address.go index d43ea4f8a4..767f56a353 100644 --- a/common/internal_address.go +++ b/common/internal_address.go @@ -141,3 +141,8 @@ func (a InternalAddress) IsInQuaiLedgerScope() bool { // The first bit of the second byte is not set if the address is in the Quai ledger return a.Bytes()[1] <= 127 } + +func (a InternalAddress) IsInQiLedgerScope() bool { + // The first bit of the second byte is set if the address is in the Qi ledger + return a.Bytes()[1] > 127 +} diff --git a/common/proto_common.pb.go b/common/proto_common.pb.go index eb90de7fbc..9ffbc5669f 100644 --- a/common/proto_common.pb.go +++ b/common/proto_common.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.28.1 +// protoc v5.28.2 // source: common/proto_common.proto package common diff --git a/consensus/blake3pow/consensus.go b/consensus/blake3pow/consensus.go index 4c3b1f4326..07bdec16ad 100644 --- a/consensus/blake3pow/consensus.go +++ b/consensus/blake3pow/consensus.go @@ -605,6 +605,7 @@ func (blake3pow *Blake3pow) Finalize(chain consensus.ChainHeaderReader, header * return nil, err } state.CreateAccount(lockupContract) + state.SetNonce(lockupContract, 1) // so it's not considered "empty" alloc := core.ReadGenesisAlloc("genallocs/gen_alloc_quai_"+nodeLocation.Name()+".json", blake3pow.logger) blake3pow.logger.WithField("alloc", len(alloc)).Info("Allocating genesis accounts") diff --git a/consensus/progpow/consensus.go b/consensus/progpow/consensus.go index a834420174..bcc67054ae 100644 --- a/consensus/progpow/consensus.go +++ b/consensus/progpow/consensus.go @@ -661,6 +661,7 @@ func (progpow *Progpow) Finalize(chain consensus.ChainHeaderReader, header *type return nil, err } state.CreateAccount(lockupContract) + state.SetNonce(lockupContract, 1) // so it's not considered "empty" alloc := core.ReadGenesisAlloc("genallocs/gen_alloc_quai_"+nodeLocation.Name()+".json", progpow.logger) progpow.logger.WithField("alloc", len(alloc)).Info("Allocating genesis accounts") diff --git a/core/genesis.go b/core/genesis.go index 993b8eb55d..e6f97f49c8 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -273,6 +273,7 @@ func (g *Genesis) ToBlock(startingExpansionNumber uint64) *types.WorkObject { wo.WorkObjectHeader().SetPrimeTerminusNumber(big.NewInt(0)) wo.WorkObjectHeader().SetTime(g.Timestamp) wo.WorkObjectHeader().SetCoinbase(common.Zero) + wo.WorkObjectHeader().SetLock(0) wo.Header().SetExtra(g.ExtraData) wo.Header().SetGasLimit(g.GasLimit) wo.Header().SetGasUsed(0) diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 40a4a910a0..9e607e8539 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -59,7 +59,7 @@ func TestHeaderStorage(t *testing.T) { woBody := types.EmptyWorkObjectBody() woBody.SetHeader(header) - woHeader := types.NewWorkObjectHeader(header.Hash(), common.Hash{1}, big.NewInt(1), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{1}, common.Location{0, 0})) + woHeader := types.NewWorkObjectHeader(header.Hash(), common.Hash{1}, big.NewInt(1), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{1}, common.Location{0, 0})) wo := types.NewWorkObject(woHeader, woBody, nil) @@ -190,7 +190,7 @@ func TestPbCacheStorage(t *testing.T) { woBody := types.EmptyWorkObjectBody() woBody.SetHeader(types.EmptyHeader()) - woHeader := types.NewWorkObjectHeader(types.EmptyRootHash, types.EmptyRootHash, big.NewInt(11), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{1}, common.Location{0, 0})) + woHeader := types.NewWorkObjectHeader(types.EmptyRootHash, types.EmptyRootHash, big.NewInt(11), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{1}, common.Location{0, 0})) wo := types.NewWorkObject(woHeader, woBody, nil) WritePbCacheBody(db, common.Hash{1}, wo) @@ -320,7 +320,7 @@ func TestBlockHashesIterator(t *testing.T) { blockHeader := types.EmptyHeader() blockBody := types.EmptyWorkObjectBody() blockBody.SetHeader(blockHeader) - blockWoHeader := types.NewWorkObjectHeader(blockHeader.Hash(), types.EmptyHash, big.NewInt(int64(i+1)), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 2, common.Location{0, byte(j)}, common.BytesToAddress([]byte{1}, common.Location{0, byte(j)})) + blockWoHeader := types.NewWorkObjectHeader(blockHeader.Hash(), types.EmptyHash, big.NewInt(int64(i+1)), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 2, common.Location{0, byte(j)}, common.BytesToAddress([]byte{1}, common.Location{0, byte(j)})) block := types.NewWorkObject(blockWoHeader, blockBody, nil) WriteWorkObject(db, block.Hash(), block, types.BlockObject, common.ZONE_CTX) hashes[i][block.Hash()] = true @@ -345,7 +345,7 @@ func TestCommonAncestor(t *testing.T) { regionHeader.SetNumber(big.NewInt(1), common.REGION_CTX) regionBody := types.EmptyWorkObjectBody() regionBody.SetHeader(regionHeader) - regionWoHeader := types.NewWorkObjectHeader(regionHeader.Hash(), types.EmptyRootHash, big.NewInt(1), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, common.Location{0}, common.BytesToAddress([]byte{0}, common.Location{0, 0})) + regionWoHeader := types.NewWorkObjectHeader(regionHeader.Hash(), types.EmptyRootHash, big.NewInt(1), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 1, common.Location{0}, common.BytesToAddress([]byte{0}, common.Location{0, 0})) regionBlock := types.NewWorkObject(regionWoHeader, regionBody, nil) WriteWorkObject(db, regionBlock.Hash(), regionBlock, types.BlockObject, common.REGION_CTX) @@ -353,7 +353,7 @@ func TestCommonAncestor(t *testing.T) { zone0Header := types.EmptyHeader() zone0Body := types.EmptyWorkObjectBody() zone0Body.SetHeader(zone0Header) - zone0WoHeader := types.NewWorkObjectHeader(zone0Header.Hash(), regionBlock.Hash(), big.NewInt(2), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 2, common.Location{0, 0}, common.BytesToAddress([]byte{0}, common.Location{0, 0})) + zone0WoHeader := types.NewWorkObjectHeader(zone0Header.Hash(), regionBlock.Hash(), big.NewInt(2), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 2, common.Location{0, 0}, common.BytesToAddress([]byte{0}, common.Location{0, 0})) zone0Block := types.NewWorkObject(zone0WoHeader, zone0Body, nil) WriteWorkObject(db, zone0Block.Hash(), zone0Block, types.BlockObject, common.ZONE_CTX) @@ -361,14 +361,14 @@ func TestCommonAncestor(t *testing.T) { zone1Header1 := types.EmptyHeader() zone1Body1 := types.EmptyWorkObjectBody() zone1Body1.SetHeader(zone1Header1) - zone1WoHeader1 := types.NewWorkObjectHeader(zone1Header1.Hash(), regionBlock.Hash(), big.NewInt(2), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 2, common.Location{0, 1}, common.BytesToAddress([]byte{0}, common.Location{0, 1})) + zone1WoHeader1 := types.NewWorkObjectHeader(zone1Header1.Hash(), regionBlock.Hash(), big.NewInt(2), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 2, common.Location{0, 1}, common.BytesToAddress([]byte{0}, common.Location{0, 1})) zone1Block1 := types.NewWorkObject(zone1WoHeader1, zone1Body1, nil) WriteWorkObject(db, zone1Block1.Hash(), zone1Block1, types.BlockObject, common.ZONE_CTX) zone1Header2 := types.EmptyHeader() zone1Body2 := types.EmptyWorkObjectBody() zone1Body2.SetHeader(zone1Header2) - zone1WoHeader2 := types.NewWorkObjectHeader(zone1Header2.Hash(), zone1Block1.Hash(), big.NewInt(3), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 3, common.Location{0, 1}, common.BytesToAddress([]byte{0}, common.Location{0, 1})) + zone1WoHeader2 := types.NewWorkObjectHeader(zone1Header2.Hash(), zone1Block1.Hash(), big.NewInt(3), big.NewInt(3000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 3, common.Location{0, 1}, common.BytesToAddress([]byte{0}, common.Location{0, 1})) zone1Block2 := types.NewWorkObject(zone1WoHeader2, zone1Body2, nil) WriteWorkObject(db, zone1Block2.Hash(), zone1Block2, types.BlockObject, common.ZONE_CTX) @@ -585,7 +585,7 @@ func createTestWorkObject() *types.WorkObject { woBody := types.EmptyWorkObjectBody() woBody.SetHeader(types.EmptyHeader()) - woHeader := types.NewWorkObjectHeader(types.EmptyRootHash, types.EmptyRootHash, big.NewInt(11), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{0}, common.Location{0, 0})) + woHeader := types.NewWorkObjectHeader(types.EmptyRootHash, types.EmptyRootHash, big.NewInt(11), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{0}, common.Location{0, 0})) return types.NewWorkObject(woHeader, woBody, nil) } @@ -739,7 +739,7 @@ func createBlockWithTransactions(txs types.Transactions) *types.WorkObject { woBody := types.EmptyWorkObjectBody() woBody.SetHeader(types.EmptyHeader()) woBody.SetTransactions(txs) - return types.NewWorkObject(types.NewWorkObjectHeader(types.EmptyRootHash, types.EmptyRootHash, big.NewInt(0), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{0}, common.Location{0, 0})), woBody, nil) + return types.NewWorkObject(types.NewWorkObjectHeader(types.EmptyRootHash, types.EmptyRootHash, big.NewInt(0), big.NewInt(30000), big.NewInt(42), types.EmptyRootHash, types.BlockNonce{23}, 1, 1, common.LocationFromAddressBytes([]byte{0x01, 0x01}), common.BytesToAddress([]byte{0}, common.Location{0, 0})), woBody, nil) } func writeBlockForReceipts(db ethdb.Database, hash common.Hash, txs types.Transactions) { diff --git a/core/rawdb/db.pb.go b/core/rawdb/db.pb.go index 525bfc27ab..0c54a7f092 100644 --- a/core/rawdb/db.pb.go +++ b/core/rawdb/db.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.28.1 +// protoc v5.28.2 // source: core/rawdb/db.proto package rawdb diff --git a/core/slice.go b/core/slice.go index 271953c405..d369df2fb8 100644 --- a/core/slice.go +++ b/core/slice.go @@ -905,6 +905,7 @@ func (sl *Slice) combinePendingHeader(header *types.WorkObject, slPendingHeader combinedPendingHeader.WorkObjectHeader().SetTxHash(header.TxHash()) combinedPendingHeader.WorkObjectHeader().SetPrimeTerminusNumber(header.PrimeTerminusNumber()) combinedPendingHeader.WorkObjectHeader().SetCoinbase(header.Coinbase()) + combinedPendingHeader.WorkObjectHeader().SetLock(header.Lock()) combinedPendingHeader.Header().SetEtxRollupHash(header.EtxRollupHash()) combinedPendingHeader.Header().SetUncledEntropy(header.Header().UncledEntropy()) @@ -1027,8 +1028,6 @@ func (sl *Slice) NewGenesisPendingHeader(domPendingHeader *types.WorkObject, dom localPendingHeader.WorkObjectHeader().SetCoinbase(common.Zero) } - localPendingHeader.WorkObjectHeader().SetLocation(common.Location{0, 0}) - if nodeCtx == common.PRIME_CTX { domPendingHeader = types.CopyWorkObject(localPendingHeader) } else { diff --git a/core/state_processor.go b/core/state_processor.go index ee55077845..97f6494451 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -19,6 +19,7 @@ package core import ( "errors" "fmt" + "math" "math/big" "runtime/debug" "sync" @@ -306,6 +307,9 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty emittedEtxs := make([]*types.Transaction, 0) // create a etx for the Coinbase and all the workshares in the block coinbase := block.Coinbase() + if _, err := coinbase.InternalAddress(); err != nil { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("could not get internal address for coinbase: %w", err) + } if coinbase.IsInQiLedgerScope() { // placeholder for the coinbase coinbaseEtx := types.NewTx(&types.ExternalTx{}) emittedEtxs = append(emittedEtxs, coinbaseEtx) @@ -318,13 +322,17 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty for i, uncle := range block.Uncles() { reward := misc.CalculateReward(uncle) uncleCoinbase := uncle.Coinbase() + if _, err := uncleCoinbase.InternalAddress(); err != nil { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("could not get internal address for uncle coinbase: %w", err) + } // parent hash encoding for populating into the originating tx hash for coinbase origin := block.ParentHash(nodeCtx) origin[0] = byte(block.Location().Region()) origin[1] = byte(block.Location().Zone()) - emittedEtxs = append(emittedEtxs, types.NewTx(&types.ExternalTx{To: &uncleCoinbase, Value: reward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: uint16(i) + 1, Sender: uncleCoinbase})) + emittedEtxs = append(emittedEtxs, types.NewTx(&types.ExternalTx{To: &uncleCoinbase, Value: reward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: uint16(i) + 1, Sender: uncleCoinbase, Data: []byte{uncle.Lock()}})) } + quaiCoinbaseEtxs := make(map[[21]byte]*big.Int) var totalQiTime time.Duration var totalEtxAppendTime time.Duration var totalEtxCoinbaseTime time.Duration @@ -403,12 +411,25 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty // 3) do not produce any receipts/logs // 4) etx emit threshold numbers if types.IsCoinBaseTx(tx) { - iAddr, err := tx.To().InternalAddress() - if err != nil { - return nil, nil, nil, nil, 0, 0, nil, errors.New("coinbase address is not in the chain scope") + if tx.To() == nil { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("coinbase tx %x has no recipient", tx.Hash()) } + if len(tx.Data()) == 0 { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("coinbase tx %x has no lockup byte", tx.Hash()) + } + if _, err := tx.To().InternalAddress(); err != nil { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("coinbase tx %x has invalid recipient: %w", tx.Hash(), err) + } + lockupByte := tx.Data()[0] if tx.To().IsInQiLedgerScope() { - value := tx.Value() + if int(lockupByte) > len(params.LockupByteToBlockDepth) { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("coinbase lockup byte %d is out of range", lockupByte) + } + lockup := new(big.Int).SetUint64(params.LockupByteToBlockDepth[lockupByte]) + if lockup.Uint64() < params.ConversionLockPeriod { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("coinbase lockup period is less than the minimum lockup period of %d blocks", params.ConversionLockPeriod) + } + value := params.CalculateCoinbaseValueWithLockup(tx.Value(), lockupByte) denominations := misc.FindMinDenominations(value) outputIndex := uint16(0) // Iterate over the denominations in descending order @@ -422,20 +443,28 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty // No more gas, the rest of the denominations are lost but the tx is still valid break } - utxo := types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), block.Number(nodeCtx))) + utxo := types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), lockup)) // the ETX hash is guaranteed to be unique if err := rawdb.CreateUTXO(batch, etx.Hash(), outputIndex, utxo); err != nil { return nil, nil, nil, nil, 0, 0, nil, err } utxosCreatedDeleted.UtxosCreatedHashes = append(utxosCreatedDeleted.UtxosCreatedHashes, types.UTXOHash(etx.Hash(), outputIndex, utxo)) utxosCreatedDeleted.UtxosCreatedKeys = append(utxosCreatedDeleted.UtxosCreatedKeys, rawdb.UtxoKey(etx.Hash(), outputIndex)) - p.logger.Debugf("Creating UTXO for coinbase %032x with denomination %d index %d\n", tx.Hash(), denomination, outputIndex) + p.logger.Debugf("Creating UTXO for coinbase %032x with denomination %d index %d and lock %d\n", tx.Hash(), denomination, outputIndex, lockup.Int64()) outputIndex++ } } } else if tx.To().IsInQuaiLedgerScope() { - // This includes the value and the fees - statedb.AddBalance(iAddr, tx.Value()) + // Combine similar lockups (to address and lockup period) into a single lockup entry + coinbaseAddrWithLockup := [21]byte(append(tx.To().Bytes(), lockupByte)) + if val, ok := quaiCoinbaseEtxs[coinbaseAddrWithLockup]; ok { + // Combine the values of the coinbase transactions + val.Add(val, tx.Value()) + quaiCoinbaseEtxs[coinbaseAddrWithLockup] = val + } else { + // Add the new coinbase transaction to the map + quaiCoinbaseEtxs[coinbaseAddrWithLockup] = tx.Value() // this creates a new *big.Int + } } timeDelta := time.Since(startTimeEtx) timeCoinbase += timeDelta @@ -443,7 +472,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty } if etx.To().IsInQiLedgerScope() { if etx.ETXSender().Location().Equal(*etx.To().Location()) { // Quai->Qi Conversion - lock := new(big.Int).Add(header.Number(nodeCtx), big.NewInt(params.ConversionLockPeriod)) + lock := new(big.Int).Add(header.Number(nodeCtx), new(big.Int).SetUint64(params.ConversionLockPeriod)) primeTerminus := p.hc.GetHeaderByHash(header.PrimeTerminusHash()) if primeTerminus == nil { return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("could not find prime terminus header %032x", header.PrimeTerminusHash()) @@ -509,7 +538,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty continue } else { if etx.ETXSender().Location().Equal(*etx.To().Location()) { // Qi->Quai Conversion - msg.SetLock(new(big.Int).Add(header.Number(nodeCtx), big.NewInt(params.ConversionLockPeriod))) + msg.SetLock(new(big.Int).Add(header.Number(nodeCtx), new(big.Int).SetUint64(params.ConversionLockPeriod))) primeTerminus := p.hc.GetHeaderByHash(header.PrimeTerminusHash()) if primeTerminus == nil { return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("could not find prime terminus header %032x", header.PrimeTerminusHash()) @@ -590,6 +619,21 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty p.logger.Errorf("prevInboundEtxs: %d, oldestIndex: %d, etxHash: %s", len(prevInboundEtxs), oldestIndex.Int64(), etx.Hash().Hex()) return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("total gas used by ETXs %d is not within the range %d to %d", totalEtxGas, minimumEtxGas, maximumEtxGas) } + lockupContractAddress := vm.LockupContractAddresses[[2]byte{nodeLocation[0], nodeLocation[1]}] + for coinbaseAddrWithLockup, value := range quaiCoinbaseEtxs { + addr := common.BytesToAddress(coinbaseAddrWithLockup[:20], nodeLocation) + lockupByte := coinbaseAddrWithLockup[20] + lockup := new(big.Int).SetUint64(params.LockupByteToBlockDepth[lockupByte]) + if lockup.Uint64() < params.ConversionLockPeriod { + return nil, nil, nil, nil, 0, 0, nil, fmt.Errorf("coinbase lockup period is less than the minimum lockup period of %d blocks", params.ConversionLockPeriod) + } + value := params.CalculateCoinbaseValueWithLockup(value, lockupByte) + gasUsed, _, err := vm.AddNewLock(parent.QuaiStateSize(), statedb, addr, new(types.GasPool).AddGas(math.MaxUint64), lockup, value, lockupContractAddress) + if err != nil { + return nil, nil, nil, nil, 0, 0, nil, err + } + p.logger.Debugf("Creating Lockup for coinbase addr %s with value %d lock %d gasUsed %d\n", addr.String(), value.Uint64(), lockup.Int64(), gasUsed) + } coinbaseReward := misc.CalculateReward(block.WorkObjectHeader()) blockReward := new(big.Int).Add(coinbaseReward, totalFees) @@ -597,7 +641,7 @@ func (p *StateProcessor) Process(block *types.WorkObject, batch ethdb.Batch) (ty origin := block.ParentHash(nodeCtx) origin[0] = byte(block.Location().Region()) origin[1] = byte(block.Location().Zone()) - emittedEtxs[0] = types.NewTx(&types.ExternalTx{To: &coinbase, Value: blockReward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: 0, Sender: coinbase}) + emittedEtxs[0] = types.NewTx(&types.ExternalTx{To: &coinbase, Value: blockReward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: 0, Sender: coinbase, Data: []byte{block.Lock()}}) time4 := common.PrettyDuration(time.Since(start)) // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) @@ -1287,7 +1331,7 @@ func ApplyTransaction(config *params.ChainConfig, parent *types.WorkObject, pare return nil, nil, err } if tx.Type() == types.ExternalTxType && tx.ETXSender().Location().Equal(*tx.To().Location()) { // Qi->Quai Conversion - msg.SetLock(new(big.Int).Add(header.Number(nodeCtx), big.NewInt(params.ConversionLockPeriod))) + msg.SetLock(new(big.Int).Add(header.Number(nodeCtx), new(big.Int).SetUint64(params.ConversionLockPeriod))) var primeTerminus *types.WorkObject if parentOrder == common.PRIME_CTX { primeTerminus = parent diff --git a/core/types/block.go b/core/types/block.go index 8230688f6d..8672fee63c 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -175,6 +175,7 @@ func EmptyWorkObject(nodeCtx int) *WorkObject { wo.woHeader.SetTxHash(EmptyRootHash) wo.woHeader.SetNonce(EncodeNonce(0)) wo.woHeader.SetLocation(common.Location{}) + wo.woHeader.SetLock(0) wo.woHeader.SetTime(0) wo.woBody.SetHeader(h) wo.woBody.SetUncles([]*WorkObjectHeader{}) diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index 301f826d37..0c83f44404 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -301,6 +301,7 @@ func (wh *WorkObjectHeader) MarshalJSON() ([]byte, error) { MixHash common.Hash `json:"mixHash" gencoden:"required"` Time hexutil.Uint64 `json:"timestamp" gencoden:"required"` Nonce BlockNonce `json:"nonce" gencoden:"required"` + Lock hexutil.Uint64 `json:"lock" gencoden:"required"` Coinbase common.Address `json:"coinbase" gencoden:"required"` } @@ -314,6 +315,7 @@ func (wh *WorkObjectHeader) MarshalJSON() ([]byte, error) { enc.Time = hexutil.Uint64(wh.Time()) enc.Nonce = wh.Nonce() enc.Coinbase = wh.Coinbase() + enc.Lock = hexutil.Uint64(wh.Lock()) raw, err := json.Marshal(&enc) return raw, err @@ -331,6 +333,7 @@ func (wh *WorkObjectHeader) UnmarshalJSON(input []byte) error { MixHash common.Hash `json:"mixHash" gencoden:"required"` Time hexutil.Uint64 `json:"timestamp" gencoden:"required"` Nonce BlockNonce `json:"nonce" gencoden:"required"` + Lock hexutil.Uint64 `json:"lock" gencoden:"required"` Coinbase common.Address `json:"coinbase" gencoden:"required"` } @@ -352,6 +355,7 @@ func (wh *WorkObjectHeader) UnmarshalJSON(input []byte) error { wh.SetMixHash(dec.MixHash) wh.SetTime(uint64(dec.Time)) wh.SetNonce(dec.Nonce) + wh.SetLock(uint8(dec.Lock)) wh.SetCoinbase(dec.Coinbase) return nil } diff --git a/core/types/proto_block.pb.go b/core/types/proto_block.pb.go index 98f469f95f..154099e24d 100644 --- a/core/types/proto_block.pb.go +++ b/core/types/proto_block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.28.1 +// protoc v5.28.2 // source: core/types/proto_block.proto package types @@ -743,6 +743,7 @@ type ProtoWorkObjectHeader struct { Time *uint64 `protobuf:"varint,9,opt,name=time,proto3,oneof" json:"time,omitempty"` PrimeTerminusNumber []byte `protobuf:"bytes,10,opt,name=prime_terminus_number,json=primeTerminusNumber,proto3,oneof" json:"prime_terminus_number,omitempty"` Coinbase *common.ProtoAddress `protobuf:"bytes,11,opt,name=coinbase,proto3,oneof" json:"coinbase,omitempty"` + Lock *uint32 `protobuf:"varint,12,opt,name=lock,proto3,oneof" json:"lock,omitempty"` } func (x *ProtoWorkObjectHeader) Reset() { @@ -854,6 +855,13 @@ func (x *ProtoWorkObjectHeader) GetCoinbase() *common.ProtoAddress { return nil } +func (x *ProtoWorkObjectHeader) GetLock() uint32 { + if x != nil && x.Lock != nil { + return *x.Lock + } + return 0 +} + type ProtoWorkObjectHeaders struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2654,7 +2662,7 @@ var file_core_types_proto_block_proto_rawDesc = []byte{ 0x73, 0x73, 0x5f, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, 0xa5, 0x05, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x54, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, 0xc7, 0x05, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, @@ -2687,272 +2695,275 @@ var file_core_types_proto_block_proto_rawDesc = []byte{ 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x0b, 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, 0x48, 0x0a, 0x52, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, - 0x65, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, - 0x68, 0x61, 0x73, 0x68, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x68, 0x61, 0x73, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, - 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x42, 0x0a, - 0x0a, 0x08, 0x5f, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6e, - 0x6f, 0x6e, 0x63, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6d, 0x69, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x07, - 0x0a, 0x05, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x70, 0x72, 0x69, 0x6d, - 0x65, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x22, 0x55, - 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x77, 0x6f, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x09, 0x77, 0x6f, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0xe0, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, - 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2f, 0x0a, - 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x41, - 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x88, 0x01, - 0x01, 0x12, 0x3a, 0x0a, 0x06, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, - 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x48, 0x02, 0x52, 0x06, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x42, 0x0a, - 0x0d, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x18, 0x04, - 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, 0x03, - 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x74, 0x78, 0x73, 0x88, 0x01, - 0x01, 0x12, 0x35, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x48, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x6e, - 0x69, 0x66, 0x65, 0x73, 0x74, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x10, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x48, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6c, 0x69, 0x6e, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, - 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x75, 0x6e, - 0x63, 0x6c, 0x65, 0x73, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6d, 0x61, 0x6e, 0x69, 0x66, - 0x65, 0x73, 0x74, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, - 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0xda, 0x01, 0x0a, 0x0f, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x3e, 0x0a, 0x09, - 0x77, 0x6f, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, - 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, - 0x08, 0x77, 0x6f, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x38, 0x0a, 0x07, - 0x77, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x48, 0x01, 0x52, 0x06, 0x77, 0x6f, 0x42, - 0x6f, 0x64, 0x79, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x02, 0x52, 0x02, 0x74, - 0x78, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x77, 0x6f, 0x5f, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x77, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x42, 0x05, - 0x0a, 0x03, 0x5f, 0x74, 0x78, 0x22, 0x4d, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, - 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0c, 0x77, 0x6f, 0x72, - 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 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, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x22, 0x68, 0x0a, 0x18, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, - 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 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, 0x5f, - 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x56, 0x69, 0x65, 0x77, 0x12, 0x42, 0x0a, 0x0c, 0x77, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x0d, 0x48, 0x0b, 0x52, 0x04, 0x6c, 0x6f, 0x63, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, + 0x0c, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x0e, 0x0a, + 0x0c, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x09, 0x0a, + 0x07, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x64, 0x69, 0x66, + 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x74, 0x78, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x42, 0x0b, 0x0a, + 0x09, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6d, + 0x69, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x75, 0x73, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, + 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, + 0x22, 0x55, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x77, 0x6f, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x09, 0x77, 0x6f, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0xe0, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x2f, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, + 0x12, 0x41, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x88, 0x01, 0x01, 0x12, 0x3a, 0x0a, 0x06, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x48, 0x02, 0x52, 0x06, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, + 0x42, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x65, 0x74, 0x78, 0x73, + 0x18, 0x04, 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, 0x03, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x74, 0x78, 0x73, + 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x48, 0x04, 0x52, 0x08, 0x6d, + 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x88, 0x01, 0x01, 0x12, 0x43, 0x0a, 0x10, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x48, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x88, 0x01, 0x01, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x5f, + 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x73, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, + 0x69, 0x6e, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0xda, 0x01, 0x0a, 0x0f, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x3e, + 0x0a, 0x09, 0x77, 0x6f, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, + 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, + 0x00, 0x52, 0x08, 0x77, 0x6f, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x38, + 0x0a, 0x07, 0x77, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, + 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x48, 0x01, 0x52, 0x06, 0x77, + 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x02, 0x52, + 0x02, 0x74, 0x78, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x77, 0x6f, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x77, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, + 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x74, 0x78, 0x22, 0x4d, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, - 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x69, - 0x65, 0x77, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, - 0x69, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 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, 0xf0, 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, 0x2e, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 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, 0x2a, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 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, 0x05, 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, - 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0d, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x18, 0x07, 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, 0x0c, 0x6f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x74, 0x78, 0x73, 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, 0xa8, 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, 0x42, 0x0a, 0x0d, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 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, 0x0c, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x74, 0x78, 0x73, 0x88, 0x01, 0x01, 0x42, 0x09, - 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 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, 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, + 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0x68, 0x0a, 0x18, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, + 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 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, 0x5f, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x56, 0x69, 0x65, 0x77, 0x12, 0x42, 0x0a, + 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x56, 0x69, 0x65, 0x77, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x22, 0x69, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x57, 0x6f, 0x72, 0x6b, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 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, 0xf0, 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, 0x2e, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 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, 0x2a, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x04, 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, 0x05, 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, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0d, + 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x65, 0x74, 0x78, 0x73, 0x18, 0x07, 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, 0x0c, 0x6f, + 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x74, 0x78, 0x73, 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, 0xa8, 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, 0x42, 0x0a, 0x0d, + 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 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, + 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x45, 0x74, 0x78, 0x73, 0x88, 0x01, 0x01, + 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x10, 0x0a, 0x0e, 0x5f, + 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 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, 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, 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, - 0x22, 0x8c, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x55, - 0x54, 0x58, 0x4f, 0x12, 0x35, 0x0a, 0x08, 0x6f, 0x75, 0x74, 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, 0x08, 0x6f, - 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x05, 0x73, 0x75, - 0x74, 0x78, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x48, 0x01, 0x52, 0x05, - 0x73, 0x75, 0x74, 0x78, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6f, 0x75, 0x74, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x75, 0x74, 0x78, 0x6f, 0x22, - 0x40, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x55, 0x54, 0x58, - 0x4f, 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x53, 0x70, 0x65, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x52, 0x06, 0x73, 0x75, 0x74, 0x78, 0x6f, - 0x73, 0x22, 0x1f, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, 0x6b, 0x65, - 0x79, 0x73, 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, + 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, 0x22, 0x8c, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x53, 0x70, 0x65, 0x6e, + 0x74, 0x55, 0x54, 0x58, 0x4f, 0x12, 0x35, 0x0a, 0x08, 0x6f, 0x75, 0x74, 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, + 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x05, + 0x73, 0x75, 0x74, 0x78, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x54, 0x78, 0x4f, 0x75, 0x74, 0x48, 0x01, + 0x52, 0x05, 0x73, 0x75, 0x74, 0x78, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6f, + 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x75, 0x74, 0x78, + 0x6f, 0x22, 0x40, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x55, + 0x54, 0x58, 0x4f, 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x52, 0x06, 0x73, 0x75, 0x74, + 0x78, 0x6f, 0x73, 0x22, 0x1f, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x4b, 0x65, 0x79, 0x73, + 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, + 0x6b, 0x65, 0x79, 0x73, 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 ( diff --git a/core/types/proto_block.proto b/core/types/proto_block.proto index 0ec7eda988..9fbe2f41a7 100644 --- a/core/types/proto_block.proto +++ b/core/types/proto_block.proto @@ -86,6 +86,7 @@ message ProtoWorkObjectHeader { optional uint64 time = 9; optional bytes prime_terminus_number = 10; optional common.ProtoAddress coinbase = 11; + optional uint32 lock = 12; } message ProtoWorkObjectHeaders { diff --git a/core/types/wo.go b/core/types/wo.go index b3ba2627b2..71537676fe 100644 --- a/core/types/wo.go +++ b/core/types/wo.go @@ -49,9 +49,9 @@ type WorkObjectHeader struct { mixHash common.Hash time uint64 nonce BlockNonce - - PowHash atomic.Value - PowDigest atomic.Value + lock uint8 + PowHash atomic.Value + PowDigest atomic.Value } type WorkObjects []*WorkObject @@ -207,6 +207,10 @@ func (wo *WorkObject) Nonce() BlockNonce { return wo.WorkObjectHeader().Nonce() } +func (wo *WorkObject) Lock() uint8 { + return wo.WorkObjectHeader().Lock() +} + func (wo *WorkObject) Location() common.Location { return wo.WorkObjectHeader().Location() } @@ -533,6 +537,10 @@ func (wh *WorkObjectHeader) Nonce() BlockNonce { return wh.nonce } +func (wh *WorkObjectHeader) Lock() uint8 { + return wh.lock +} + func (wh *WorkObjectHeader) NonceU64() uint64 { return wh.nonce.Uint64() } @@ -585,6 +593,10 @@ func (wh *WorkObjectHeader) SetNonce(nonce BlockNonce) { wh.nonce = nonce } +func (wh *WorkObjectHeader) SetLock(lock uint8) { + wh.lock = lock +} + func (wh *WorkObjectHeader) SetTime(val uint64) { wh.time = val } @@ -788,7 +800,7 @@ func NewWorkObjectBody(header *Header, txs []*Transaction, etxs []*Transaction, } func NewWorkObjectWithHeader(header *WorkObject, tx *Transaction, nodeCtx int, woType WorkObjectView) *WorkObject { - woHeader := NewWorkObjectHeader(header.Hash(), header.ParentHash(common.ZONE_CTX), header.WorkObjectHeader().number, header.WorkObjectHeader().difficulty, header.WorkObjectHeader().PrimeTerminusNumber(), header.WorkObjectHeader().txHash, header.WorkObjectHeader().nonce, header.WorkObjectHeader().time, header.Location(), header.Coinbase()) + woHeader := NewWorkObjectHeader(header.Hash(), header.ParentHash(common.ZONE_CTX), header.WorkObjectHeader().number, header.WorkObjectHeader().difficulty, header.WorkObjectHeader().PrimeTerminusNumber(), header.WorkObjectHeader().txHash, header.WorkObjectHeader().nonce, header.WorkObjectHeader().lock, header.WorkObjectHeader().time, header.Location(), header.Coinbase()) woBody, _ := NewWorkObjectBody(header.Body().Header(), nil, nil, nil, nil, nil, nil, nodeCtx) return NewWorkObject(woHeader, woBody, tx) } @@ -962,7 +974,7 @@ func (wo *WorkObject) ProtoDecode(data *ProtoWorkObject, location common.Locatio return nil } -func NewWorkObjectHeader(headerHash common.Hash, parentHash common.Hash, number *big.Int, difficulty *big.Int, primeTerminusNumber *big.Int, txHash common.Hash, nonce BlockNonce, time uint64, location common.Location, coinbase common.Address) *WorkObjectHeader { +func NewWorkObjectHeader(headerHash common.Hash, parentHash common.Hash, number *big.Int, difficulty *big.Int, primeTerminusNumber *big.Int, txHash common.Hash, nonce BlockNonce, lock uint8, time uint64, location common.Location, coinbase common.Address) *WorkObjectHeader { return &WorkObjectHeader{ headerHash: headerHash, parentHash: parentHash, @@ -971,6 +983,7 @@ func NewWorkObjectHeader(headerHash common.Hash, parentHash common.Hash, number primeTerminusNumber: primeTerminusNumber, txHash: txHash, nonce: nonce, + lock: lock, time: time, location: location, coinbase: coinbase, @@ -990,6 +1003,7 @@ func CopyWorkObjectHeader(wh *WorkObjectHeader) *WorkObjectHeader { cpy.SetTime(wh.Time()) cpy.SetPrimeTerminusNumber(wh.primeTerminusNumber) cpy.SetCoinbase(wh.Coinbase()) + cpy.SetLock(wh.Lock()) return &cpy } @@ -1006,6 +1020,7 @@ func (wh *WorkObjectHeader) RPCMarshalWorkObjectHeader() map[string]interface{} "timestamp": hexutil.Uint64(wh.Time()), "mixHash": wh.MixHash(), "coinbase": wh.Coinbase(), + "lock": hexutil.Uint64(wh.Lock()), } return result } @@ -1048,6 +1063,7 @@ func (wh *WorkObjectHeader) SealEncode() *ProtoWorkObjectHeader { location := wh.Location().ProtoEncode() time := wh.Time() coinbase := common.ProtoAddress{Value: wh.Coinbase().Bytes()} + lock := uint32(wh.Lock()) return &ProtoWorkObjectHeader{ HeaderHash: &hash, @@ -1057,6 +1073,7 @@ func (wh *WorkObjectHeader) SealEncode() *ProtoWorkObjectHeader { TxHash: &txHash, PrimeTerminusNumber: primeTerminusNumber, Location: location, + Lock: &lock, Coinbase: &coinbase, Time: &time, } @@ -1073,6 +1090,7 @@ func (wh *WorkObjectHeader) ProtoEncode() (*ProtoWorkObjectHeader, error) { nonce := wh.Nonce().Uint64() mixHash := common.ProtoHash{Value: wh.MixHash().Bytes()} coinbase := common.ProtoAddress{Value: wh.Coinbase().Bytes()} + lock := uint32(wh.Lock()) return &ProtoWorkObjectHeader{ HeaderHash: &hash, @@ -1083,6 +1101,7 @@ func (wh *WorkObjectHeader) ProtoEncode() (*ProtoWorkObjectHeader, error) { TxHash: &txHash, Location: location, Nonce: &nonce, + Lock: &lock, MixHash: &mixHash, Time: &wh.time, Coinbase: &coinbase, @@ -1101,6 +1120,7 @@ func (wh *WorkObjectHeader) ProtoDecode(data *ProtoWorkObjectHeader, location co wh.SetPrimeTerminusNumber(new(big.Int).SetBytes(data.GetPrimeTerminusNumber())) wh.SetTxHash(common.BytesToHash(data.GetTxHash().Value)) wh.SetNonce(uint64ToByteArr(data.GetNonce())) + wh.SetLock(uint8(data.GetLock())) wh.SetLocation(data.GetLocation().GetValue()) wh.SetMixHash(common.BytesToHash(data.GetMixHash().Value)) wh.SetTime(data.GetTime()) diff --git a/core/types/wo_test.go b/core/types/wo_test.go index 3c33fd67c7..f568dc81da 100644 --- a/core/types/wo_test.go +++ b/core/types/wo_test.go @@ -22,6 +22,7 @@ func woTestData() (*WorkObject, common.Hash) { coinbase: common.HexToAddress("0x123456789abcdef0123456789abcdef0123456789", common.Location{0, 0}), time: uint64(1), nonce: EncodeNonce(uint64(1)), + lock: 1, }, } return wo, wo.Hash() diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 123c328e46..d51aff203c 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -30,6 +30,7 @@ import ( "github.com/dominant-strategies/go-quai/crypto" "github.com/dominant-strategies/go-quai/crypto/blake2b" "github.com/dominant-strategies/go-quai/crypto/bn256" + "github.com/dominant-strategies/go-quai/log" "github.com/dominant-strategies/go-quai/params" //lint:ignore SA1019 Needed for precompile @@ -528,7 +529,7 @@ func RedeemQuai(blockContext BlockContext, statedb StateDB, sender common.Addres return gasUsed, stateGas, errors.New("account has locked too many times, overflows uint64") } - for i := int64(0); i < math.MaxInt64; i++ { // TODO: We should decide on a reasonable limit + for i := int64(0); i < math.MaxInt64; i++ { // Ensure we have enough gas to complete this step entirely requiredGas := coldSloadCost + sstoreResetGas + coldSloadCost + sstoreResetGas + sstoreResetGas + params.CallValueTransferGas if gas.Gas() < requiredGas { @@ -556,6 +557,7 @@ func RedeemQuai(blockContext BlockContext, statedb StateDB, sender common.Addres lock := new(big.Int).SetBytes(lockHash[:]) if lock.Cmp(blockHeight) > 0 { // lock not ready yet. Lockups are stored in FIFO order, so we don't have to go through the rest + // TODO: It's possible that coinbase lockups are stored with differing lock heights, so we may need to check all locks return gasUsed, stateGas, fmt.Errorf("lockup not ready yet, lock height: %d, current block height: %d", lock, blockHeight) } // Set the lock to zero @@ -574,7 +576,7 @@ func RedeemQuai(blockContext BlockContext, statedb StateDB, sender common.Addres return gasUsed, stateGas, ErrOutOfGas } if (balanceHash == common.Hash{}) { - // If locked balance after covnert is zero, either it doesn't exist or something is broken + // If locked balance after convert is zero, either it doesn't exist or something is broken return gasUsed, stateGas, errors.New("balance not found") } // Set the locked balance to zero @@ -586,7 +588,7 @@ func RedeemQuai(blockContext BlockContext, statedb StateDB, sender common.Addres } // Increment the current lock counter currentLockNumber.Add(currentLockNumber, big1) - currentLockHash = common.BytesToHash(binary.BigEndian.AppendUint64([]byte{}, currentLockNumber.Uint64())) + currentLockHash = common.BytesToHash(currentLockNumber.Bytes()) statedb.SetState(internalContractAddress, sender.Hash(), currentLockHash) gasUsed += sstoreResetGas stateGas += sstoreResetGas @@ -611,7 +613,7 @@ func RedeemQuai(blockContext BlockContext, statedb StateDB, sender common.Addres } // AddNewLock adds a new locked balance to the lockup contract -func AddNewLock(blockContext BlockContext, statedb StateDB, toAddr common.Address, gas *types.GasPool, lock *big.Int, balance *big.Int, lockupContractAddress common.Address) (uint64, uint64, error) { +func AddNewLock(stateSize *big.Int, statedb StateDB, toAddr common.Address, gas *types.GasPool, lock *big.Int, balance *big.Int, lockupContractAddress common.Address) (uint64, uint64, error) { internalContractAddress, err := lockupContractAddress.InternalAndQuaiAddress() if err != nil { return 0, 0, err @@ -619,9 +621,11 @@ func AddNewLock(blockContext BlockContext, statedb StateDB, toAddr common.Addres if len(lock.Bytes()) > common.HashLength || len(balance.Bytes()) > common.HashLength { return 0, 0, errors.New("lock or balance is too large") } - stateSize := blockContext.QuaiStateSize contractSize := statedb.GetSize(internalContractAddress) - currentLockHash := statedb.GetState(internalContractAddress, common.BytesToHash(toAddr.Bytes())) + senderHash := toAddr.Hash() + senderHash[0] = 1 // Set the first byte to 1 for the latest lock pointer + // The latest lock hash points to the latest lock stored for the sender + latestLockHash := statedb.GetState(internalContractAddress, senderHash) coldSloadCost := params.ColdSloadCost(stateSize, contractSize) sstoreSetGas := params.SstoreSetGas(stateSize, contractSize) gasUsed := coldSloadCost @@ -630,27 +634,75 @@ func AddNewLock(blockContext BlockContext, statedb StateDB, toAddr common.Addres // This contract does not revert. If the caller runs out of gas, we just stop return gasUsed, stateGas, ErrOutOfGas } - if (currentLockHash == common.Hash{}) { - // No lock found, create a new one - statedb.SetState(internalContractAddress, common.BytesToHash(toAddr.Bytes()), common.BytesToHash([]byte{1})) + // Ensure we have enough gas to complete this step entirely + requiredGas := coldSloadCost + sstoreSetGas + sstoreSetGas + sstoreSetGas + sstoreSetGas + if gas.Gas() < requiredGas { + return gasUsed, stateGas, fmt.Errorf("insufficient gas to add new lock, required %d, got %d", requiredGas, gas.Gas()) + } + if (latestLockHash == common.Hash{}) { + // No lock found, create a new current lock pointer + statedb.SetState(internalContractAddress, toAddr.Hash(), common.BytesToHash([]byte{1})) gasUsed += sstoreSetGas stateGas += sstoreSetGas - currentLockHash = common.BytesToHash([]byte{1}) + if gas.SubGas(sstoreSetGas) != nil { + return gasUsed, stateGas, ErrOutOfGas + } + // Set latest lock pointer also to 1 + latestLockHash = common.BytesToHash([]byte{1}) } - currentLockNumber := new(big.Int).SetBytes(currentLockHash[:]) - if !currentLockNumber.IsUint64() { + latestLockNumber := new(big.Int).SetBytes(latestLockHash[:]) + if !latestLockNumber.IsUint64() { return gasUsed, stateGas, errors.New("account has locked too many times, overflows uint64") } - for i := int64(0); i < math.MaxInt64; i++ { // TODO: We should decide on a reasonable limit - // Ensure we have enough gas to complete this step entirely - requiredGas := coldSloadCost + sstoreSetGas + sstoreSetGas + key := toAddr.Bytes() + // Append latest lock to the key + key = binary.BigEndian.AppendUint64(key, latestLockNumber.Uint64()) + key = append(key, byte(1)) // Set the 29th byte of the key to 1 for lockup + if len(key) > common.HashLength { + return gasUsed, stateGas, errors.New("lockup key is too long, math is broken") + } + lockHash := statedb.GetState(internalContractAddress, common.BytesToHash(key)) + gasUsed += coldSloadCost + stateGas += coldSloadCost + if gas.SubGas(coldSloadCost) != nil { + // This contract does not revert. If the caller runs out of gas, we just stop + return gasUsed, stateGas, ErrOutOfGas + } + if (lockHash == common.Hash{}) { + // Lock doesn't exist, so add the new one here + statedb.SetState(internalContractAddress, common.BytesToHash(key), common.BytesToHash(lock.Bytes())) + gasUsed += sstoreSetGas + stateGas += sstoreSetGas + if gas.SubGas(sstoreSetGas) != nil { + return gasUsed, stateGas, ErrOutOfGas + } + key[28] = 0 // Set the 29th byte of the key to 0 for balance + statedb.SetState(internalContractAddress, common.BytesToHash(key), common.BytesToHash(balance.Bytes())) + gasUsed += sstoreSetGas + stateGas += sstoreSetGas + if gas.SubGas(sstoreSetGas) != nil { + return gasUsed, stateGas, ErrOutOfGas + } + // Increment the latest lock counter + latestLockNumber.Add(latestLockNumber, big1) + statedb.SetState(internalContractAddress, senderHash, common.BytesToHash(latestLockNumber.Bytes())) + gasUsed += sstoreSetGas + stateGas += sstoreSetGas + if gas.SubGas(sstoreSetGas) != nil { + return gasUsed, stateGas, ErrOutOfGas + } + // Addition of new lock successful + return gasUsed, stateGas, nil + } else { // This can only in the event of a bug (the latest lock number is wrong) if gas.Gas() < requiredGas { return gasUsed, stateGas, fmt.Errorf("insufficient gas to add new lock, required %d, got %d", requiredGas, gas.Gas()) } + log.Global.Errorf("latest lock number is wrong for address %s: %s %s", toAddr.String(), senderHash, latestLockHash.String()) + latestLockNumber.Add(latestLockNumber, big1) key := toAddr.Bytes() // Append current lock to the key - key = binary.BigEndian.AppendUint64(key, currentLockNumber.Uint64()) + key = binary.BigEndian.AppendUint64(key, latestLockNumber.Uint64()) key = append(key, byte(1)) // Set the 29th byte of the key to 1 for lockup if len(key) > common.HashLength { return gasUsed, stateGas, errors.New("lockup key is too long, math is broken") @@ -677,11 +729,13 @@ func AddNewLock(blockContext BlockContext, statedb StateDB, toAddr common.Addres if gas.SubGas(sstoreSetGas) != nil { return gasUsed, stateGas, ErrOutOfGas } + // Increment the latest lock counter + latestLockNumber.Add(latestLockNumber, big1) + statedb.SetState(internalContractAddress, senderHash, common.BytesToHash(latestLockNumber.Bytes())) // Addition of new lock successful return gasUsed, stateGas, nil + } else { + return gasUsed, stateGas, errors.New("latest lock number is wrong, math is broken") } - // Lock exists, increment the current lock counter (but don't store it) - currentLockNumber.Add(currentLockNumber, big1) } - return gasUsed, stateGas, errors.New("account has locked too many times, overflows int64") } diff --git a/core/vm/evm.go b/core/vm/evm.go index 01aff7472a..ba0be7e673 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -216,7 +216,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas if err := evm.Context.Transfer(evm.StateDB, caller.Address(), lockupContractAddress, value); err != nil { return nil, gas, stateGas, err } - gasUsed, stateGasUsed, err := AddNewLock(evm.Context, evm.StateDB, addr, new(types.GasPool).AddGas(gas), lock, evm.Context.BlockNumber, lockupContractAddress) + gasUsed, stateGasUsed, err := AddNewLock(evm.Context.QuaiStateSize, evm.StateDB, addr, new(types.GasPool).AddGas(gas), lock, evm.Context.BlockNumber, lockupContractAddress) if gas > gasUsed { gas = gas - gasUsed } else { diff --git a/core/worker.go b/core/worker.go index da8a2b2060..2f71d210de 100644 --- a/core/worker.go +++ b/core/worker.go @@ -3,6 +3,7 @@ package core import ( "errors" "fmt" + "math" "math/big" "runtime/debug" "sort" @@ -20,6 +21,7 @@ import ( "github.com/dominant-strategies/go-quai/core/rawdb" "github.com/dominant-strategies/go-quai/core/state" "github.com/dominant-strategies/go-quai/core/types" + "github.com/dominant-strategies/go-quai/core/vm" "github.com/dominant-strategies/go-quai/ethdb" "github.com/dominant-strategies/go-quai/event" "github.com/dominant-strategies/go-quai/log" @@ -54,6 +56,8 @@ const ( chainSideChanSize = 10 c_uncleCacheSize = 100 + + defaultCoinbaseLockup = 1 ) // environment is the worker's current environment and holds all @@ -61,27 +65,29 @@ const ( type environment struct { signer types.Signer - state *state.StateDB // apply state changes here - ancestors mapset.Set // ancestor set (used for checking uncle parent validity) - family mapset.Set // family set (used for checking uncle invalidity) - tcount int // tx count in cycle - gasPool *types.GasPool // available gas used to pack transactions - coinbase common.Address - etxRLimit int // Remaining number of cross-region ETXs that can be included - etxPLimit int // Remaining number of cross-prime ETXs that can be included - parentOrder *int - wo *types.WorkObject - txs []*types.Transaction - etxs []*types.Transaction - utxoFees *big.Int - quaiFees *big.Int - subManifest types.BlockManifest - receipts []*types.Receipt - uncleMu sync.RWMutex - uncles map[common.Hash]*types.WorkObjectHeader - utxosCreate []common.Hash - utxosDelete []common.Hash - deletedUtxos map[common.Hash]struct{} + state *state.StateDB // apply state changes here + ancestors mapset.Set // ancestor set (used for checking uncle parent validity) + family mapset.Set // family set (used for checking uncle invalidity) + tcount int // tx count in cycle + gasPool *types.GasPool // available gas used to pack transactions + coinbase common.Address + etxRLimit int // Remaining number of cross-region ETXs that can be included + etxPLimit int // Remaining number of cross-prime ETXs that can be included + parentOrder *int + wo *types.WorkObject + txs []*types.Transaction + etxs []*types.Transaction + utxoFees *big.Int + quaiFees *big.Int + subManifest types.BlockManifest + receipts []*types.Receipt + uncleMu sync.RWMutex + uncles map[common.Hash]*types.WorkObjectHeader + utxosCreate []common.Hash + utxosDelete []common.Hash + parentStateSize *big.Int + quaiCoinbaseEtxs map[[21]byte]*big.Int + deletedUtxos map[common.Hash]struct{} } // unclelist returns the contained uncles as the list format. @@ -512,7 +518,9 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool) (*typ w.coinbase = common.Zero } coinbase = w.coinbase // Use the preset address as the fee recipient - + if _, err := coinbase.InternalAddress(); nodeCtx == common.ZONE_CTX && err != nil { + return nil, fmt.Errorf("invalid coinbase address %v: %v", coinbase, err) + } work, err := w.prepareWork(&generateParams{ timestamp: uint64(timestamp), coinbase: coinbase, @@ -541,7 +549,10 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool) (*typ for i, uncle := range uncles { reward := misc.CalculateReward(uncle) uncleCoinbase := uncle.Coinbase() - work.etxs = append(work.etxs, types.NewTx(&types.ExternalTx{To: &uncleCoinbase, Value: reward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: uint16(i) + 1, Sender: uncleCoinbase})) + if _, err := uncleCoinbase.InternalAddress(); err != nil { + return nil, fmt.Errorf("invalid workshare coinbase address %v: %v", uncleCoinbase, err) + } + work.etxs = append(work.etxs, types.NewTx(&types.ExternalTx{To: &uncleCoinbase, Value: reward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: uint16(i) + 1, Sender: uncleCoinbase, Data: []byte{uncle.Lock()}})) } // Fill pending transactions from the txpool @@ -578,13 +589,13 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool) (*typ coinbaseReward := misc.CalculateReward(work.wo.WorkObjectHeader()) blockFees := new(big.Int).Add(work.utxoFees, misc.QuaiToQi(primeTerminus.WorkObjectHeader(), work.quaiFees)) blockReward := new(big.Int).Add(coinbaseReward, blockFees) - coinbaseEtx := types.NewTx(&types.ExternalTx{To: &coinbase, Value: blockReward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: 0, Sender: coinbase}) + coinbaseEtx := types.NewTx(&types.ExternalTx{To: &coinbase, Value: blockReward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: 0, Sender: coinbase, Data: []byte{work.wo.Lock()}}) work.etxs[0] = coinbaseEtx } else if coinbase.IsInQuaiLedgerScope() { coinbaseReward := misc.CalculateReward(work.wo.WorkObjectHeader()) blockFees := new(big.Int).Add(work.quaiFees, misc.QiToQuai(primeTerminus.WorkObjectHeader(), work.utxoFees)) blockReward := new(big.Int).Add(coinbaseReward, blockFees) - coinbaseEtx := types.NewTx(&types.ExternalTx{To: &coinbase, Value: blockReward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: 0, Sender: coinbase}) + coinbaseEtx := types.NewTx(&types.ExternalTx{To: &coinbase, Value: blockReward, IsCoinbase: true, OriginatingTxHash: origin, ETXIndex: 0, Sender: coinbase, Data: []byte{work.wo.Lock()}}) work.etxs[0] = coinbaseEtx } } @@ -674,16 +685,18 @@ func (w *worker) makeEnv(parent *types.WorkObject, proposedWo *types.WorkObject, } // Note the passed coinbase may be different with header.Coinbase. env := &environment{ - signer: types.MakeSigner(w.chainConfig, proposedWo.Number(w.hc.NodeCtx())), - state: state, - coinbase: coinbase, - ancestors: mapset.NewSet(), - family: mapset.NewSet(), - wo: proposedWo, - uncles: make(map[common.Hash]*types.WorkObjectHeader), - etxRLimit: etxRLimit, - etxPLimit: etxPLimit, - deletedUtxos: make(map[common.Hash]struct{}), + signer: types.MakeSigner(w.chainConfig, proposedWo.Number(w.hc.NodeCtx())), + state: state, + coinbase: coinbase, + ancestors: mapset.NewSet(), + family: mapset.NewSet(), + wo: proposedWo, + uncles: make(map[common.Hash]*types.WorkObjectHeader), + etxRLimit: etxRLimit, + etxPLimit: etxPLimit, + parentStateSize: quaiStateSize, + quaiCoinbaseEtxs: make(map[[21]byte]*big.Int), + deletedUtxos: make(map[common.Hash]struct{}), } // Keep track of transactions which return errors so they can be removed env.tcount = 0 @@ -740,12 +753,22 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t // 3) do not produce any receipts/logs // 4) etx emit threshold numbers if types.IsCoinBaseTx(tx) { - iAddr, err := tx.To().InternalAddress() - if err != nil { - return nil, false, errors.New("coinbase address is not in the chain scope") + if tx.To() == nil { + return nil, false, fmt.Errorf("coinbase tx %x has no recipient", tx.Hash()) + } + if len(tx.Data()) == 0 { + return nil, false, fmt.Errorf("coinbase tx %x has no lockup data", tx.Hash()) } + if _, err := tx.To().InternalAddress(); err != nil { + return nil, false, fmt.Errorf("invalid coinbase address %v: %v", tx.To(), err) + } + lockupByte := tx.Data()[0] if tx.To().IsInQiLedgerScope() { - value := tx.Value() + lockup := new(big.Int).SetUint64(params.LockupByteToBlockDepth[lockupByte]) + if lockup.Uint64() < params.ConversionLockPeriod { + return nil, false, fmt.Errorf("coinbase lockup period is less than the minimum lockup period of %d blocks", params.ConversionLockPeriod) + } + value := params.CalculateCoinbaseValueWithLockup(tx.Value(), lockupByte) denominations := misc.FindMinDenominations(value) outputIndex := uint16(0) // Iterate over the denominations in descending order @@ -760,14 +783,22 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t break } // the ETX hash is guaranteed to be unique - utxoHash := types.UTXOHash(tx.Hash(), outputIndex, types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), env.wo.Number(w.hc.NodeCtx())))) + utxoHash := types.UTXOHash(tx.Hash(), outputIndex, types.NewUtxoEntry(types.NewTxOut(uint8(denomination), tx.To().Bytes(), lockup))) env.utxosCreate = append(env.utxosCreate, utxoHash) outputIndex++ } } } else if tx.To().IsInQuaiLedgerScope() { - // This includes the value and the fees - env.state.AddBalance(iAddr, tx.Value()) + // Combine similar lockups (to address and lockup period) into a single lockup entry + coinbaseAddrWithLockup := [21]byte(append(tx.To().Bytes(), lockupByte)) + if val, ok := env.quaiCoinbaseEtxs[coinbaseAddrWithLockup]; ok { + // Combine the values of the coinbase transactions + val.Add(val, tx.Value()) + env.quaiCoinbaseEtxs[coinbaseAddrWithLockup] = val + } else { + // Add the new coinbase transaction to the map + env.quaiCoinbaseEtxs[coinbaseAddrWithLockup] = tx.Value() // this creates a new *big.Int + } } env.txs = append(env.txs, tx) return []*types.Log{}, false, nil @@ -776,7 +807,7 @@ func (w *worker) commitTransaction(env *environment, parent *types.WorkObject, t gasUsed := env.wo.GasUsed() if tx.ETXSender().Location().Equal(*tx.To().Location()) { // Quai->Qi conversion txGas := tx.Gas() - lock := new(big.Int).Add(env.wo.Number(w.hc.NodeCtx()), big.NewInt(params.ConversionLockPeriod)) + lock := new(big.Int).Add(env.wo.Number(w.hc.NodeCtx()), new(big.Int).SetUint64(params.ConversionLockPeriod)) if env.parentOrder == nil { return nil, false, errors.New("parent order not set") } @@ -1035,6 +1066,21 @@ func (w *worker) commitTransactions(env *environment, parent *types.WorkObject, txs.Shift(from.Bytes20(), false) } } + // Process Quai coinbase lockups (push all of the same coinbases to a singe lockup for state storage efficiency) + lockupContractAddress := vm.LockupContractAddresses[[2]byte{w.chainConfig.Location[0], w.chainConfig.Location[1]}] + for addressWithLockup, value := range env.quaiCoinbaseEtxs { + addr := common.BytesToAddress(addressWithLockup[:20], w.chainConfig.Location) + lockupByte := addressWithLockup[20] + lockup := new(big.Int).SetUint64(params.LockupByteToBlockDepth[lockupByte]) + if lockup.Uint64() < params.ConversionLockPeriod { + return fmt.Errorf("coinbase lockup period is less than the minimum lockup period of %d blocks", params.ConversionLockPeriod) + } + value := params.CalculateCoinbaseValueWithLockup(value, lockupByte) + _, _, err := vm.AddNewLock(env.parentStateSize, env.state, addr, new(types.GasPool).AddGas(math.MaxUint64), lockup, value, lockupContractAddress) + if err != nil { + return err + } + } if len(qiTxsToRemove) > 0 { w.txPool.AsyncRemoveQiTxs(qiTxsToRemove) // non-blocking } @@ -1085,6 +1131,7 @@ func (w *worker) prepareWork(genParams *generateParams, wo *types.WorkObject) (* // Construct the sealing block header, set the extra field if it's allowed num := parent.Number(nodeCtx) newWo := types.EmptyWorkObject(nodeCtx) + newWo.WorkObjectHeader().SetLock(defaultCoinbaseLockup) newWo.SetParentHash(wo.Hash(), nodeCtx) if w.hc.IsGenesisHash(parent.Hash()) { newWo.SetNumber(big.NewInt(1), nodeCtx) @@ -1248,7 +1295,7 @@ func (w *worker) prepareWork(genParams *generateParams, wo *types.WorkObject) (* 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(), newWo.WorkObjectHeader().PrimeTerminusNumber(), newWo.TxHash(), newWo.Nonce(), newWo.Time(), newWo.Location(), newWo.Coinbase()) + proposedWoHeader := types.NewWorkObjectHeader(newWo.Hash(), newWo.ParentHash(nodeCtx), newWo.Number(nodeCtx), newWo.Difficulty(), newWo.WorkObjectHeader().PrimeTerminusNumber(), newWo.TxHash(), newWo.Nonce(), newWo.Lock(), newWo.Time(), newWo.Location(), newWo.Coinbase()) proposedWoBody := types.NewWoBody(newWo.Header(), nil, nil, nil, nil, nil) proposedWo := types.NewWorkObject(proposedWoHeader, proposedWoBody, nil) env, err := w.makeEnv(parent, proposedWo, w.coinbase) @@ -1298,7 +1345,7 @@ func (w *worker) prepareWork(genParams *generateParams, wo *types.WorkObject) (* } return env, nil } else { - proposedWoHeader := types.NewWorkObjectHeader(newWo.Hash(), newWo.ParentHash(nodeCtx), newWo.Number(nodeCtx), newWo.Difficulty(), newWo.WorkObjectHeader().PrimeTerminusNumber(), types.EmptyRootHash, newWo.Nonce(), newWo.Time(), newWo.Location(), newWo.Coinbase()) + proposedWoHeader := types.NewWorkObjectHeader(newWo.Hash(), newWo.ParentHash(nodeCtx), newWo.Number(nodeCtx), newWo.Difficulty(), newWo.WorkObjectHeader().PrimeTerminusNumber(), types.EmptyRootHash, newWo.Nonce(), newWo.Lock(), newWo.Time(), newWo.Location(), newWo.Coinbase()) proposedWoBody := types.NewWoBody(newWo.Header(), nil, nil, nil, nil, nil) proposedWo := types.NewWorkObject(proposedWoHeader, proposedWoBody, nil) return &environment{wo: proposedWo}, nil diff --git a/p2p/node/peerManager/peerdb/peer_info.pb.go b/p2p/node/peerManager/peerdb/peer_info.pb.go index c7c6c6ccf2..ca1882ad1f 100644 --- a/p2p/node/peerManager/peerdb/peer_info.pb.go +++ b/p2p/node/peerManager/peerdb/peer_info.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.28.1 +// protoc v5.28.2 // source: p2p/node/peerManager/peerdb/peer_info.proto package peerdb diff --git a/p2p/pb/quai_messages.pb.go b/p2p/pb/quai_messages.pb.go index d09c5aa20a..a1fc057b18 100644 --- a/p2p/pb/quai_messages.pb.go +++ b/p2p/pb/quai_messages.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v5.28.1 +// protoc v5.28.2 // source: p2p/pb/quai_messages.proto package pb diff --git a/params/config.go b/params/config.go index a726059c04..395695b33c 100644 --- a/params/config.go +++ b/params/config.go @@ -26,18 +26,18 @@ import ( // Genesis hashes to enforce below configs on. var ( // Progpow GenesisHashes - ProgpowColosseumGenesisHash = common.HexToHash("0x079e89a92bbd044ee6d981d0644c9da1dc960e72d90df212c77e8b9cd12f9ecd") - ProgpowGardenGenesisHash = common.HexToHash("0xa4f23733a64776e5d6cd4a37e6ffdfd3ac6b078ec28d03fd8120d48a008b7b4b") - ProgpowOrchardGenesisHash = common.HexToHash("0xfa9092f9095c4efd4c51c72467d381162f565930f31a9ff9ae79a3af20c61f7d") - ProgpowLighthouseGenesisHash = common.HexToHash("0x6a5e86275011865c578343aeecc9f8e789109d0158a2840c9a089baa1f340415") - ProgpowLocalGenesisHash = common.HexToHash("0x901999d492a4aa4fe5ff4a149a06a0c8e3a47c042377df1ed44f05ededcd82ef") + ProgpowColosseumGenesisHash = common.HexToHash("0x592d5fbe87d36110246844bdc3227ecba5cc755601a0192a45f7bd3eebe7e053") + ProgpowGardenGenesisHash = common.HexToHash("0x4ff2dbf6d8a625661104728dfaa9ff6f00e6f3c44b6fdd9da3a534b77d517074") + ProgpowOrchardGenesisHash = common.HexToHash("0x57668da2ac7648c73e7a50aa3d3532eeb645f8de2ee30bab2b0a240ff06f669a") + ProgpowLighthouseGenesisHash = common.HexToHash("0x33ecb8d3b753ce0b233082febddf80d1ecf0bcc9bbc69666a6337deeace87c77") + ProgpowLocalGenesisHash = common.HexToHash("0x560e76288c5e9191e54be98be8177ed8ef59ac6f6b9d1c2bb5240880ca639e10") // Blake3GenesisHashes - Blake3PowColosseumGenesisHash = common.HexToHash("0x9d5a5146ba57f1230118bddc23e99bcc193c780fc3766d58d9e14f096481c215") - Blake3PowGardenGenesisHash = common.HexToHash("0x4c7611e9684bd82f1e33ad7712fbdc05b6f355fd3df2a0d0b18f9013e905cabd") - Blake3PowOrchardGenesisHash = common.HexToHash("0xef4f268a48658f05a932c5c01e24847626953a5cedabe4f8ca9a694ea24931ec") - Blake3PowLighthouseGenesisHash = common.HexToHash("0xef4f268a48658f05a932c5c01e24847626953a5cedabe4f8ca9a694ea24931ec") - Blake3PowLocalGenesisHash = common.HexToHash("0x4c7611e9684bd82f1e33ad7712fbdc05b6f355fd3df2a0d0b18f9013e905cabd") + Blake3PowColosseumGenesisHash = common.HexToHash("0x4f2f67806dd70f0ae8957b6f8022af14deabc0fa869edb538f5d18dc5aec88d0") + Blake3PowGardenGenesisHash = common.HexToHash("0xac77b1bff97c7169f2c51fcce147cd978d981c0234edc0cd8e73d16942f9ea6c") + Blake3PowOrchardGenesisHash = common.HexToHash("0x1d2a4582ff2134d82a735c06e3e264ecd357dedcff5dfab0da8b7f8f0b198317") + Blake3PowLighthouseGenesisHash = common.HexToHash("0x1d2a4582ff2134d82a735c06e3e264ecd357dedcff5dfab0da8b7f8f0b198317") + Blake3PowLocalGenesisHash = common.HexToHash("0xac77b1bff97c7169f2c51fcce147cd978d981c0234edc0cd8e73d16942f9ea6c") ) // Different Network names diff --git a/params/protocol_params.go b/params/protocol_params.go index eab6cc3e62..3e405407af 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -150,9 +150,9 @@ const ( // infrastructure, if needed, to account for the upcoming network change. TREE_EXPANSION_WAIT_COUNT = 1024 - ConversionLockPeriod int64 = 10 // The number of zone blocks that a conversion output is locked for - MinQiConversionDenomination = 1 - ConversionConfirmationContext = common.PRIME_CTX // A conversion requires a single coincident Dom confirmation + ConversionLockPeriod uint64 = 10 // The number of zone blocks that a conversion output is locked for + MinQiConversionDenomination = 1 + ConversionConfirmationContext = common.PRIME_CTX // A conversion requires a single coincident Dom confirmation ) var ( @@ -179,8 +179,23 @@ var ( MaxWorkShareCount = 16 WorkSharesThresholdDiff = 3 // 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 + LockupByteToBlockDepth = make(map[uint8]uint64) + LockupByteToRewardsRatio = make(map[uint8]*big.Int) ) +func init() { + LockupByteToBlockDepth[0] = ConversionLockPeriod // minimum lockup period + LockupByteToBlockDepth[1] = 720 // 2 hours + LockupByteToBlockDepth[2] = 1440 // 4 hours + LockupByteToBlockDepth[3] = 2880 // 8 hours + LockupByteToBlockDepth[4] = 4320 // 12 hours + + LockupByteToRewardsRatio[1] = big.NewInt(7) // additional 14% + LockupByteToRewardsRatio[2] = big.NewInt(6) // additional 16% + LockupByteToRewardsRatio[3] = big.NewInt(5) // additional 20% + LockupByteToRewardsRatio[4] = big.NewInt(4) // additional 25% +} + // This is TimeFactor*TimeFactor*common.NumZonesInRegion*common.NumRegionsInPrime func PrimeEntropyTarget(expansionNum uint8) *big.Int { numRegions, numZones := common.GetHierarchySizeForExpansionNumber(expansionNum) @@ -246,3 +261,10 @@ func CalculateGasWithStateScaling(stateSize, contractSize *big.Int, baseRate uin // If we can assume that the gas price constants is correct for level 7 trie return (uint64(scalingFactor) * baseRate) / 7 } + +func CalculateCoinbaseValueWithLockup(value *big.Int, lockupByte uint8) *big.Int { + if lockupByte == 0 { + return value + } + return new(big.Int).Add(value, new(big.Int).Div(value, LockupByteToRewardsRatio[lockupByte])) +} diff --git a/quaiclient/quaiclient.go b/quaiclient/quaiclient.go index c7caf328ef..514adb518a 100644 --- a/quaiclient/quaiclient.go +++ b/quaiclient/quaiclient.go @@ -70,6 +70,7 @@ func DialContext(ctx context.Context, rawurl string, logger *log.Logger) (*Clien "attempts": attempts, "delay": delaySecs, "url": rawurl, + "err": err, }).Warn("Attempting to connect to go-quai node. Waiting and retrying...") time.Sleep(time.Duration(delaySecs) * time.Second)