Replace header finality point with pruning point and enforce finality rules on IBD with headers proof (#1823)

* Replace header finality point with pruning point

* Fix TestTransactionAcceptance

* Fix pruning candidate

* Store all past pruning points

* Pass pruning points on IBD

* Add blue score to block header

* Simplify ArePruningPointsInValidChain

* Fix static check errors

* Fix genesis

* Renames and text fixing

* Use ExpectedHeaderPruningPoint in block builder

* Fix TestCheckPruningPointViolation
This commit is contained in:
Ori Newman 2021-08-31 08:01:48 +03:00 committed by GitHub
parent 837dac68b5
commit d9bc94a2a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 3213 additions and 2384 deletions

View File

@ -38,9 +38,10 @@ func DomainBlockHeaderToBlockHeader(domainBlockHeader externalapi.BlockHeader) *
Timestamp: mstime.UnixMilliseconds(domainBlockHeader.TimeInMilliseconds()),
Bits: domainBlockHeader.Bits(),
Nonce: domainBlockHeader.Nonce(),
BlueScore: domainBlockHeader.BlueScore(),
DAAScore: domainBlockHeader.DAAScore(),
BlueWork: domainBlockHeader.BlueWork(),
FinalityPoint: domainBlockHeader.FinalityPoint(),
PruningPoint: domainBlockHeader.PruningPoint(),
}
}
@ -69,8 +70,9 @@ func BlockHeaderToDomainBlockHeader(blockHeader *MsgBlockHeader) externalapi.Blo
blockHeader.Bits,
blockHeader.Nonce,
blockHeader.DAAScore,
blockHeader.BlueScore,
blockHeader.BlueWork,
blockHeader.FinalityPoint,
blockHeader.PruningPoint,
)
}
@ -358,8 +360,9 @@ func DomainBlockToRPCBlock(block *externalapi.DomainBlock) *RPCBlock {
Bits: block.Header.Bits(),
Nonce: block.Header.Nonce(),
DAAScore: block.Header.DAAScore(),
BlueScore: block.Header.BlueScore(),
BlueWork: block.Header.BlueWork().Text(16),
FinalityPoint: block.Header.FinalityPoint().String(),
PruningPoint: block.Header.PruningPoint().String(),
}
transactions := make([]*RPCTransaction, len(block.Transactions))
for i, transaction := range block.Transactions {
@ -400,7 +403,7 @@ func RPCBlockToDomainBlock(block *RPCBlock) (*externalapi.DomainBlock, error) {
if !success {
return nil, errors.Errorf("failed to parse blue work: %s", block.Header.BlueWork)
}
finalityPoint, err := externalapi.NewDomainHashFromString(block.Header.FinalityPoint)
pruningPoint, err := externalapi.NewDomainHashFromString(block.Header.PruningPoint)
if err != nil {
return nil, err
}
@ -414,8 +417,9 @@ func RPCBlockToDomainBlock(block *RPCBlock) (*externalapi.DomainBlock, error) {
block.Header.Bits,
block.Header.Nonce,
block.Header.DAAScore,
block.Header.BlueScore,
blueWork,
finalityPoint)
pruningPoint)
transactions := make([]*externalapi.DomainTransaction, len(block.Transactions))
for i, transaction := range block.Transactions {
domainTransaction, err := RPCTransactionToDomainTransaction(transaction)

View File

@ -65,6 +65,7 @@ const (
CmdRequestBlockBlueWork
CmdIBDBlock
CmdRequestIBDBlocks
CmdPruningPoints
// rpc
CmdGetCurrentNetworkRequestMessage
@ -183,6 +184,7 @@ var ProtocolMessageCommandToString = map[MessageCommand]string{
CmdRequestBlockBlueWork: "RequestBlockBlueWork",
CmdIBDBlock: "IBDBlock",
CmdRequestIBDBlocks: "RequestIBDBlocks",
CmdPruningPoints: "PruningPoints",
}
// RPCMessageCommandToString maps all MessageCommands to their string representation

View File

@ -28,10 +28,11 @@ func TestBlock(t *testing.T) {
bits := blockOne.Header.Bits
nonce := blockOne.Header.Nonce
daaScore := blockOne.Header.DAAScore
blueScore := blockOne.Header.BlueScore
blueWork := blockOne.Header.BlueWork
finalityPoint := blockOne.Header.FinalityPoint
pruningPoint := blockOne.Header.PruningPoint
bh := NewBlockHeader(1, parents, hashMerkleRoot, acceptedIDMerkleRoot, utxoCommitment, bits, nonce,
daaScore, blueWork, finalityPoint)
daaScore, blueScore, blueWork, pruningPoint)
// Ensure the command is expected value.
wantCmd := MessageCommand(5)

View File

@ -63,11 +63,12 @@ type MsgBlockHeader struct {
// DAASCore is the DAA score of the block.
DAAScore uint64
BlueScore uint64
// BlueWork is the blue work of the block.
BlueWork *big.Int
// FinalityPoint is the highest finality point below the block.
FinalityPoint *externalapi.DomainHash
PruningPoint *externalapi.DomainHash
}
// BlockHash computes the block identifier hash for the given block header.
@ -79,8 +80,8 @@ func (h *MsgBlockHeader) BlockHash() *externalapi.DomainHash {
// block hash, hash merkle root, accepted ID merkle root, difficulty bits, and nonce used to generate the
// block with defaults or calclulated values for the remaining fields.
func NewBlockHeader(version uint16, parents []externalapi.BlockLevelParents, hashMerkleRoot *externalapi.DomainHash,
acceptedIDMerkleRoot *externalapi.DomainHash, utxoCommitment *externalapi.DomainHash, bits uint32, nonce uint64,
daaScore uint64, blueWork *big.Int, finalityPoint *externalapi.DomainHash) *MsgBlockHeader {
acceptedIDMerkleRoot *externalapi.DomainHash, utxoCommitment *externalapi.DomainHash, bits uint32, nonce,
daaScore, blueScore uint64, blueWork *big.Int, pruningPoint *externalapi.DomainHash) *MsgBlockHeader {
// Limit the timestamp to one millisecond precision since the protocol
// doesn't support better.
@ -94,7 +95,8 @@ func NewBlockHeader(version uint16, parents []externalapi.BlockLevelParents, has
Bits: bits,
Nonce: nonce,
DAAScore: daaScore,
BlueScore: blueScore,
BlueWork: blueWork,
FinalityPoint: finalityPoint,
PruningPoint: pruningPoint,
}
}

View File

@ -23,10 +23,11 @@ func TestBlockHeader(t *testing.T) {
acceptedIDMerkleRoot := exampleAcceptedIDMerkleRoot
bits := uint32(0x1d00ffff)
daaScore := uint64(123)
blueWork := big.NewInt(456)
finalityPoint := simnetGenesisHash
blueScore := uint64(456)
blueWork := big.NewInt(789)
pruningPoint := simnetGenesisHash
bh := NewBlockHeader(1, parents, merkleHash, acceptedIDMerkleRoot, exampleUTXOCommitment, bits, nonce,
daaScore, blueWork, finalityPoint)
daaScore, blueScore, blueWork, pruningPoint)
// Ensure we get the same data back out.
if !reflect.DeepEqual(bh.Parents, parents) {
@ -49,12 +50,16 @@ func TestBlockHeader(t *testing.T) {
t.Errorf("NewBlockHeader: wrong daaScore - got %v, want %v",
bh.DAAScore, daaScore)
}
if bh.BlueScore != blueScore {
t.Errorf("NewBlockHeader: wrong blueScore - got %v, want %v",
bh.BlueScore, blueScore)
}
if bh.BlueWork != blueWork {
t.Errorf("NewBlockHeader: wrong blueWork - got %v, want %v",
bh.BlueWork, blueWork)
}
if !bh.FinalityPoint.Equal(finalityPoint) {
t.Errorf("NewBlockHeader: wrong finalityHash - got %v, want %v",
bh.FinalityPoint, finalityPoint)
if !bh.PruningPoint.Equal(pruningPoint) {
t.Errorf("NewBlockHeader: wrong pruningPoint - got %v, want %v",
bh.PruningPoint, pruningPoint)
}
}

View File

@ -0,0 +1,20 @@
package appmessage
// MsgPruningPoints represents a kaspa PruningPoints message
type MsgPruningPoints struct {
baseMessage
Headers []*MsgBlockHeader
}
// Command returns the protocol command string for the message
func (msg *MsgPruningPoints) Command() MessageCommand {
return CmdPruningPoints
}
// NewMsgPruningPoints returns a new MsgPruningPoints.
func NewMsgPruningPoints(headers []*MsgBlockHeader) *MsgPruningPoints {
return &MsgPruningPoints{
Headers: headers,
}
}

View File

@ -78,8 +78,9 @@ type RPCBlockHeader struct {
Bits uint32
Nonce uint64
DAAScore uint64
BlueScore uint64
BlueWork string
FinalityPoint string
PruningPoint string
}
// RPCBlockLevelParents holds parent hashes for one block level

View File

@ -24,6 +24,22 @@ func HandlePruningPointAndItsAnticoneRequests(context PruningPointAndItsAnticone
}
log.Debugf("Got request for pruning point and its anticone from %s", peer)
pruningPointHeaders, err := context.Domain().Consensus().PruningPointHeaders()
if err != nil {
return err
}
msgPruningPointHeaders := make([]*appmessage.MsgBlockHeader, len(pruningPointHeaders))
for i, header := range pruningPointHeaders {
msgPruningPointHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(header)
}
err = outgoingRoute.Enqueue(appmessage.NewMsgPruningPoints(msgPruningPointHeaders))
if err != nil {
return err
}
blocks, err := context.Domain().Consensus().PruningPointAndItsAnticoneWithTrustedData()
if err != nil {
return err

View File

@ -16,7 +16,7 @@ func (flow *handleRelayInvsFlow) ibdWithHeadersProof(highHash *externalapi.Domai
return err
}
err = flow.downloadHeadersAndPruningUTXOSet(flow.Domain().StagingConsensus(), highHash)
err = flow.downloadHeadersAndPruningUTXOSet(highHash)
if err != nil {
if !flow.IsRecoverableError(err) {
return err
@ -93,13 +93,13 @@ func (flow *handleRelayInvsFlow) downloadHeadersProof() error {
return nil
}
func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(consensus externalapi.Consensus, highHash *externalapi.DomainHash) error {
func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash) error {
err := flow.downloadHeadersProof()
if err != nil {
return err
}
pruningPoint, err := flow.syncPruningPointAndItsAnticone(consensus)
pruningPoint, err := flow.syncPruningPointsAndPruningPointAnticone()
if err != nil {
return err
}
@ -110,7 +110,7 @@ func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(consensus exte
return protocolerrors.Errorf(true, "the genesis pruning point violates finality")
}
err = flow.syncPruningPointFutureHeaders(consensus, pruningPoint, highHash)
err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), pruningPoint, highHash)
if err != nil {
return err
}
@ -118,7 +118,7 @@ func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(consensus exte
log.Debugf("Blocks downloaded from peer %s", flow.peer)
log.Debugf("Syncing the current pruning point UTXO set")
syncedPruningPointUTXOSetSuccessfully, err := flow.syncPruningPointUTXOSet(consensus, pruningPoint)
syncedPruningPointUTXOSetSuccessfully, err := flow.syncPruningPointUTXOSet(flow.Domain().StagingConsensus(), pruningPoint)
if err != nil {
return err
}
@ -130,13 +130,19 @@ func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(consensus exte
return nil
}
func (flow *handleRelayInvsFlow) syncPruningPointAndItsAnticone(consensus externalapi.Consensus) (*externalapi.DomainHash, error) {
log.Infof("Downloading pruning point and its anticone from %s", flow.peer)
func (flow *handleRelayInvsFlow) syncPruningPointsAndPruningPointAnticone() (*externalapi.DomainHash, error) {
log.Infof("Downloading the past pruning point and the pruning point anticone from %s", flow.peer)
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointAndItsAnticone())
if err != nil {
return nil, err
}
err = flow.validateAndInsertPruningPoints()
if err != nil {
return nil, err
}
pruningPoint, done, err := flow.receiveBlockWithTrustedData()
if err != nil {
return nil, err
@ -146,7 +152,7 @@ func (flow *handleRelayInvsFlow) syncPruningPointAndItsAnticone(consensus extern
return nil, protocolerrors.Errorf(true, "got `done` message before receiving the pruning point")
}
err = flow.processBlockWithTrustedData(consensus, pruningPoint)
err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), pruningPoint)
if err != nil {
return nil, err
}
@ -161,7 +167,7 @@ func (flow *handleRelayInvsFlow) syncPruningPointAndItsAnticone(consensus extern
break
}
err = flow.processBlockWithTrustedData(consensus, blockWithTrustedData)
err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), blockWithTrustedData)
if err != nil {
return nil, err
}
@ -199,7 +205,54 @@ func (flow *handleRelayInvsFlow) receiveBlockWithTrustedData() (*appmessage.MsgB
}
}
func (flow *handleRelayInvsFlow) syncPruningPointUTXOSet(consensus externalapi.Consensus, pruningPoint *externalapi.DomainHash) (bool, error) {
func (flow *handleRelayInvsFlow) receivePruningPoints() (*appmessage.MsgPruningPoints, error) {
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
if err != nil {
return nil, err
}
msgPruningPoints, ok := message.(*appmessage.MsgPruningPoints)
if !ok {
return nil,
protocolerrors.Errorf(true, "received unexpected message type. "+
"expected: %s, got: %s", appmessage.CmdPruningPoints, message.Command())
}
return msgPruningPoints, nil
}
func (flow *handleRelayInvsFlow) validateAndInsertPruningPoints() error {
pruningPoints, err := flow.receivePruningPoints()
if err != nil {
return err
}
headers := make([]externalapi.BlockHeader, len(pruningPoints.Headers))
for i, header := range pruningPoints.Headers {
headers[i] = appmessage.BlockHeaderToDomainBlockHeader(header)
}
arePruningPointsViolatingFinality, err := flow.Domain().Consensus().ArePruningPointsViolatingFinality(headers)
if err != nil {
return err
}
if arePruningPointsViolatingFinality {
// TODO: Find a better way to deal with finality conflicts.
return protocolerrors.Errorf(false, "pruning points are violating finality")
}
err = flow.Domain().StagingConsensus().ImportPruningPoints(headers)
if err != nil {
return err
}
return nil
}
func (flow *handleRelayInvsFlow) syncPruningPointUTXOSet(consensus externalapi.Consensus,
pruningPoint *externalapi.DomainHash) (bool, error) {
log.Infof("Checking if the suggested pruning point %s is compatible to the node DAG", pruningPoint)
isValid, err := flow.Domain().StagingConsensus().IsValidPruningPoint(pruningPoint)
if err != nil {

View File

@ -172,7 +172,7 @@ func (m *Manager) registerBlockRelayFlows(router *routerpkg.Router, isStopping *
appmessage.CmdDoneHeaders, appmessage.CmdUnexpectedPruningPoint, appmessage.CmdPruningPointUTXOSetChunk,
appmessage.CmdBlockHeaders, appmessage.CmdIBDBlockLocatorHighestHash, appmessage.CmdBlockWithTrustedData,
appmessage.CmdDoneBlocksWithTrustedData, appmessage.CmdIBDBlockLocatorHighestHashNotFound,
appmessage.CmdDonePruningPointUTXOSetChunks, appmessage.CmdIBDBlock,
appmessage.CmdDonePruningPointUTXOSetChunks, appmessage.CmdIBDBlock, appmessage.CmdPruningPoints,
},
isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
return blockrelay.HandleRelayInvs(m.context, incomingRoute,

View File

@ -409,6 +409,35 @@ func (s *consensus) PruningPoint() (*externalapi.DomainHash, error) {
return s.pruningStore.PruningPoint(s.databaseContext, stagingArea)
}
func (s *consensus) PruningPointHeaders() ([]externalapi.BlockHeader, error) {
s.lock.Lock()
defer s.lock.Unlock()
stagingArea := model.NewStagingArea()
lastPruningPointIndex, err := s.pruningStore.CurrentPruningPointIndex(s.databaseContext, stagingArea)
if err != nil {
return nil, err
}
headers := make([]externalapi.BlockHeader, 0, lastPruningPointIndex)
for i := uint64(0); i <= lastPruningPointIndex; i++ {
pruningPoint, err := s.pruningStore.PruningPointByIndex(s.databaseContext, stagingArea, i)
if err != nil {
return nil, err
}
header, err := s.blockHeaderStore.BlockHeader(s.databaseContext, stagingArea, pruningPoint)
if err != nil {
return nil, err
}
headers = append(headers, header)
}
return headers, nil
}
func (s *consensus) ClearImportedPruningPointData() error {
s.lock.Lock()
defer s.lock.Unlock()
@ -568,6 +597,33 @@ func (s *consensus) IsValidPruningPoint(blockHash *externalapi.DomainHash) (bool
return s.pruningManager.IsValidPruningPoint(stagingArea, blockHash)
}
func (s *consensus) ArePruningPointsViolatingFinality(pruningPoints []externalapi.BlockHeader) (bool, error) {
s.lock.Lock()
defer s.lock.Unlock()
stagingArea := model.NewStagingArea()
return s.pruningManager.ArePruningPointsViolatingFinality(stagingArea, pruningPoints)
}
func (s *consensus) ImportPruningPoints(pruningPoints []externalapi.BlockHeader) error {
s.lock.Lock()
defer s.lock.Unlock()
stagingArea := model.NewStagingArea()
err := s.consensusStateManager.ImportPruningPoints(stagingArea, pruningPoints)
if err != nil {
return err
}
err = staging.CommitAllChanges(s.databaseContext, stagingArea)
if err != nil {
return err
}
return nil
}
func (s *consensus) GetVirtualSelectedParentChainFromBlock(blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, error) {
s.lock.Lock()
defer s.lock.Unlock()

View File

@ -20,8 +20,9 @@ func DomainBlockHeaderToDbBlockHeader(domainBlockHeader externalapi.BlockHeader)
Bits: domainBlockHeader.Bits(),
Nonce: domainBlockHeader.Nonce(),
DaaScore: domainBlockHeader.DAAScore(),
BlueScore: domainBlockHeader.BlueScore(),
BlueWork: domainBlockHeader.BlueWork().Bytes(),
FinalityPoint: DomainHashToDbHash(domainBlockHeader.FinalityPoint()),
PruningPoint: DomainHashToDbHash(domainBlockHeader.PruningPoint()),
}
}
@ -46,7 +47,8 @@ func DbBlockHeaderToDomainBlockHeader(dbBlockHeader *DbBlockHeader) (externalapi
if dbBlockHeader.Version > math.MaxUint16 {
return nil, errors.Errorf("Invalid header version - bigger then uint16")
}
finalityPoint, err := DbHashToDomainHash(dbBlockHeader.FinalityPoint)
pruningPoint, err := DbHashToDomainHash(dbBlockHeader.PruningPoint)
if err != nil {
return nil, err
}
@ -61,7 +63,8 @@ func DbBlockHeaderToDomainBlockHeader(dbBlockHeader *DbBlockHeader) (externalapi
dbBlockHeader.Bits,
dbBlockHeader.Nonce,
dbBlockHeader.DaaScore,
dbBlockHeader.BlueScore,
new(big.Int).SetBytes(dbBlockHeader.BlueWork),
finalityPoint,
pruningPoint,
), nil
}

View File

@ -1,12 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.25.0
// protoc v3.12.3
// source: dbobjects.proto
package serialization
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@ -20,6 +21,10 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type DbBlock struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -90,7 +95,8 @@ type DbBlockHeader struct {
Nonce uint64 `protobuf:"varint,8,opt,name=nonce,proto3" json:"nonce,omitempty"`
DaaScore uint64 `protobuf:"varint,9,opt,name=daaScore,proto3" json:"daaScore,omitempty"`
BlueWork []byte `protobuf:"bytes,10,opt,name=blueWork,proto3" json:"blueWork,omitempty"`
FinalityPoint *DbHash `protobuf:"bytes,11,opt,name=finalityPoint,proto3" json:"finalityPoint,omitempty"`
PruningPoint *DbHash `protobuf:"bytes,12,opt,name=pruningPoint,proto3" json:"pruningPoint,omitempty"`
BlueScore uint64 `protobuf:"varint,13,opt,name=blueScore,proto3" json:"blueScore,omitempty"`
}
func (x *DbBlockHeader) Reset() {
@ -195,13 +201,20 @@ func (x *DbBlockHeader) GetBlueWork() []byte {
return nil
}
func (x *DbBlockHeader) GetFinalityPoint() *DbHash {
func (x *DbBlockHeader) GetPruningPoint() *DbHash {
if x != nil {
return x.FinalityPoint
return x.PruningPoint
}
return nil
}
func (x *DbBlockHeader) GetBlueScore() uint64 {
if x != nil {
return x.BlueScore
}
return 0
}
type DbBlockLevelParents struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -1748,7 +1761,7 @@ var file_dbobjects_proto_rawDesc = []byte{
0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73,
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x22, 0xff, 0x03, 0x0a, 0x0d, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x69, 0x6f, 0x6e, 0x73, 0x22, 0x9b, 0x04, 0x0a, 0x0d, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x3c, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
@ -1776,224 +1789,226 @@ var file_dbobjects_proto_rawDesc = []byte{
0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20,
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a,
0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x12, 0x3b, 0x0a, 0x0d, 0x66, 0x69, 0x6e,
0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0d, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74,
0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x50, 0x0a, 0x13, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x39, 0x0a,
0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65,
0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x1c, 0x0a, 0x06, 0x44, 0x62, 0x48, 0x61,
0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0xad, 0x02, 0x0a, 0x0d, 0x44, 0x62, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x3c, 0x0a,
0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22,
0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x12, 0x39, 0x0a, 0x0c, 0x70, 0x72, 0x75,
0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50,
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72,
0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f,
0x72, 0x65, 0x22, 0x50, 0x0a, 0x13, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x65, 0x76,
0x65, 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0c, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61,
0x73, 0x68, 0x65, 0x73, 0x22, 0x1c, 0x0a, 0x06, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x12, 0x12,
0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61,
0x73, 0x68, 0x22, 0xad, 0x02, 0x0a, 0x0d, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39,
0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21,
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x70,
0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c,
0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6c,
0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65,
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62,
0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x52, 0x0c, 0x73, 0x75,
0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61,
0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07,
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70,
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xc1, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x45, 0x0a,
0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69,
0x6e, 0x74, 0x52, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73,
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a,
0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x69,
0x67, 0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a,
0x73, 0x69, 0x67, 0x4f, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x68, 0x0a, 0x0a, 0x44, 0x62,
0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52,
0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x14,
0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69,
0x6e, 0x64, 0x65, 0x78, 0x22, 0x37, 0x0a, 0x0f, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73,
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d,
0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x77, 0x0a,
0x13, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75,
0x74, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c,
0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x34, 0x0a, 0x0e, 0x44, 0x62, 0x53, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c,
0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x10,
0x44, 0x62, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61,
0x12, 0x56, 0x0a, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61,
0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44,
0x61, 0x74, 0x61, 0x52, 0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74,
0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb6, 0x01, 0x0a, 0x15, 0x44, 0x62, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61,
0x74, 0x61, 0x12, 0x68, 0x0a, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74,
0x61, 0x52, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63,
0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x09,
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73,
0x68, 0x22, 0xed, 0x01, 0x0a, 0x1b, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74,
0x61, 0x12, 0x3e, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03,
0x66, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65,
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x63, 0x63, 0x65, 0x70,
0x74, 0x65, 0x64, 0x12, 0x5c, 0x0a, 0x1b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69,
0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x52, 0x1b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65,
0x73, 0x22, 0x76, 0x0a, 0x10, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
0x65, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52,
0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x27, 0x0a, 0x0d, 0x44, 0x62, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74,
0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
0x75, 0x73, 0x22, 0xdb, 0x02, 0x0a, 0x13, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68,
0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c,
0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62,
0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65,
0x57, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65,
0x57, 0x6f, 0x72, 0x6b, 0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64,
0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73,
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48,
0x61, 0x73, 0x68, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42,
0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73,
0x68, 0x52, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73,
0x12, 0x39, 0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x6d,
0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x12, 0x53, 0x0a, 0x12, 0x62,
0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41,
0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x52, 0x12, 0x62, 0x6c,
0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73,
0x22, 0x6d, 0x0a, 0x14, 0x44, 0x62, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63,
0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65,
0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73,
0x68, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61,
0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22,
0x28, 0x0a, 0x0a, 0x44, 0x62, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x12, 0x1a, 0x0a,
0x08, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x08, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x22, 0x46, 0x0a, 0x09, 0x44, 0x62, 0x55,
0x74, 0x78, 0x6f, 0x53, 0x65, 0x74, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d,
0x73, 0x22, 0x87, 0x01, 0x0a, 0x14, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x6f, 0x75,
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73,
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f,
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e,
0x74, 0x12, 0x38, 0x0a, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75,
0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x3c, 0x0a, 0x07, 0x6f, 0x75, 0x74,
0x70, 0x75, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x65, 0x72,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07,
0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x54,
0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x54,
0x69, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
0x6b, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74,
0x77, 0x6f, 0x72, 0x6b, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x06, 0x20,
0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
0x6f, 0x61, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f,
0x61, 0x64, 0x22, 0xc1, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x70, 0x72, 0x65,
0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x10,
0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x12, 0x28, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72,
0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61,
0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65,
0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65,
0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x4f, 0x70, 0x43,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x4f,
0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x68, 0x0a, 0x0a, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70,
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72,
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0d, 0x74, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e,
0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78,
0x22, 0x37, 0x0a, 0x0f, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x13, 0x44, 0x62, 0x54,
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x20, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
0x79, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
0x65, 0x79, 0x22, 0x34, 0x0a, 0x0e, 0x44, 0x62, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f,
0x72, 0x6b, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f,
0x72, 0x6b, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x10, 0x44, 0x62, 0x41, 0x63,
0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x56, 0x0a, 0x13,
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44,
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52,
0x13, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65,
0x44, 0x61, 0x74, 0x61, 0x22, 0xb6, 0x01, 0x0a, 0x15, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x68,
0x0a, 0x19, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63,
0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41,
0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x19, 0x74,
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74,
0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61,
0x73, 0x68, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0xed, 0x01,
0x0a, 0x1b, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41,
0x63, 0x63, 0x65, 0x70, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3e, 0x0a,
0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a,
0x03, 0x66, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12,
0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12,
0x5c, 0x0a, 0x1b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x52, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x45, 0x0a, 0x11, 0x44,
0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79,
0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x22, 0xb7, 0x01, 0x0a, 0x0b, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c,
0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62,
0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44,
0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a,
0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
0x52, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x22, 0xfe, 0x01, 0x0a,
0x12, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44,
0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x63, 0x68,
0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61,
0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52, 0x08,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x75, 0x74, 0x75,
0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x18, 0x04, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x11, 0x66, 0x75, 0x74, 0x75,
0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x22, 0x40, 0x0a,
0x16, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49,
0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a,
0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22,
0x88, 0x01, 0x0a, 0x0a, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x44, 0x69, 0x66, 0x66, 0x12, 0x39,
0x0a, 0x05, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e,
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62,
0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74,
0x65, 0x6d, 0x52, 0x05, 0x74, 0x6f, 0x41, 0x64, 0x64, 0x12, 0x3f, 0x0a, 0x08, 0x74, 0x6f, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74,
0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d,
0x52, 0x08, 0x74, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x33, 0x0a, 0x06, 0x44, 0x62,
0x54, 0x69, 0x70, 0x73, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03,
0x52, 0x1b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70,
0x75, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x76, 0x0a,
0x10, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x2f, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x04, 0x74, 0x69, 0x70, 0x73, 0x22,
0x24, 0x0a, 0x0c, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x2a, 0x0a, 0x12, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x22, 0x90, 0x01, 0x0a, 0x1b, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x48, 0x4f,
0x53, 0x54, 0x44, 0x41, 0x47, 0x44, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x50, 0x61, 0x69,
0x72, 0x12, 0x29, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x74, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x63, 0x68, 0x69,
0x6c, 0x64, 0x72, 0x65, 0x6e, 0x22, 0x27, 0x0a, 0x0d, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xdb,
0x02, 0x0a, 0x13, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64,
0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63,
0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53,
0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b,
0x12, 0x3d, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65,
0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52,
0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12,
0x3b, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73,
0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0d, 0x6d,
0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0c,
0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65,
0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x12, 0x53, 0x0a, 0x12, 0x62, 0x6c, 0x75, 0x65, 0x73,
0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x06, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63,
0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x52, 0x12, 0x62, 0x6c, 0x75, 0x65, 0x73, 0x41,
0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x22, 0x6d, 0x0a, 0x14,
0x44, 0x62, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53,
0x69, 0x7a, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73, 0x68,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x62,
0x6c, 0x75, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63,
0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x61,
0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x28, 0x0a, 0x0a, 0x44,
0x62, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x75, 0x6c,
0x74, 0x69, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x75, 0x6c,
0x74, 0x69, 0x73, 0x65, 0x74, 0x22, 0x46, 0x0a, 0x09, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x53,
0x65, 0x74, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x87, 0x01,
0x0a, 0x14, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69,
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x4f, 0x75, 0x74, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x38, 0x0a,
0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x75, 0x74,
0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x45, 0x0a, 0x11, 0x44, 0x62, 0x53, 0x63, 0x72,
0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xb7,
0x01, 0x0a, 0x0b, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x16,
0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06,
0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x20, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
0x79, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
0x65, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63,
0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x43, 0x6f,
0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73,
0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x22, 0xfe, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x52,
0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12,
0x31, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x74, 0x12, 0x41, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69,
0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f,
0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x15, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x46, 0x0a, 0x0c,
0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64,
0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0c, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67,
0x44, 0x61, 0x74, 0x61, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70,
0x61, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x44, 0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x11, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f,
0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x22, 0x40, 0x0a, 0x16, 0x44, 0x62, 0x52,
0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72,
0x76, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64,
0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x88, 0x01, 0x0a, 0x0a,
0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x44, 0x69, 0x66, 0x66, 0x12, 0x39, 0x0a, 0x05, 0x74, 0x6f,
0x41, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f,
0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05,
0x74, 0x6f, 0x41, 0x64, 0x64, 0x12, 0x3f, 0x0a, 0x08, 0x74, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76,
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c,
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x55, 0x74, 0x78, 0x6f, 0x43, 0x6f,
0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x74, 0x6f,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22, 0x33, 0x0a, 0x06, 0x44, 0x62, 0x54, 0x69, 0x70, 0x73,
0x12, 0x29, 0x0a, 0x04, 0x74, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15,
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
0x62, 0x48, 0x61, 0x73, 0x68, 0x52, 0x04, 0x74, 0x69, 0x70, 0x73, 0x22, 0x24, 0x0a, 0x0c, 0x44,
0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x22, 0x2a, 0x0a, 0x12, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64,
0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x90, 0x01,
0x0a, 0x1b, 0x44, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x48, 0x4f, 0x53, 0x54, 0x44, 0x41,
0x47, 0x44, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x50, 0x61, 0x69, 0x72, 0x12, 0x29, 0x0a,
0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x62, 0x48, 0x61,
0x73, 0x68, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x46, 0x0a, 0x0c, 0x47, 0x68, 0x6f, 0x73,
0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22,
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44,
0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61,
0x74, 0x61, 0x52, 0x0c, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61,
0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b,
0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x73,
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -2047,7 +2062,7 @@ var file_dbobjects_proto_depIdxs = []int32{
3, // 3: serialization.DbBlockHeader.hashMerkleRoot:type_name -> serialization.DbHash
3, // 4: serialization.DbBlockHeader.acceptedIDMerkleRoot:type_name -> serialization.DbHash
3, // 5: serialization.DbBlockHeader.utxoCommitment:type_name -> serialization.DbHash
3, // 6: serialization.DbBlockHeader.finalityPoint:type_name -> serialization.DbHash
3, // 6: serialization.DbBlockHeader.pruningPoint:type_name -> serialization.DbHash
3, // 7: serialization.DbBlockLevelParents.parentHashes:type_name -> serialization.DbHash
5, // 8: serialization.DbTransaction.inputs:type_name -> serialization.DbTransactionInput
8, // 9: serialization.DbTransaction.outputs:type_name -> serialization.DbTransactionOutput

View File

@ -19,7 +19,8 @@ message DbBlockHeader {
uint64 nonce = 8;
uint64 daaScore = 9;
bytes blueWork = 10;
DbHash finalityPoint = 11;
DbHash pruningPoint = 12;
uint64 blueScore = 13;
}
message DbBlockLevelParents {

View File

@ -8,8 +8,8 @@ import (
type pruningStagingShard struct {
store *pruningStore
currentPruningPoint *externalapi.DomainHash
previousPruningPoint *externalapi.DomainHash
pruningPointByIndex map[uint64]*externalapi.DomainHash
currentPruningPointIndex *uint64
newPruningPointCandidate *externalapi.DomainHash
startUpdatingPruningPointUTXOSet bool
}
@ -18,8 +18,7 @@ func (ps *pruningStore) stagingShard(stagingArea *model.StagingArea) *pruningSta
return stagingArea.GetOrCreateShard(model.StagingShardIDPruning, func() model.StagingShard {
return &pruningStagingShard{
store: ps,
currentPruningPoint: nil,
previousPruningPoint: nil,
pruningPointByIndex: map[uint64]*externalapi.DomainHash{},
newPruningPointCandidate: nil,
startUpdatingPruningPointUTXOSet: false,
}
@ -27,28 +26,32 @@ func (ps *pruningStore) stagingShard(stagingArea *model.StagingArea) *pruningSta
}
func (mss *pruningStagingShard) Commit(dbTx model.DBTransaction) error {
if mss.currentPruningPoint != nil {
pruningPointBytes, err := mss.store.serializeHash(mss.currentPruningPoint)
for index, hash := range mss.pruningPointByIndex {
hashCopy := hash
hashBytes, err := mss.store.serializeHash(hash)
if err != nil {
return err
}
err = dbTx.Put(mss.store.pruningBlockHashKey, pruningPointBytes)
err = dbTx.Put(mss.store.indexAsKey(index), hashBytes)
if err != nil {
return err
}
mss.store.pruningPointCache = mss.currentPruningPoint
mss.store.pruningPointByIndexCache.Add(index, hashCopy)
}
if mss.previousPruningPoint != nil {
oldPruningPointBytes, err := mss.store.serializeHash(mss.previousPruningPoint)
if mss.currentPruningPointIndex != nil {
indexBytes := mss.store.serializeIndex(*mss.currentPruningPointIndex)
err := dbTx.Put(mss.store.currentPruningPointIndexKey, indexBytes)
if err != nil {
return err
}
err = dbTx.Put(mss.store.previousPruningBlockHashKey, oldPruningPointBytes)
if err != nil {
return err
if mss.store.currentPruningPointIndexCache == nil {
var zero uint64
mss.store.currentPruningPointIndexCache = &zero
}
mss.store.oldPruningPointCache = mss.previousPruningPoint
*mss.store.currentPruningPointIndexCache = *mss.currentPruningPointIndex
}
if mss.newPruningPointCandidate != nil {
@ -74,5 +77,5 @@ func (mss *pruningStagingShard) Commit(dbTx model.DBTransaction) error {
}
func (mss *pruningStagingShard) isStaged() bool {
return mss.currentPruningPoint != nil || mss.newPruningPointCandidate != nil || mss.previousPruningPoint != nil || mss.startUpdatingPruningPointUTXOSet
return len(mss.pruningPointByIndex) > 0 || mss.newPruningPointCandidate != nil || mss.startUpdatingPruningPointUTXOSet
}

View File

@ -1,45 +1,49 @@
package pruningstore
import (
"encoding/binary"
"github.com/golang/protobuf/proto"
"github.com/kaspanet/kaspad/domain/consensus/database"
"github.com/kaspanet/kaspad/domain/consensus/database/binaryserialization"
"github.com/kaspanet/kaspad/domain/consensus/database/serialization"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/lrucacheuint64tohash"
"github.com/kaspanet/kaspad/domain/prefixmanager/prefix"
)
var pruningBlockHashKeyName = []byte("pruning-block-hash")
var previousPruningBlockHashKeyName = []byte("previous-pruning-block-hash")
var currentPruningPointIndexKeyName = []byte("pruning-block-index")
var candidatePruningPointHashKeyName = []byte("candidate-pruning-point-hash")
var pruningPointUTXOSetBucketName = []byte("pruning-point-utxo-set")
var updatingPruningPointUTXOSetKeyName = []byte("updating-pruning-point-utxo-set")
var pruningPointByIndexBucketName = []byte("pruning-point-by-index")
// pruningStore represents a store for the current pruning state
type pruningStore struct {
pruningPointCache *externalapi.DomainHash
oldPruningPointCache *externalapi.DomainHash
pruningPointCandidateCache *externalapi.DomainHash
pruningPointByIndexCache *lrucacheuint64tohash.LRUCache
currentPruningPointIndexCache *uint64
pruningPointCandidateCache *externalapi.DomainHash
pruningBlockHashKey model.DBKey
previousPruningBlockHashKey model.DBKey
currentPruningPointIndexKey model.DBKey
candidatePruningPointHashKey model.DBKey
pruningPointUTXOSetBucket model.DBBucket
updatingPruningPointUTXOSetKey model.DBKey
importedPruningPointUTXOsBucket model.DBBucket
importedPruningPointMultisetKey model.DBKey
pruningPointByIndexBucket model.DBBucket
}
// New instantiates a new PruningStore
func New(prefix *prefix.Prefix) model.PruningStore {
func New(prefix *prefix.Prefix, cacheSize int, preallocate bool) model.PruningStore {
return &pruningStore{
pruningBlockHashKey: database.MakeBucket(prefix.Serialize()).Key(pruningBlockHashKeyName),
previousPruningBlockHashKey: database.MakeBucket(prefix.Serialize()).Key(previousPruningBlockHashKeyName),
pruningPointByIndexCache: lrucacheuint64tohash.New(cacheSize, preallocate),
currentPruningPointIndexKey: database.MakeBucket(prefix.Serialize()).Key(currentPruningPointIndexKeyName),
candidatePruningPointHashKey: database.MakeBucket(prefix.Serialize()).Key(candidatePruningPointHashKeyName),
pruningPointUTXOSetBucket: database.MakeBucket(prefix.Serialize()).Bucket(pruningPointUTXOSetBucketName),
importedPruningPointUTXOsBucket: database.MakeBucket(prefix.Serialize()).Bucket(importedPruningPointUTXOsBucketName),
updatingPruningPointUTXOSetKey: database.MakeBucket(prefix.Serialize()).Key(updatingPruningPointUTXOSetKeyName),
importedPruningPointMultisetKey: database.MakeBucket(prefix.Serialize()).Key(importedPruningPointMultisetKeyName),
pruningPointByIndexBucket: database.MakeBucket(prefix.Serialize()).Bucket(pruningPointByIndexBucketName),
}
}
@ -87,16 +91,24 @@ func (ps *pruningStore) HasPruningPointCandidate(dbContext model.DBReader, stagi
return dbContext.Has(ps.candidatePruningPointHashKey)
}
// Stage stages the pruning state
func (ps *pruningStore) StagePruningPoint(stagingArea *model.StagingArea, pruningPointBlockHash *externalapi.DomainHash) {
stagingShard := ps.stagingShard(stagingArea)
// StagePruningPoint stages the pruning state
func (ps *pruningStore) StagePruningPoint(dbContext model.DBWriter, stagingArea *model.StagingArea, pruningPointBlockHash *externalapi.DomainHash) error {
newPruningPointIndex := uint64(0)
pruningPointIndex, err := ps.CurrentPruningPointIndex(dbContext, stagingArea)
if database.IsNotFoundError(err) {
newPruningPointIndex = 0
} else if err != nil {
return err
} else {
newPruningPointIndex = pruningPointIndex + 1
}
stagingShard.currentPruningPoint = pruningPointBlockHash
}
err = ps.StagePruningPointByIndex(dbContext, stagingArea, pruningPointBlockHash, newPruningPointIndex)
if err != nil {
return err
}
func (ps *pruningStore) StagePreviousPruningPoint(stagingArea *model.StagingArea, oldPruningPointBlockHash *externalapi.DomainHash) {
stagingShard := ps.stagingShard(stagingArea)
stagingShard.previousPruningPoint = oldPruningPointBlockHash
return nil
}
func (ps *pruningStore) IsStaged(stagingArea *model.StagingArea) bool {
@ -146,17 +158,26 @@ func (ps *pruningStore) UpdatePruningPointUTXOSet(dbContext model.DBWriter, diff
// PruningPoint gets the current pruning point
func (ps *pruningStore) PruningPoint(dbContext model.DBReader, stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
pruningPointIndex, err := ps.CurrentPruningPointIndex(dbContext, stagingArea)
if err != nil {
return nil, err
}
return ps.PruningPointByIndex(dbContext, stagingArea, pruningPointIndex)
}
func (ps *pruningStore) PruningPointByIndex(dbContext model.DBReader, stagingArea *model.StagingArea, index uint64) (*externalapi.DomainHash, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.currentPruningPoint != nil {
return stagingShard.currentPruningPoint, nil
if hash, exists := stagingShard.pruningPointByIndex[index]; exists {
return hash, nil
}
if ps.pruningPointCache != nil {
return ps.pruningPointCache, nil
if hash, exists := ps.pruningPointByIndexCache.Get(index); exists {
return hash, nil
}
pruningPointBytes, err := dbContext.Get(ps.pruningBlockHashKey)
pruningPointBytes, err := dbContext.Get(ps.indexAsKey(index))
if err != nil {
return nil, err
}
@ -165,34 +186,10 @@ func (ps *pruningStore) PruningPoint(dbContext model.DBReader, stagingArea *mode
if err != nil {
return nil, err
}
ps.pruningPointCache = pruningPoint
ps.pruningPointByIndexCache.Add(index, pruningPoint)
return pruningPoint, nil
}
// OldPruningPoint returns the pruning point *before* the current one
func (ps *pruningStore) PreviousPruningPoint(dbContext model.DBReader, stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.previousPruningPoint != nil {
return stagingShard.previousPruningPoint, nil
}
if ps.oldPruningPointCache != nil {
return ps.oldPruningPointCache, nil
}
oldPruningPointBytes, err := dbContext.Get(ps.previousPruningBlockHashKey)
if err != nil {
return nil, err
}
oldPruningPoint, err := ps.deserializePruningPoint(oldPruningPointBytes)
if err != nil {
return nil, err
}
ps.oldPruningPointCache = oldPruningPoint
return oldPruningPoint, nil
}
func (ps *pruningStore) serializeHash(hash *externalapi.DomainHash) ([]byte, error) {
return proto.Marshal(serialization.DomainHashToDbHash(hash))
}
@ -207,18 +204,26 @@ func (ps *pruningStore) deserializePruningPoint(pruningPointBytes []byte) (*exte
return serialization.DbHashToDomainHash(dbHash)
}
func (ps *pruningStore) deserializeIndex(indexBytes []byte) (uint64, error) {
return binaryserialization.DeserializeUint64(indexBytes)
}
func (ps *pruningStore) serializeIndex(index uint64) []byte {
return binaryserialization.SerializeUint64(index)
}
func (ps *pruningStore) HasPruningPoint(dbContext model.DBReader, stagingArea *model.StagingArea) (bool, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.currentPruningPoint != nil {
if stagingShard.currentPruningPointIndex != nil {
return true, nil
}
if ps.pruningPointCache != nil {
if ps.currentPruningPointIndexCache != nil {
return true, nil
}
return dbContext.Has(ps.pruningBlockHashKey)
return dbContext.Has(ps.currentPruningPointIndexKey)
}
func (ps *pruningStore) PruningPointUTXOIterator(dbContext model.DBReader) (externalapi.ReadOnlyUTXOSetIterator, error) {
@ -280,3 +285,57 @@ func (ps *pruningStore) HadStartedUpdatingPruningPointUTXOSet(dbContext model.DB
func (ps *pruningStore) FinishUpdatingPruningPointUTXOSet(dbContext model.DBWriter) error {
return dbContext.Delete(ps.updatingPruningPointUTXOSetKey)
}
func (ps *pruningStore) indexAsKey(index uint64) model.DBKey {
var keyBytes [8]byte
binary.BigEndian.PutUint64(keyBytes[:], index)
return ps.pruningPointByIndexBucket.Key(keyBytes[:])
}
func (ps *pruningStore) StagePruningPointByIndex(dbContext model.DBReader, stagingArea *model.StagingArea,
pruningPointBlockHash *externalapi.DomainHash, index uint64) error {
stagingShard := ps.stagingShard(stagingArea)
stagingShard.pruningPointByIndex[index] = pruningPointBlockHash
pruningPointIndex, err := ps.CurrentPruningPointIndex(dbContext, stagingArea)
isNotFoundError := database.IsNotFoundError(err)
if !isNotFoundError && err != nil {
return err
}
if stagingShard.currentPruningPointIndex == nil {
var zero uint64
stagingShard.currentPruningPointIndex = &zero
}
if isNotFoundError || index > pruningPointIndex {
*stagingShard.currentPruningPointIndex = index
}
return nil
}
func (ps *pruningStore) CurrentPruningPointIndex(dbContext model.DBReader, stagingArea *model.StagingArea) (uint64, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.currentPruningPointIndex != nil {
return *stagingShard.currentPruningPointIndex, nil
}
if ps.currentPruningPointIndexCache != nil {
return *ps.currentPruningPointIndexCache, nil
}
pruningPointIndexBytes, err := dbContext.Get(ps.currentPruningPointIndexKey)
if err != nil {
return 0, err
}
index, err := ps.deserializeIndex(pruningPointIndexBytes)
if err != nil {
return 0, err
}
*ps.currentPruningPointIndexCache = index
return index, nil
}

View File

@ -132,7 +132,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
blockStatusStore := blockstatusstore.New(dbPrefix, pruningWindowSizePlusFinalityDepthForCache, preallocateCaches)
multisetStore := multisetstore.New(dbPrefix, 200, preallocateCaches)
pruningStore := pruningstore.New(dbPrefix)
pruningStore := pruningstore.New(dbPrefix, 2, preallocateCaches)
reachabilityDataStore := reachabilitydatastore.New(dbPrefix, pruningWindowSizePlusFinalityDepthForCache, preallocateCaches)
utxoDiffStore := utxodiffstore.New(dbPrefix, 200, preallocateCaches)
consensusStateStore := consensusstatestore.New(dbPrefix, 10_000, preallocateCaches)
@ -232,41 +232,8 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
dagTraversalManager,
finalityManager,
ghostdagDataStore)
blockValidator := blockvalidator.New(
config.PowMax,
config.SkipProofOfWork,
genesisHash,
config.EnableNonNativeSubnetworks,
config.MaxBlockMass,
config.MergeSetSizeLimit,
config.MaxBlockParents,
config.TimestampDeviationTolerance,
config.TargetTimePerBlock,
dbManager,
difficultyManager,
pastMedianTimeManager,
transactionValidator,
ghostdagManager,
dagTopologyManager,
dagTraversalManager,
coinbaseManager,
mergeDepthManager,
reachabilityManager,
finalityManager,
pruningStore,
blockStore,
ghostdagDataStore,
blockHeaderStore,
blockStatusStore,
reachabilityDataStore,
consensusStateStore,
daaBlocksStore,
)
consensusStateManager, err := consensusstatemanager.New(
dbManager,
config.PruningDepth(),
config.MaxBlockParents,
config.MergeSetSizeLimit,
genesisHash,
@ -276,7 +243,6 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
dagTraversalManager,
pastMedianTimeManager,
transactionValidator,
blockValidator,
coinbaseManager,
mergeDepthManager,
finalityManager,
@ -303,6 +269,8 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
dagTraversalManager,
dagTopologyManager,
consensusStateManager,
finalityManager,
consensusStateStore,
ghostdagDataStore,
pruningStore,
@ -326,6 +294,40 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
config.DifficultyAdjustmentWindowSize,
)
blockValidator := blockvalidator.New(
config.PowMax,
config.SkipProofOfWork,
genesisHash,
config.EnableNonNativeSubnetworks,
config.MaxBlockMass,
config.MergeSetSizeLimit,
config.MaxBlockParents,
config.TimestampDeviationTolerance,
config.TargetTimePerBlock,
dbManager,
difficultyManager,
pastMedianTimeManager,
transactionValidator,
ghostdagManager,
dagTopologyManager,
dagTraversalManager,
coinbaseManager,
mergeDepthManager,
reachabilityManager,
finalityManager,
pruningManager,
pruningStore,
blockStore,
ghostdagDataStore,
blockHeaderStore,
blockStatusStore,
reachabilityDataStore,
consensusStateStore,
daaBlocksStore,
)
syncManager := syncmanager.New(
dbManager,
genesisHash,
@ -344,6 +346,8 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
blockBuilder := blockbuilder.New(
dbManager,
genesisHash,
difficultyManager,
pastMedianTimeManager,
coinbaseManager,
@ -351,12 +355,15 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
ghostdagManager,
transactionValidator,
finalityManager,
pruningManager,
acceptanceDataStore,
blockRelationStore,
multisetStore,
ghostdagDataStore,
daaBlocksStore,
pruningStore,
blockHeaderStore,
)
blockProcessor := blockprocessor.New(

View File

@ -66,8 +66,9 @@ type BaseBlockHeader interface {
Bits() uint32
Nonce() uint64
DAAScore() uint64
BlueScore() uint64
BlueWork() *big.Int
FinalityPoint() *DomainHash
PruningPoint() *DomainHash
Equal(other BaseBlockHeader) bool
}

View File

@ -109,8 +109,9 @@ func initTestBlockStructsForClone() []*externalapi.DomainBlock {
5,
6,
7,
big.NewInt(8),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{9}),
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
),
initTestBaseTransactions(),
}, {
@ -124,8 +125,9 @@ func initTestBlockStructsForClone() []*externalapi.DomainBlock {
5,
6,
7,
big.NewInt(8),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{9}),
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
),
initTestBaseTransactions(),
},
@ -155,8 +157,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
5,
6,
7,
big.NewInt(8),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{9}),
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
),
initTestBaseTransactions()},
expectedResult: false,
@ -174,8 +177,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -196,8 +200,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestAnotherTransactions(),
},
@ -214,8 +219,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -235,8 +241,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -253,8 +260,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestTwoTransactions(),
},
@ -271,8 +279,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -289,8 +298,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -307,8 +317,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -325,8 +336,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -343,8 +355,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
100, // Changed
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -361,8 +374,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
100, // Changed
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -379,8 +393,9 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
100, // Changed
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -397,8 +412,28 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
100, // Changed
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &externalapi.DomainBlock{
blockheader.NewImmutableBlockHeader(
0,
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{1})}},
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{2}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{3}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{4}),
5,
6,
7,
8,
9,
big.NewInt(100), // Changed
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
),
initTestBaseTransactions(),
},
@ -415,7 +450,8 @@ func initTestBlockStructsForEqual() *[]TestBlockStruct {
6,
7,
8,
big.NewInt(9),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{100}), // Changed
),
initTestBaseTransactions(),

View File

@ -7,6 +7,7 @@ type Consensus interface {
ValidateAndInsertBlock(block *DomainBlock, shouldValidateAgainstUTXO bool) (*BlockInsertionResult, error)
ValidateAndInsertBlockWithTrustedData(block *BlockWithTrustedData, validateUTXO bool) (*BlockInsertionResult, error)
ValidateTransactionAndPopulateWithConsensusData(transaction *DomainTransaction) error
ImportPruningPoints(pruningPoints []BlockHeader) error
GetBlock(blockHash *DomainHash) (*DomainBlock, error)
GetBlockEvenIfHeaderOnly(blockHash *DomainHash) (*DomainBlock, error)
@ -20,6 +21,7 @@ type Consensus interface {
GetPruningPointUTXOs(expectedPruningPointHash *DomainHash, fromOutpoint *DomainOutpoint, limit int) ([]*OutpointAndUTXOEntryPair, error)
GetVirtualUTXOs(expectedVirtualParents []*DomainHash, fromOutpoint *DomainOutpoint, limit int) ([]*OutpointAndUTXOEntryPair, error)
PruningPoint() (*DomainHash, error)
PruningPointHeaders() ([]BlockHeader, error)
PruningPointAndItsAnticoneWithTrustedData() ([]*BlockWithTrustedData, error)
ClearImportedPruningPointData() error
AppendImportedPruningPointUTXOs(outpointAndUTXOEntryPairs []*OutpointAndUTXOEntryPair) error
@ -33,6 +35,7 @@ type Consensus interface {
GetVirtualInfo() (*VirtualInfo, error)
GetVirtualDAAScore() (uint64, error)
IsValidPruningPoint(blockHash *DomainHash) (bool, error)
ArePruningPointsViolatingFinality(pruningPoints []BlockHeader) (bool, error)
GetVirtualSelectedParentChainFromBlock(blockHash *DomainHash) (*SelectedChainPath, error)
IsInSelectedParentChainOf(blockHashA *DomainHash, blockHashB *DomainHash) (bool, error)
GetHeadersSelectedTip() (*DomainHash, error)

View File

@ -5,15 +5,17 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
// PruningStore represents a store for the current pruning state
type PruningStore interface {
Store
StagePruningPoint(stagingArea *StagingArea, pruningPointBlockHash *externalapi.DomainHash)
StagePreviousPruningPoint(stagingArea *StagingArea, oldPruningPointBlockHash *externalapi.DomainHash)
StagePruningPoint(dbContext DBWriter, stagingArea *StagingArea, pruningPointBlockHash *externalapi.DomainHash) error
StagePruningPointByIndex(dbContext DBReader, stagingArea *StagingArea,
pruningPointBlockHash *externalapi.DomainHash, index uint64) error
StagePruningPointCandidate(stagingArea *StagingArea, candidate *externalapi.DomainHash)
IsStaged(stagingArea *StagingArea) bool
PruningPointCandidate(dbContext DBReader, stagingArea *StagingArea) (*externalapi.DomainHash, error)
HasPruningPointCandidate(dbContext DBReader, stagingArea *StagingArea) (bool, error)
PreviousPruningPoint(dbContext DBReader, stagingArea *StagingArea) (*externalapi.DomainHash, error)
PruningPoint(dbContext DBReader, stagingArea *StagingArea) (*externalapi.DomainHash, error)
HasPruningPoint(dbContext DBReader, stagingArea *StagingArea) (bool, error)
CurrentPruningPointIndex(dbContext DBReader, stagingArea *StagingArea) (uint64, error)
PruningPointByIndex(dbContext DBReader, stagingArea *StagingArea, index uint64) (*externalapi.DomainHash, error)
StageStartUpdatingPruningPointUTXOSet(stagingArea *StagingArea)
HadStartedUpdatingPruningPointUTXOSet(dbContext DBWriter) (bool, error)

View File

@ -6,7 +6,8 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
type ConsensusStateManager interface {
AddBlock(stagingArea *StagingArea, blockHash *externalapi.DomainHash, updateVirtual bool) (*externalapi.SelectedChainPath, externalapi.UTXODiff, *UTXODiffReversalData, error)
PopulateTransactionWithUTXOEntries(stagingArea *StagingArea, transaction *externalapi.DomainTransaction) error
ImportPruningPoint(stagingArea *StagingArea, newPruningPoint *externalapi.DomainHash) error
ImportPruningPointUTXOSet(stagingArea *StagingArea, newPruningPoint *externalapi.DomainHash) error
ImportPruningPoints(stagingArea *StagingArea, pruningPoints []externalapi.BlockHeader) error
RestorePastUTXOSetIterator(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (externalapi.ReadOnlyUTXOSetIterator, error)
CalculatePastUTXOAndAcceptanceData(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (externalapi.UTXODiff, externalapi.AcceptanceData, Multiset, error)
GetVirtualSelectedParentChainFromBlock(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, error)

View File

@ -6,9 +6,14 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
type PruningManager interface {
UpdatePruningPointByVirtual(stagingArea *StagingArea) error
IsValidPruningPoint(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (bool, error)
ArePruningPointsViolatingFinality(stagingArea *StagingArea, pruningPoints []externalapi.BlockHeader) (bool, error)
ArePruningPointsInValidChain(stagingArea *StagingArea) (bool, error)
ClearImportedPruningPointData() error
AppendImportedPruningPointUTXOs(outpointAndUTXOEntryPairs []*externalapi.OutpointAndUTXOEntryPair) error
UpdatePruningPointIfRequired() error
PruneAllBlocksBelow(stagingArea *StagingArea, pruningPointHash *externalapi.DomainHash) error
PruningPointAndItsAnticoneWithTrustedData() ([]*externalapi.BlockWithTrustedData, error)
NextPruningPointAndCandidateByBlockHash(stagingArea *StagingArea,
blockHash *externalapi.DomainHash) (*externalapi.DomainHash, *externalapi.DomainHash, error)
ExpectedHeaderPruningPoint(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error)
}

View File

@ -19,6 +19,7 @@ import (
type blockBuilder struct {
databaseContext model.DBManager
genesisHash *externalapi.DomainHash
difficultyManager model.DifficultyManager
pastMedianTimeManager model.PastMedianTimeManager
@ -27,17 +28,21 @@ type blockBuilder struct {
ghostdagManager model.GHOSTDAGManager
transactionValidator model.TransactionValidator
finalityManager model.FinalityManager
pruningManager model.PruningManager
acceptanceDataStore model.AcceptanceDataStore
blockRelationStore model.BlockRelationStore
multisetStore model.MultisetStore
ghostdagDataStore model.GHOSTDAGDataStore
daaBlocksStore model.DAABlocksStore
pruningStore model.PruningStore
blockHeaderStore model.BlockHeaderStore
}
// New creates a new instance of a BlockBuilder
func New(
databaseContext model.DBManager,
genesisHash *externalapi.DomainHash,
difficultyManager model.DifficultyManager,
pastMedianTimeManager model.PastMedianTimeManager,
@ -46,16 +51,21 @@ func New(
ghostdagManager model.GHOSTDAGManager,
transactionValidator model.TransactionValidator,
finalityManager model.FinalityManager,
pruningManager model.PruningManager,
acceptanceDataStore model.AcceptanceDataStore,
blockRelationStore model.BlockRelationStore,
multisetStore model.MultisetStore,
ghostdagDataStore model.GHOSTDAGDataStore,
daaBlocksStore model.DAABlocksStore,
pruningStore model.PruningStore,
blockHeaderStore model.BlockHeaderStore,
) model.BlockBuilder {
return &blockBuilder{
databaseContext: databaseContext,
databaseContext: databaseContext,
genesisHash: genesisHash,
difficultyManager: difficultyManager,
pastMedianTimeManager: pastMedianTimeManager,
coinbaseManager: coinbaseManager,
@ -63,12 +73,15 @@ func New(
ghostdagManager: ghostdagManager,
transactionValidator: transactionValidator,
finalityManager: finalityManager,
pruningManager: pruningManager,
acceptanceDataStore: acceptanceDataStore,
blockRelationStore: blockRelationStore,
multisetStore: multisetStore,
ghostdagDataStore: ghostdagDataStore,
daaBlocksStore: daaBlocksStore,
pruningStore: pruningStore,
blockHeaderStore: blockHeaderStore,
}
}
@ -198,7 +211,11 @@ func (bb *blockBuilder) buildHeader(stagingArea *model.StagingArea, transactions
if err != nil {
return nil, err
}
finalityPoint, err := bb.newBlockFinalityPoint(stagingArea)
blueScore, err := bb.newBlockBlueScore(stagingArea)
if err != nil {
return nil, err
}
pruningPoint, err := bb.newBlockPruningPoint(stagingArea, model.VirtualBlockHash)
if err != nil {
return nil, err
}
@ -213,8 +230,9 @@ func (bb *blockBuilder) buildHeader(stagingArea *model.StagingArea, transactions
bits,
0,
daaScore,
blueScore,
blueWork,
finalityPoint,
pruningPoint,
), nil
}
@ -310,6 +328,14 @@ func (bb *blockBuilder) newBlockBlueWork(stagingArea *model.StagingArea) (*big.I
return virtualGHOSTDAGData.BlueWork(), nil
}
func (bb *blockBuilder) newBlockFinalityPoint(stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
return bb.finalityManager.VirtualFinalityPoint(stagingArea)
func (bb *blockBuilder) newBlockBlueScore(stagingArea *model.StagingArea) (uint64, error) {
virtualGHOSTDAGData, err := bb.ghostdagDataStore.Get(bb.databaseContext, stagingArea, model.VirtualBlockHash, false)
if err != nil {
return 0, err
}
return virtualGHOSTDAGData.BlueScore(), nil
}
func (bb *blockBuilder) newBlockPruningPoint(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
return bb.pruningManager.ExpectedHeaderPruningPoint(stagingArea, blockHash)
}

View File

@ -67,8 +67,8 @@ func (bb *testBlockBuilder) BuildBlockWithParents(parentHashes []*externalapi.Do
}
func (bb *testBlockBuilder) buildUTXOInvalidHeader(stagingArea *model.StagingArea,
parentHashes []*externalapi.DomainHash, bits uint32, daaScore uint64, blueWork *big.Int,
finalityPoint *externalapi.DomainHash, transactions []*externalapi.DomainTransaction) (externalapi.BlockHeader, error) {
parentHashes []*externalapi.DomainHash, bits uint32, daaScore, blueScore uint64, blueWork *big.Int,
transactions []*externalapi.DomainTransaction) (externalapi.BlockHeader, error) {
timeInMilliseconds, err := bb.minBlockTime(stagingArea, tempBlockHash)
if err != nil {
@ -77,6 +77,11 @@ func (bb *testBlockBuilder) buildUTXOInvalidHeader(stagingArea *model.StagingAre
hashMerkleRoot := bb.newBlockHashMerkleRoot(transactions)
pruningPoint, err := bb.newBlockPruningPoint(stagingArea, tempBlockHash)
if err != nil {
return nil, err
}
parents := []externalapi.BlockLevelParents{parentHashes}
bb.nonceCounter++
@ -90,17 +95,17 @@ func (bb *testBlockBuilder) buildUTXOInvalidHeader(stagingArea *model.StagingAre
bits,
bb.nonceCounter,
daaScore,
blueScore,
blueWork,
finalityPoint,
pruningPoint,
), nil
}
func (bb *testBlockBuilder) buildHeaderWithParents(stagingArea *model.StagingArea,
parentHashes []*externalapi.DomainHash, bits uint32, transactions []*externalapi.DomainTransaction,
acceptanceData externalapi.AcceptanceData, multiset model.Multiset, daaScore uint64, blueWork *big.Int,
finalityPoint *externalapi.DomainHash) (externalapi.BlockHeader, error) {
acceptanceData externalapi.AcceptanceData, multiset model.Multiset, daaScore, blueScore uint64, blueWork *big.Int) (externalapi.BlockHeader, error) {
header, err := bb.buildUTXOInvalidHeader(stagingArea, parentHashes, bits, daaScore, blueWork, finalityPoint, transactions)
header, err := bb.buildUTXOInvalidHeader(stagingArea, parentHashes, bits, daaScore, blueScore, blueWork, transactions)
if err != nil {
return nil, err
}
@ -122,8 +127,9 @@ func (bb *testBlockBuilder) buildHeaderWithParents(stagingArea *model.StagingAre
header.Bits(),
header.Nonce(),
header.DAAScore(),
header.BlueScore(),
header.BlueWork(),
header.FinalityPoint(),
header.PruningPoint(),
), nil
}
@ -164,6 +170,7 @@ func (bb *testBlockBuilder) buildBlockWithParents(stagingArea *model.StagingArea
return nil, nil, err
}
blueWork := ghostdagData.BlueWork()
blueScore := ghostdagData.BlueScore()
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(
stagingArea, ghostdagData.SelectedParent(), false)
@ -193,13 +200,9 @@ func (bb *testBlockBuilder) buildBlockWithParents(stagingArea *model.StagingArea
if err != nil {
return nil, nil, err
}
finalityPoint, err := bb.finalityManager.FinalityPoint(stagingArea, tempBlockHash, false)
if err != nil {
return nil, nil, err
}
header, err := bb.buildHeaderWithParents(
stagingArea, parentHashes, bits, transactionsWithCoinbase, acceptanceData, multiset, daaScore, blueWork, finalityPoint)
stagingArea, parentHashes, bits, transactionsWithCoinbase, acceptanceData, multiset, daaScore, blueScore, blueWork)
if err != nil {
return nil, nil, err
}
@ -247,6 +250,7 @@ func (bb *testBlockBuilder) BuildUTXOInvalidBlock(parentHashes []*externalapi.Do
return nil, err
}
blueWork := ghostdagData.BlueWork()
blueScore := ghostdagData.BlueScore()
// We use the genesis coinbase so that we'll have something to build merkle root and a new coinbase with
genesisTransactions := bb.testConsensus.DAGParams().GenesisBlock.Transactions
@ -258,12 +262,8 @@ func (bb *testBlockBuilder) BuildUTXOInvalidBlock(parentHashes []*externalapi.Do
if err != nil {
return nil, err
}
finalityPoint, err := bb.finalityManager.FinalityPoint(stagingArea, tempBlockHash, false)
if err != nil {
return nil, err
}
header, err := bb.buildUTXOInvalidHeader(stagingArea, parentHashes, bits, daaScore, blueWork, finalityPoint, transactions)
header, err := bb.buildUTXOInvalidHeader(stagingArea, parentHashes, bits, daaScore, blueScore, blueWork, transactions)
if err != nil {
return nil, err
}

View File

@ -74,8 +74,9 @@ func TestBlockStatus(t *testing.T) {
disqualifiedBlock.Header.Bits(),
disqualifiedBlock.Header.Nonce(),
disqualifiedBlock.Header.DAAScore(),
disqualifiedBlock.Header.BlueScore(),
disqualifiedBlock.Header.BlueWork(),
disqualifiedBlock.Header.FinalityPoint(),
disqualifiedBlock.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(disqualifiedBlock, true)
@ -100,8 +101,9 @@ func TestBlockStatus(t *testing.T) {
disqualifiedBlock.Header.Bits(),
disqualifiedBlock.Header.Nonce(),
disqualifiedBlock.Header.DAAScore(),
disqualifiedBlock.Header.BlueScore(),
disqualifiedBlock.Header.BlueWork(),
disqualifiedBlock.Header.FinalityPoint(),
disqualifiedBlock.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(invalidBlock, true)

View File

@ -22,8 +22,18 @@ func (bp *blockProcessor) validateAndInsertImportedPruningPoint(
newPruningPointHash)
}
arePruningPointsInValidChain, err := bp.pruningManager.ArePruningPointsInValidChain(stagingArea)
if err != nil {
return err
}
if !arePruningPointsInValidChain {
return errors.Wrapf(ruleerrors.ErrInvalidPruningPointsChain, "pruning points do not compose a valid "+
"chain to genesis")
}
log.Infof("Updating consensus state manager according to the new pruning point %s", newPruningPointHash)
err = bp.consensusStateManager.ImportPruningPoint(stagingArea, newPruningPointHash)
err = bp.consensusStateManager.ImportPruningPointUTXOSet(stagingArea, newPruningPointHash)
if err != nil {
return err
}

View File

@ -38,6 +38,16 @@ func addBlock(tc testapi.TestConsensus, parentHashes []*externalapi.DomainHash,
func TestValidateAndInsertImportedPruningPoint(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
syncConsensuses := func(tcSyncer, tcSyncee testapi.TestConsensus) {
pruningPointHeaders, err := tcSyncer.PruningPointHeaders()
if err != nil {
t.Fatalf("PruningPointHeaders: %+v", err)
}
err = tcSyncee.ImportPruningPoints(pruningPointHeaders)
if err != nil {
t.Fatalf("PruningPointHeaders: %+v", err)
}
pointAndItsAnticoneWithTrustedData, err := tcSyncer.PruningPointAndItsAnticoneWithTrustedData()
if err != nil {
t.Fatalf("PruningPointAndItsAnticoneWithTrustedData: %+v", err)
@ -352,6 +362,16 @@ func TestValidateAndInsertPruningPointWithSideBlocks(t *testing.T) {
t.Fatalf("Unexpected pruning point %s", pruningPoint)
}
pruningPointHeaders, err := tcSyncer.PruningPointHeaders()
if err != nil {
t.Fatalf("PruningPointHeaders: %+v", err)
}
err = tcSyncee.ImportPruningPoints(pruningPointHeaders)
if err != nil {
t.Fatalf("PruningPointHeaders: %+v", err)
}
pointAndItsAnticoneWithTrustedData, err := tcSyncer.PruningPointAndItsAnticoneWithTrustedData()
if err != nil {
t.Fatalf("PruningPointAndItsAnticoneWithTrustedData: %+v", err)

View File

@ -4,7 +4,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/consensus/utils/virtual"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/pkg/errors"
@ -31,10 +30,6 @@ func (v *blockValidator) ValidateBodyInContext(stagingArea *model.StagingArea, b
if err != nil {
return err
}
err = v.checkCoinbaseBlueScore(stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return err
}
}
return nil
}
@ -141,25 +136,3 @@ func (v *blockValidator) checkBlockTransactions(
return nil
}
func (v *blockValidator) checkCoinbaseBlueScore(stagingArea *model.StagingArea,
blockHash *externalapi.DomainHash, isBlockWithTrustedData bool) error {
block, err := v.blockStore.Block(v.databaseContext, stagingArea, blockHash)
if err != nil {
return err
}
coinbaseBlueScore, _, err := v.coinbaseManager.ExtractCoinbaseDataAndBlueScore(block.Transactions[transactionhelper.CoinbaseTransactionIndex])
if err != nil {
return err
}
blockGHOSTDAGData, err := v.ghostdagDataStore.Get(v.databaseContext, stagingArea, blockHash, isBlockWithTrustedData)
if err != nil {
return err
}
expectedBlueScore := blockGHOSTDAGData.BlueScore()
if coinbaseBlueScore != expectedBlueScore {
return errors.Wrapf(ruleerrors.ErrUnexpectedBlueScore, "block blue score of %d is not the expected value of %d", coinbaseBlueScore, expectedBlueScore)
}
return nil
}

View File

@ -48,7 +48,7 @@ func (v *blockValidator) ValidateBodyInIsolation(stagingArea *model.StagingArea,
return err
}
err = v.checkCoinbase(block)
err = v.checkCoinbaseBlueScore(block)
if err != nil {
return err
}
@ -91,11 +91,15 @@ func (v *blockValidator) ValidateBodyInIsolation(stagingArea *model.StagingArea,
return nil
}
func (v *blockValidator) checkCoinbase(block *externalapi.DomainBlock) error {
_, _, err := v.coinbaseManager.ExtractCoinbaseDataAndBlueScore(block.Transactions[transactionhelper.CoinbaseTransactionIndex])
func (v *blockValidator) checkCoinbaseBlueScore(block *externalapi.DomainBlock) error {
coinbaseBlueScore, _, err := v.coinbaseManager.ExtractCoinbaseDataAndBlueScore(block.Transactions[transactionhelper.CoinbaseTransactionIndex])
if err != nil {
return err
}
if coinbaseBlueScore != block.Header.BlueScore() {
return errors.Wrapf(ruleerrors.ErrUnexpectedCoinbaseBlueScore, "block blue score of %d is not the expected "+
"value of %d", coinbaseBlueScore, block.Header.BlueScore())
}
return nil
}

View File

@ -171,6 +171,7 @@ var unOrderedParentsBlock = externalapi.DomainBlock{
0x207fffff,
0x1,
0,
9,
big.NewInt(0),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -442,6 +443,7 @@ var exampleValidBlock = externalapi.DomainBlock{
0x207fffff,
1,
0,
9,
big.NewInt(0),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -751,6 +753,7 @@ var blockWithWrongTxOrder = externalapi.DomainBlock{
0x207fffff,
1,
0,
9,
big.NewInt(0),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -1356,6 +1359,7 @@ func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consens
0x207fffff,
0x1,
0,
0,
big.NewInt(0),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View File

@ -2,7 +2,6 @@ package blockvalidator
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
@ -78,15 +77,24 @@ func (v *blockValidator) ValidateHeaderInContext(stagingArea *model.StagingArea,
if err != nil {
return err
}
err = v.checkBlueWork(stagingArea, blockHash, header, isBlockWithTrustedData)
err = v.checkBlueWork(stagingArea, blockHash, header)
if err != nil {
return err
}
err = v.checkFinalityPoint(stagingArea, blockHash, header, isBlockWithTrustedData)
err = v.checkHeaderBlueScore(stagingArea, blockHash, header)
if err != nil {
return err
}
if !isBlockWithTrustedData {
err = v.validateHeaderPruningPoint(stagingArea, blockHash)
if err != nil {
return err
}
}
return nil
}
@ -189,9 +197,9 @@ func (v *blockValidator) checkDAAScore(stagingArea *model.StagingArea, blockHash
}
func (v *blockValidator) checkBlueWork(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
header externalapi.BlockHeader, isBlockWithTrustedData bool) error {
header externalapi.BlockHeader) error {
ghostdagData, err := v.ghostdagDataStore.Get(v.databaseContext, stagingArea, blockHash, isBlockWithTrustedData)
ghostdagData, err := v.ghostdagDataStore.Get(v.databaseContext, stagingArea, blockHash, false)
if err != nil {
return err
}
@ -202,19 +210,16 @@ func (v *blockValidator) checkBlueWork(stagingArea *model.StagingArea, blockHash
return nil
}
func (v *blockValidator) checkFinalityPoint(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
header externalapi.BlockHeader, isBlockWithTrustedData bool) error {
func (v *blockValidator) checkHeaderBlueScore(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
header externalapi.BlockHeader) error {
expectedFinalityPoint, err := v.finalityManager.FinalityPoint(stagingArea, blockHash, isBlockWithTrustedData)
ghostdagData, err := v.ghostdagDataStore.Get(v.databaseContext, stagingArea, blockHash, false)
if err != nil {
return err
}
if expectedFinalityPoint.Equal(model.VirtualGenesisBlockHash) {
return nil
}
if !header.FinalityPoint().Equal(expectedFinalityPoint) {
return errors.Wrapf(ruleerrors.ErrUnexpectedFinalityPoint, "block finality point of %s is not the expected hash of %s", header.FinalityPoint(), expectedFinalityPoint)
if header.BlueScore() != ghostdagData.BlueScore() {
return errors.Wrapf(ruleerrors.ErrUnexpectedBlueWork, "block blue work of %d is not the expected "+
"value of %d", header.BlueWork(), ghostdagData.BlueScore())
}
return nil
}

View File

@ -118,6 +118,7 @@ func TestCheckParentsIncest(t *testing.T) {
0,
0,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
),
@ -140,6 +141,7 @@ func TestCheckParentsIncest(t *testing.T) {
0,
0,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
),

View File

@ -67,8 +67,9 @@ func TestCheckBlockVersion(t *testing.T) {
block.Header.Bits(),
block.Header.Nonce(),
block.Header.DAAScore(),
block.Header.BlueScore(),
block.Header.BlueWork(),
block.Header.FinalityPoint(),
block.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(block, true)
@ -107,8 +108,9 @@ func TestCheckBlockTimestampInIsolation(t *testing.T) {
block.Header.Bits(),
block.Header.Nonce(),
block.Header.DAAScore(),
block.Header.BlueScore(),
block.Header.BlueWork(),
block.Header.FinalityPoint(),
block.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(block, true)

View File

@ -35,6 +35,7 @@ type blockValidator struct {
pruningStore model.PruningStore
reachabilityManager model.ReachabilityManager
finalityManager model.FinalityManager
pruningManager model.PruningManager
blockStore model.BlockStore
ghostdagDataStore model.GHOSTDAGDataStore
@ -68,9 +69,9 @@ func New(powMax *big.Int,
mergeDepthManager model.MergeDepthManager,
reachabilityManager model.ReachabilityManager,
finalityManager model.FinalityManager,
pruningManager model.PruningManager,
pruningStore model.PruningStore,
blockStore model.BlockStore,
ghostdagDataStore model.GHOSTDAGDataStore,
blockHeaderStore model.BlockHeaderStore,
@ -103,6 +104,7 @@ func New(powMax *big.Int,
mergeDepthManager: mergeDepthManager,
reachabilityManager: reachabilityManager,
finalityManager: finalityManager,
pruningManager: pruningManager,
pruningStore: pruningStore,
blockStore: blockStore,

View File

@ -0,0 +1,30 @@
package blockvalidator
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/pkg/errors"
)
func (v *blockValidator) validateHeaderPruningPoint(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) error {
if blockHash.Equal(v.genesisHash) {
return nil
}
header, err := v.blockHeaderStore.BlockHeader(v.databaseContext, stagingArea, blockHash)
if err != nil {
return err
}
expectedPruningPoint, err := v.pruningManager.ExpectedHeaderPruningPoint(stagingArea, blockHash)
if err != nil {
return err
}
if !header.PruningPoint().Equal(expectedPruningPoint) {
return errors.Wrapf(ruleerrors.ErrUnexpectedPruningPoint, "block pruning point of %s is not the expected hash of %s", header.PruningPoint(), expectedPruningPoint)
}
return nil
}

View File

@ -60,8 +60,9 @@ func TestPOW(t *testing.T) {
difficulty.BigToCompact(abovePowMaxTarget),
abovePowMaxBlock.Header.Nonce(),
abovePowMaxBlock.Header.DAAScore(),
abovePowMaxBlock.Header.BlueScore(),
abovePowMaxBlock.Header.BlueWork(),
abovePowMaxBlock.Header.FinalityPoint(),
abovePowMaxBlock.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(abovePowMaxBlock, true)
@ -84,8 +85,9 @@ func TestPOW(t *testing.T) {
0x00800000,
negativeTargetBlock.Header.Nonce(),
negativeTargetBlock.Header.DAAScore(),
negativeTargetBlock.Header.BlueScore(),
negativeTargetBlock.Header.BlueWork(),
negativeTargetBlock.Header.FinalityPoint(),
negativeTargetBlock.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(negativeTargetBlock, true)
@ -151,8 +153,9 @@ func TestCheckParentHeadersExist(t *testing.T) {
orphanBlock.Header.Bits(),
orphanBlock.Header.Nonce(),
orphanBlock.Header.DAAScore(),
orphanBlock.Header.BlueScore(),
orphanBlock.Header.BlueWork(),
orphanBlock.Header.FinalityPoint(),
orphanBlock.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(orphanBlock, true)
@ -182,8 +185,9 @@ func TestCheckParentHeadersExist(t *testing.T) {
orphanBlock.Header.Bits(),
orphanBlock.Header.Nonce(),
orphanBlock.Header.DAAScore(),
orphanBlock.Header.BlueScore(),
orphanBlock.Header.BlueWork(),
orphanBlock.Header.FinalityPoint(),
orphanBlock.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(invalidBlock, true)
@ -208,8 +212,9 @@ func TestCheckParentHeadersExist(t *testing.T) {
invalidBlockChild.Header.Bits(),
invalidBlockChild.Header.Nonce(),
invalidBlockChild.Header.DAAScore(),
invalidBlockChild.Header.BlueScore(),
invalidBlockChild.Header.BlueWork(),
invalidBlockChild.Header.FinalityPoint(),
invalidBlockChild.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(invalidBlockChild, true)
@ -251,7 +256,32 @@ func TestCheckPruningPointViolation(t *testing.T) {
}
}
_, _, err = tc.AddUTXOInvalidBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash})
tips, err := tc.Tips()
if err != nil {
t.Fatalf("Tips: %+v", err)
}
blockWithPruningViolation, _, err := tc.BuildBlockWithParents(tips, nil, nil)
if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err)
}
blockWithPruningViolation.Header = blockheader.NewImmutableBlockHeader(
blockWithPruningViolation.Header.Version(),
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{consensusConfig.GenesisHash}},
blockWithPruningViolation.Header.HashMerkleRoot(),
blockWithPruningViolation.Header.AcceptedIDMerkleRoot(),
blockWithPruningViolation.Header.UTXOCommitment(),
blockWithPruningViolation.Header.TimeInMilliseconds(),
blockWithPruningViolation.Header.Bits(),
blockWithPruningViolation.Header.Nonce(),
blockWithPruningViolation.Header.DAAScore(),
blockWithPruningViolation.Header.BlueScore(),
blockWithPruningViolation.Header.BlueWork(),
blockWithPruningViolation.Header.PruningPoint(),
)
_, err = tc.ValidateAndInsertBlock(blockWithPruningViolation, true)
if !errors.Is(err, ruleerrors.ErrPruningPointViolation) {
t.Fatalf("Unexpected error: %+v", err)
}

View File

@ -163,7 +163,6 @@ func (csm *consensusStateManager) applyMergeSetBlocks(stagingArea *model.Staging
for i, mergeSetBlock := range mergeSetBlocks {
mergeSetBlockHash := consensushashing.BlockHash(mergeSetBlock)
log.Tracef("Applying merge set block %s", mergeSetBlockHash)
blockAcceptanceData := &externalapi.BlockAcceptanceData{
BlockHash: mergeSetBlockHash,
TransactionAcceptanceData: make([]*externalapi.TransactionAcceptanceData, len(mergeSetBlock.Transactions)),

View File

@ -7,7 +7,6 @@ import (
// consensusStateManager manages the node's consensus state
type consensusStateManager struct {
pruningDepth uint64
maxBlockParents externalapi.KType
mergeSetSizeLimit uint64
genesisHash *externalapi.DomainHash
@ -18,7 +17,6 @@ type consensusStateManager struct {
dagTraversalManager model.DAGTraversalManager
pastMedianTimeManager model.PastMedianTimeManager
transactionValidator model.TransactionValidator
blockValidator model.BlockValidator
coinbaseManager model.CoinbaseManager
mergeDepthManager model.MergeDepthManager
finalityManager model.FinalityManager
@ -43,7 +41,6 @@ type consensusStateManager struct {
// New instantiates a new ConsensusStateManager
func New(
databaseContext model.DBManager,
pruningDepth uint64,
maxBlockParents externalapi.KType,
mergeSetSizeLimit uint64,
genesisHash *externalapi.DomainHash,
@ -53,7 +50,6 @@ func New(
dagTraversalManager model.DAGTraversalManager,
pastMedianTimeManager model.PastMedianTimeManager,
transactionValidator model.TransactionValidator,
blockValidator model.BlockValidator,
coinbaseManager model.CoinbaseManager,
mergeDepthManager model.MergeDepthManager,
finalityManager model.FinalityManager,
@ -73,7 +69,6 @@ func New(
daaBlocksStore model.DAABlocksStore) (model.ConsensusStateManager, error) {
csm := &consensusStateManager{
pruningDepth: pruningDepth,
maxBlockParents: maxBlockParents,
mergeSetSizeLimit: mergeSetSizeLimit,
genesisHash: genesisHash,
@ -84,7 +79,6 @@ func New(
dagTraversalManager: dagTraversalManager,
pastMedianTimeManager: pastMedianTimeManager,
transactionValidator: transactionValidator,
blockValidator: blockValidator,
coinbaseManager: coinbaseManager,
mergeDepthManager: mergeDepthManager,
finalityManager: finalityManager,

View File

@ -12,11 +12,11 @@ import (
"github.com/pkg/errors"
)
func (csm *consensusStateManager) ImportPruningPoint(stagingArea *model.StagingArea, newPruningPoint *externalapi.DomainHash) error {
onEnd := logger.LogAndMeasureExecutionTime(log, "ImportPruningPoint")
func (csm *consensusStateManager) ImportPruningPointUTXOSet(stagingArea *model.StagingArea, newPruningPoint *externalapi.DomainHash) error {
onEnd := logger.LogAndMeasureExecutionTime(log, "ImportPruningPointUTXOSet")
defer onEnd()
err := csm.importPruningPoint(stagingArea, newPruningPoint)
err := csm.importPruningPointUTXOSet(stagingArea, newPruningPoint)
if err != nil {
return err
}
@ -29,11 +29,9 @@ func (csm *consensusStateManager) ImportPruningPoint(stagingArea *model.StagingA
return nil
}
func (csm *consensusStateManager) importPruningPoint(
stagingArea *model.StagingArea, newPruningPoint *externalapi.DomainHash) error {
log.Debugf("importPruningPoint start")
defer log.Debugf("importPruningPoint end")
func (csm *consensusStateManager) importPruningPointUTXOSet(stagingArea *model.StagingArea, newPruningPoint *externalapi.DomainHash) error {
log.Debugf("importPruningPointUTXOSet start")
defer log.Debugf("importPruningPointUTXOSet end")
// TODO: We should validate the imported pruning point doesn't violate finality as part of the headers proof.
@ -70,10 +68,6 @@ func (csm *consensusStateManager) importPruningPoint(
log.Debugf("Updating the new pruning point to be the new virtual diff parent with an empty diff")
csm.stageDiff(stagingArea, newPruningPoint, utxo.NewUTXODiff(), nil)
log.Debugf("Staging the new pruning point %s", newPruningPoint)
csm.pruningStore.StagePruningPoint(stagingArea, newPruningPoint)
csm.pruningStore.StagePruningPointCandidate(stagingArea, newPruningPoint)
log.Debugf("Populating the pruning point with UTXO entries")
importedPruningPointUTXOIterator, err := csm.pruningStore.ImportedPruningPointUTXOIterator(csm.databaseContext)
if err != nil {
@ -133,6 +127,23 @@ func (csm *consensusStateManager) importPruningPoint(
return nil
}
func (csm *consensusStateManager) ImportPruningPoints(stagingArea *model.StagingArea, pruningPoints []externalapi.BlockHeader) error {
for i, header := range pruningPoints {
blockHash := consensushashing.HeaderHash(header)
err := csm.pruningStore.StagePruningPointByIndex(csm.databaseContext, stagingArea, blockHash, uint64(i))
if err != nil {
return err
}
csm.blockHeaderStore.Stage(stagingArea, blockHash, header)
}
lastPruningPointHeader := pruningPoints[len(pruningPoints)-1]
csm.pruningStore.StagePruningPointCandidate(stagingArea, consensushashing.HeaderHash(lastPruningPointHeader))
return nil
}
func (csm *consensusStateManager) applyImportedPruningPointUTXOSet(stagingArea *model.StagingArea, newPruningPoint *externalapi.DomainHash) error {
dbTx, err := csm.databaseContext.Begin()
if err != nil {

View File

@ -215,7 +215,7 @@ func (csm *consensusStateManager) resolveSingleBlockStatus(stagingArea *model.St
err = csm.verifyUTXO(stagingArea, block, blockHash, pastUTXOSet, acceptanceData, multiset)
if err != nil {
if errors.As(err, &ruleerrors.RuleError{}) {
log.Warnf("UTXO verification for block %s failed: %s", blockHash, err)
log.Debugf("UTXO verification for block %s failed: %s", blockHash, err)
return externalapi.StatusDisqualifiedFromChain, nil, nil
}
return 0, nil, err

View File

@ -160,9 +160,9 @@ func TestDoubleSpends(t *testing.T) {
// TestTransactionAcceptance checks that block transactions are accepted correctly when the merge set is sorted topologically.
// DAG diagram:
// genesis <- blockA <- blockB <- blockC <- ..(chain of k-blocks).. lastBlockInChain <- blockD <- blockE <- blockF
// ^ ^ |
// | redBlock <------------------------ blueChildOfRedBlock <--------------------
// genesis <- blockA <- blockB <- blockC <- ..(chain of k-blocks).. lastBlockInChain <- blockD <- blockE <- blockF <- blockG
// ^ ^ |
// | redBlock <------------------------ blueChildOfRedBlock <-------------------------------
func TestTransactionAcceptance(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
stagingArea := model.NewStagingArea()
@ -244,8 +244,12 @@ func TestTransactionAcceptance(t *testing.T) {
if err != nil {
t.Fatalf("Error creating blockD : %+v", err)
}
blockHashE, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockHashD}, nil, nil)
if err != nil {
t.Fatalf("Error creating blockD : %+v", err)
}
blockEScriptPublicKey := &externalapi.ScriptPublicKey{Script: []byte{4}, Version: 0}
blockHashE, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockHashD},
blockHashF, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockHashE},
&externalapi.DomainCoinbaseData{
ScriptPublicKey: blockEScriptPublicKey,
ExtraData: nil,
@ -254,7 +258,7 @@ func TestTransactionAcceptance(t *testing.T) {
t.Fatalf("Error creating blockE: %+v", err)
}
blockFScriptPublicKey := &externalapi.ScriptPublicKey{Script: []byte{5}, Version: 0}
blockHashF, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockHashE, hashBlueChildOfRedBlock},
blockHashG, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{blockHashF, hashBlueChildOfRedBlock},
&externalapi.DomainCoinbaseData{
ScriptPublicKey: blockFScriptPublicKey,
ExtraData: nil,
@ -263,7 +267,7 @@ func TestTransactionAcceptance(t *testing.T) {
t.Fatalf("Error creating blockF: %+v", err)
}
acceptanceData, err := testConsensus.AcceptanceDataStore().Get(testConsensus.DatabaseContext(), stagingArea, blockHashF)
acceptanceData, err := testConsensus.AcceptanceDataStore().Get(testConsensus.DatabaseContext(), stagingArea, blockHashG)
if err != nil {
t.Fatalf("Error getting acceptance data: %+v", err)
}
@ -271,7 +275,7 @@ func TestTransactionAcceptance(t *testing.T) {
if err != nil {
t.Fatalf("Error getting blueChildOfRedBlock: %+v", err)
}
blockE, err := testConsensus.GetBlock(blockHashE)
blockE, err := testConsensus.GetBlock(blockHashF)
if err != nil {
t.Fatalf("Error getting blockE: %+v", err)
}
@ -279,16 +283,16 @@ func TestTransactionAcceptance(t *testing.T) {
if err != nil {
t.Fatalf("Error getting redBlock: %+v", err)
}
blockF, err := testConsensus.GetBlock(blockHashF)
blockF, err := testConsensus.GetBlock(blockHashG)
if err != nil {
t.Fatalf("Error getting blockF: %+v", err)
}
updatedDAAScoreVirtualBlock := 25
updatedDAAScoreVirtualBlock := 26
//We expect the second transaction in the "blue block" (blueChildOfRedBlock) to be accepted because the merge set is ordered topologically
//and the red block is ordered topologically before the "blue block" so the input is known in the UTXOSet.
expectedAcceptanceData := externalapi.AcceptanceData{
{
BlockHash: blockHashE,
BlockHash: blockHashF,
TransactionAcceptanceData: []*externalapi.TransactionAcceptanceData{
{
Transaction: blockE.Transactions[0],

View File

@ -60,32 +60,104 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "C", "D", "H", "G", "B"},
expectedWindow: []string{"F", "C", "H", "D", "G", "B"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "C", "D", "H", "G", "B"},
expectedWindow: []string{"I", "F", "C", "H", "D", "G", "B"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "C", "D", "H", "G", "B"},
expectedWindow: []string{"J", "I", "F", "C", "H", "D", "G", "B"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "C", "D", "H", "G", "B"},
expectedWindow: []string{"K", "J", "I", "F", "C", "H", "D", "G", "B"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "C", "D", "H", "G", "B"},
expectedWindow: []string{"L", "K", "J", "I", "F", "C", "H", "D", "G", "B"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "C", "D", "H", "G"},
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "C", "H", "D", "G"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "C", "H", "D"},
},
},
dagconfig.TestnetParams.Name: {
{
parents: []string{"A"},
id: "B",
expectedWindow: []string{},
},
{
parents: []string{"B"},
id: "C",
expectedWindow: []string{"B"},
},
{
parents: []string{"B"},
id: "D",
expectedWindow: []string{"B"},
},
{
parents: []string{"C", "D"},
id: "E",
expectedWindow: []string{"C", "D", "B"},
},
{
parents: []string{"C", "D"},
id: "F",
expectedWindow: []string{"C", "D", "B"},
},
{
parents: []string{"A"},
id: "G",
expectedWindow: []string{},
},
{
parents: []string{"G"},
id: "H",
expectedWindow: []string{"G"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "C", "D", "H", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "C", "D", "H", "B"},
},
{
parents: []string{"N"},
@ -93,7 +165,7 @@ func TestBlockWindow(t *testing.T) {
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "C", "D", "H"},
},
},
dagconfig.TestnetParams.Name: {
dagconfig.DevnetParams.Name: {
{
parents: []string{"A"},
id: "B",
@ -129,6 +201,78 @@ func TestBlockWindow(t *testing.T) {
id: "H",
expectedWindow: []string{"G"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "D", "C", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "D", "C", "B"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "D", "C"},
},
},
dagconfig.SimnetParams.Name: {
{
parents: []string{"A"},
id: "B",
expectedWindow: []string{},
},
{
parents: []string{"B"},
id: "C",
expectedWindow: []string{"B"},
},
{
parents: []string{"B"},
id: "D",
expectedWindow: []string{"B"},
},
{
parents: []string{"D", "C"},
id: "E",
expectedWindow: []string{"D", "C", "B"},
},
{
parents: []string{"D", "C"},
id: "F",
expectedWindow: []string{"D", "C", "B"},
},
{
parents: []string{"A"},
id: "G",
expectedWindow: []string{},
},
{
parents: []string{"G"},
id: "H",
expectedWindow: []string{"G"},
},
{
parents: []string{"H", "F"},
id: "I",
@ -165,150 +309,6 @@ func TestBlockWindow(t *testing.T) {
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
},
},
dagconfig.DevnetParams.Name: {
{
parents: []string{"A"},
id: "B",
expectedWindow: []string{},
},
{
parents: []string{"B"},
id: "C",
expectedWindow: []string{"B"},
},
{
parents: []string{"B"},
id: "D",
expectedWindow: []string{"B"},
},
{
parents: []string{"C", "D"},
id: "E",
expectedWindow: []string{"D", "C", "B"},
},
{
parents: []string{"C", "D"},
id: "F",
expectedWindow: []string{"D", "C", "B"},
},
{
parents: []string{"A"},
id: "G",
expectedWindow: []string{},
},
{
parents: []string{"G"},
id: "H",
expectedWindow: []string{"G"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "B"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
},
},
dagconfig.SimnetParams.Name: {
{
parents: []string{"A"},
id: "B",
expectedWindow: []string{},
},
{
parents: []string{"B"},
id: "C",
expectedWindow: []string{"B"},
},
{
parents: []string{"B"},
id: "D",
expectedWindow: []string{"B"},
},
{
parents: []string{"D", "C"},
id: "E",
expectedWindow: []string{"C", "D", "B"},
},
{
parents: []string{"D", "C"},
id: "F",
expectedWindow: []string{"C", "D", "B"},
},
{
parents: []string{"A"},
id: "G",
expectedWindow: []string{},
},
{
parents: []string{"G"},
id: "H",
expectedWindow: []string{"G"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "H", "C", "D", "B", "G"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "H", "C", "D", "B", "G"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "H", "C", "D", "B", "G"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "H", "C", "D", "B", "G"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "H", "C", "D", "B", "G"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "H", "C", "D", "B"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "H", "C", "D"},
},
},
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.K = 1

View File

@ -120,6 +120,7 @@ func TestGHOSTDAG(t *testing.T) {
genesisHeader.Bits(),
0,
0,
0,
big.NewInt(0),
nil,
)
@ -218,6 +219,7 @@ func TestBlueWork(t *testing.T) {
0,
0,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
)
@ -246,6 +248,7 @@ func TestBlueWork(t *testing.T) {
math.MaxUint32, // Put a very high difficulty so the chain that contains this block will have a very high blue work
0,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
)

View File

@ -36,10 +36,10 @@ func TestPruning(t *testing.T) {
dagconfig.SimnetParams.Name: "1582",
},
"dag-for-test-pruning.json": {
dagconfig.MainnetParams.Name: "503",
dagconfig.TestnetParams.Name: "503",
dagconfig.MainnetParams.Name: "502",
dagconfig.TestnetParams.Name: "502",
dagconfig.DevnetParams.Name: "503",
dagconfig.SimnetParams.Name: "503",
dagconfig.SimnetParams.Name: "502",
},
}

View File

@ -3,6 +3,7 @@ package pruningmanager
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/multiset"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/domain/consensus/utils/virtual"
@ -16,23 +17,24 @@ import (
type pruningManager struct {
databaseContext model.DBManager
dagTraversalManager model.DAGTraversalManager
dagTopologyManager model.DAGTopologyManager
consensusStateManager model.ConsensusStateManager
dagTraversalManager model.DAGTraversalManager
dagTopologyManager model.DAGTopologyManager
consensusStateManager model.ConsensusStateManager
finalityManager model.FinalityManager
consensusStateStore model.ConsensusStateStore
ghostdagDataStore model.GHOSTDAGDataStore
pruningStore model.PruningStore
blockStatusStore model.BlockStatusStore
headerSelectedTipStore model.HeaderSelectedTipStore
blocksWithTrustedDataDAAWindowStore model.BlocksWithTrustedDataDAAWindowStore
multiSetStore model.MultisetStore
acceptanceDataStore model.AcceptanceDataStore
blocksStore model.BlockStore
blockHeaderStore model.BlockHeaderStore
utxoDiffStore model.UTXODiffStore
daaBlocksStore model.DAABlocksStore
reachabilityDataStore model.ReachabilityDataStore
multiSetStore model.MultisetStore
acceptanceDataStore model.AcceptanceDataStore
blocksStore model.BlockStore
blockHeaderStore model.BlockHeaderStore
utxoDiffStore model.UTXODiffStore
daaBlocksStore model.DAABlocksStore
reachabilityDataStore model.ReachabilityDataStore
isArchivalNode bool
genesisHash *externalapi.DomainHash
@ -50,6 +52,7 @@ func New(
dagTraversalManager model.DAGTraversalManager,
dagTopologyManager model.DAGTopologyManager,
consensusStateManager model.ConsensusStateManager,
finalityManager model.FinalityManager,
consensusStateStore model.ConsensusStateStore,
ghostdagDataStore model.GHOSTDAGDataStore,
@ -79,6 +82,7 @@ func New(
dagTraversalManager: dagTraversalManager,
dagTopologyManager: dagTopologyManager,
consensusStateManager: consensusStateManager,
finalityManager: finalityManager,
consensusStateStore: consensusStateStore,
ghostdagDataStore: ghostdagDataStore,
@ -104,8 +108,6 @@ func New(
}
}
// FindNextPruningPoint finds the next pruning point from the
// given blockHash
func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.StagingArea) error {
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.UpdatePruningPointByVirtual")
defer onEnd()
@ -131,24 +133,24 @@ func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.Staging
return nil
}
virtualGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, model.VirtualBlockHash, false)
if err != nil {
return err
}
newPruningPoint, newCandidate, err := pm.NextPruningPointAndCandidateByBlockHash(stagingArea, virtualGHOSTDAGData.SelectedParent())
if err != nil {
return err
}
currentCandidate, err := pm.pruningPointCandidate(stagingArea)
if err != nil {
return err
}
currentCandidateGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, currentCandidate, false)
if err != nil {
return err
}
virtual, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, model.VirtualBlockHash, false)
if err != nil {
return err
}
virtualSelectedParent, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, virtual.SelectedParent(), false)
if err != nil {
return err
if !newCandidate.Equal(currentCandidate) {
log.Debugf("Staged a new pruning candidate, old: %s, new: %s", currentCandidate, newCandidate)
pm.pruningStore.StagePruningPointCandidate(stagingArea, newCandidate)
}
currentPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea)
@ -156,14 +158,49 @@ func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.Staging
return err
}
currentPruningPointGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, currentPruningPoint, false)
if err != nil {
return err
if !newPruningPoint.Equal(currentPruningPoint) {
log.Debugf("Moving pruning point from %s to %s", currentPruningPoint, newPruningPoint)
err = pm.savePruningPoint(stagingArea, newPruningPoint)
if err != nil {
return err
}
}
iterator, err := pm.dagTraversalManager.SelectedChildIterator(stagingArea, virtual.SelectedParent(), currentCandidate)
return nil
}
func (pm *pruningManager) NextPruningPointAndCandidateByBlockHash(stagingArea *model.StagingArea,
blockHash *externalapi.DomainHash) (*externalapi.DomainHash, *externalapi.DomainHash, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.NextPruningPointAndCandidateByBlockHash")
defer onEnd()
currentCandidate, err := pm.pruningPointCandidate(stagingArea)
if err != nil {
return err
return nil, nil, err
}
ghostdagData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, blockHash, false)
if err != nil {
return nil, nil, err
}
currentPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea)
if err != nil {
return nil, nil, err
}
currentPruningPointGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, currentPruningPoint, false)
if err != nil {
return nil, nil, err
}
// We iterate until the selected parent of the given block, in order to allow a situation where the given block hash
// belongs to the virtual. This shouldn't change anything since the max blue score difference between a block and its
// selected parent is K, and K << pm.pruningDepth.
iterator, err := pm.dagTraversalManager.SelectedChildIterator(stagingArea, ghostdagData.SelectedParent(), currentCandidate)
if err != nil {
return nil, nil, err
}
defer iterator.Close()
@ -180,26 +217,25 @@ func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.Staging
// that a block that was once in depth of pm.pruningDepth cannot be
// reorged without causing a finality conflict first.
newCandidate := currentCandidate
newCandidateGHOSTDAGData := currentCandidateGHOSTDAGData
newPruningPoint := currentPruningPoint
newPruningPointGHOSTDAGData := currentPruningPointGHOSTDAGData
for ok := iterator.First(); ok; ok = iterator.Next() {
selectedChild, err := iterator.Get()
if err != nil {
return err
return nil, nil, err
}
selectedChildGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, selectedChild, false)
if err != nil {
return err
return nil, nil, err
}
if virtualSelectedParent.BlueScore()-selectedChildGHOSTDAGData.BlueScore() < pm.pruningDepth {
if ghostdagData.BlueScore()-selectedChildGHOSTDAGData.BlueScore() < pm.pruningDepth {
break
}
newCandidate = selectedChild
newCandidateGHOSTDAGData = selectedChildGHOSTDAGData
newCandidateGHOSTDAGData := selectedChildGHOSTDAGData
// We move the pruning point every time the candidate's finality score is
// bigger than the current pruning point finality score.
@ -209,26 +245,7 @@ func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.Staging
}
}
if !newCandidate.Equal(currentCandidate) {
log.Debugf("Staged a new pruning candidate, old: %s, new: %s", currentCandidate, newCandidate)
pm.pruningStore.StagePruningPointCandidate(stagingArea, newCandidate)
}
// We move the pruning point every time the candidate's finality score is
// bigger than the current pruning point finality score.
if pm.finalityScore(newCandidateGHOSTDAGData.BlueScore()) <= pm.finalityScore(currentPruningPointGHOSTDAGData.BlueScore()) {
return nil
}
if !newPruningPoint.Equal(currentPruningPoint) {
log.Debugf("Moving pruning point from %s to %s", currentPruningPoint, newPruningPoint)
err = pm.savePruningPoint(stagingArea, newPruningPoint)
if err != nil {
return err
}
}
return nil
return newPruningPoint, newCandidate, nil
}
func (pm *pruningManager) isInPruningFutureOrInVirtualPast(stagingArea *model.StagingArea, block *externalapi.DomainHash,
@ -356,16 +373,10 @@ func (pm *pruningManager) pruneTips(stagingArea *model.StagingArea, pruningPoint
func (pm *pruningManager) savePruningPoint(stagingArea *model.StagingArea, pruningPointHash *externalapi.DomainHash) error {
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.savePruningPoint")
defer onEnd()
// If pruningPointHash is the genesis then there's no pruning point set right now.
if !pruningPointHash.Equal(pm.genesisHash) {
previousPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea)
if err != nil {
return err
}
pm.pruningStore.StagePreviousPruningPoint(stagingArea, previousPruningPoint)
err := pm.pruningStore.StagePruningPoint(pm.databaseContext, stagingArea, pruningPointHash)
if err != nil {
return err
}
pm.pruningStore.StagePruningPoint(stagingArea, pruningPointHash)
pm.pruningStore.StageStartUpdatingPruningPointUTXOSet(stagingArea)
return nil
@ -435,6 +446,116 @@ func (pm *pruningManager) IsValidPruningPoint(stagingArea *model.StagingArea, bl
return true, nil
}
func (pm *pruningManager) ArePruningPointsViolatingFinality(stagingArea *model.StagingArea,
pruningPoints []externalapi.BlockHeader) (bool, error) {
virtualFinalityPoint, err := pm.finalityManager.VirtualFinalityPoint(stagingArea)
if err != nil {
return false, err
}
virtualFinalityPointFinalityPoint, err := pm.finalityManager.FinalityPoint(stagingArea, virtualFinalityPoint, false)
if err != nil {
return false, err
}
for _, header := range pruningPoints {
blockHash := consensushashing.HeaderHash(header)
exists, err := pm.blockStatusStore.Exists(pm.databaseContext, stagingArea, blockHash)
if err != nil {
return false, err
}
if !exists {
continue
}
isInSelectedParentChainOfVirtualFinalityPointFinalityPoint, err := pm.dagTopologyManager.
IsInSelectedParentChainOf(stagingArea, virtualFinalityPointFinalityPoint, blockHash)
if err != nil {
return false, err
}
return !isInSelectedParentChainOfVirtualFinalityPointFinalityPoint, nil
}
// If no pruning point is known, there's definitely a finality violation
return true, nil
}
func (pm *pruningManager) ArePruningPointsInValidChain(stagingArea *model.StagingArea) (bool, error) {
lastPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea)
if err != nil {
return false, err
}
expectedPruningPoints := make([]*externalapi.DomainHash, 0)
headersSelectedTip, err := pm.headerSelectedTipStore.HeadersSelectedTip(pm.databaseContext, stagingArea)
if err != nil {
return false, err
}
current := headersSelectedTip
for !current.Equal(lastPruningPoint) {
header, err := pm.blockHeaderStore.BlockHeader(pm.databaseContext, stagingArea, current)
if err != nil {
return false, err
}
if len(expectedPruningPoints) == 0 ||
!expectedPruningPoints[len(expectedPruningPoints)-1].Equal(header.PruningPoint()) {
expectedPruningPoints = append(expectedPruningPoints, header.PruningPoint())
}
currentGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, current, false)
if err != nil {
return false, err
}
current = currentGHOSTDAGData.SelectedParent()
}
lastPruningPointIndex, err := pm.pruningStore.CurrentPruningPointIndex(pm.databaseContext, stagingArea)
if err != nil {
return false, err
}
for i := lastPruningPointIndex; ; i-- {
pruningPoint, err := pm.pruningStore.PruningPointByIndex(pm.databaseContext, stagingArea, i)
if err != nil {
return false, err
}
header, err := pm.blockHeaderStore.BlockHeader(pm.databaseContext, stagingArea, pruningPoint)
if err != nil {
return false, err
}
var expectedPruningPoint *externalapi.DomainHash
expectedPruningPoint, expectedPruningPoints = expectedPruningPoints[0], expectedPruningPoints[1:]
if !pruningPoint.Equal(expectedPruningPoint) {
return false, nil
}
if i == 0 {
if len(expectedPruningPoints) != 0 {
return false, nil
}
if !pruningPoint.Equal(pm.genesisHash) {
return false, nil
}
break
}
if !expectedPruningPoints[len(expectedPruningPoints)-1].Equal(header.PruningPoint()) {
expectedPruningPoints = append(expectedPruningPoints, header.PruningPoint())
}
}
return true, nil
}
func (pm *pruningManager) pruningPointCandidate(stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
hasPruningPointCandidate, err := pm.pruningStore.HasPruningPointCandidate(pm.databaseContext, stagingArea)
if err != nil {
@ -503,7 +624,16 @@ func (pm *pruningManager) calculateDiffBetweenPreviousAndCurrentPruningPoints(st
return utxo.NewUTXODiff(), nil
}
previousPruningHash, err := pm.pruningStore.PreviousPruningPoint(pm.databaseContext, stagingArea)
pruningPointIndex, err := pm.pruningStore.CurrentPruningPointIndex(pm.databaseContext, stagingArea)
if err != nil {
return nil, err
}
if pruningPointIndex == 0 {
return nil, errors.Errorf("previous pruning point doesn't exist")
}
previousPruningHash, err := pm.pruningStore.PruningPointByIndex(pm.databaseContext, stagingArea, pruningPointIndex-1)
if err != nil {
return nil, err
}
@ -828,3 +958,60 @@ func (pm *pruningManager) blockWithTrustedData(stagingArea *model.StagingArea, b
GHOSTDAGData: ghostdagDataHashPairs,
}, nil
}
func (pm *pruningManager) ExpectedHeaderPruningPoint(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
nextOrCurrentPruningPoint, _, err := pm.NextPruningPointAndCandidateByBlockHash(stagingArea, blockHash)
if err != nil {
return nil, err
}
isHeaderPruningPoint, err := pm.isPruningPointInPruningDepth(stagingArea, blockHash, nextOrCurrentPruningPoint)
if err != nil {
return nil, err
}
if isHeaderPruningPoint {
return nextOrCurrentPruningPoint, nil
}
pruningPointIndex, err := pm.pruningStore.CurrentPruningPointIndex(pm.databaseContext, stagingArea)
if err != nil {
return nil, err
}
for i := pruningPointIndex; ; i-- {
currentPruningPoint, err := pm.pruningStore.PruningPointByIndex(pm.databaseContext, stagingArea, i)
if err != nil {
return nil, err
}
isHeaderPruningPoint, err := pm.isPruningPointInPruningDepth(stagingArea, blockHash, currentPruningPoint)
if err != nil {
return nil, err
}
if isHeaderPruningPoint {
return currentPruningPoint, nil
}
if i == 0 {
break
}
}
return pm.genesisHash, nil
}
func (pm *pruningManager) isPruningPointInPruningDepth(stagingArea *model.StagingArea, blockHash, pruningPoint *externalapi.DomainHash) (bool, error) {
pruningPointHeader, err := pm.blockHeaderStore.BlockHeader(pm.databaseContext, stagingArea, pruningPoint)
if err != nil {
return false, err
}
blockGHOSTDAGData, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, blockHash, false)
if err != nil {
return false, err
}
return blockGHOSTDAGData.BlueScore() >= pruningPointHeader.BlueScore()+pm.pruningDepth, nil
}

View File

@ -46,9 +46,13 @@ var (
// the expected value.
ErrUnexpectedFinalityPoint = newRuleError("ErrUnexpectedFinalityPoint")
// ErrUnexpectedBlueScore indicates specified blue score does not align with
// ErrUnexpectedCoinbaseBlueScore indicates specified blue score in the coinbase does not align with
// the expected value.
ErrUnexpectedBlueScore = newRuleError("ErrUnexpectedBlueScore")
ErrUnexpectedCoinbaseBlueScore = newRuleError("ErrUnexpectedCoinbaseBlueScore")
// ErrUnexpectedHeaderBlueScore indicates specified blue score in the header does not align with
// the expected value.
ErrUnexpectedHeaderBlueScore = newRuleError("ErrUnexpectedHeaderBlueScore")
// ErrTargetTooHigh indicates specified bits do not align with
// the expected value either because it is above the valid
@ -198,6 +202,8 @@ var (
ErrUnexpectedPruningPoint = newRuleError("ErrUnexpectedPruningPoint")
ErrInvalidPruningPointsChain = newRuleError("ErrInvalidPruningPointsChain")
ErrSuggestedPruningViolatesFinality = newRuleError("ErrSuggestedPruningViolatesFinality")
//ErrBlockVersionIsUnknown indicates that the block version is unknown.
@ -216,6 +222,10 @@ var (
ErrGenesisOnInitializedConsensus = newRuleError("ErrGenesisOnInitializedConsensus")
ErrPruningPointSelectedChildDisqualifiedFromChain = newRuleError("ErrPruningPointSelectedChildDisqualifiedFromChain")
// ErrUnexpectedFinalityPoint indicates a block header pruning point does not align with
// the expected value.
ErrUnexpectedHeaderPruningPoint = newRuleError("ErrUnexpectedHeaderPruningPoint")
)
// RuleError identifies a rule violation. It is used to indicate that

View File

@ -15,8 +15,17 @@ type blockHeader struct {
bits uint32
nonce uint64
daaScore uint64
blueScore uint64
blueWork *big.Int
finalityPoint *externalapi.DomainHash
pruningPoint *externalapi.DomainHash
}
func (bh *blockHeader) BlueScore() uint64 {
return bh.blueScore
}
func (bh *blockHeader) PruningPoint() *externalapi.DomainHash {
return bh.pruningPoint
}
func (bh *blockHeader) DAAScore() uint64 {
@ -27,10 +36,6 @@ func (bh *blockHeader) BlueWork() *big.Int {
return bh.blueWork
}
func (bh *blockHeader) FinalityPoint() *externalapi.DomainHash {
return bh.finalityPoint
}
func (bh *blockHeader) ToImmutable() externalapi.BlockHeader {
return bh.clone()
}
@ -131,11 +136,15 @@ func (bh *blockHeader) Equal(other externalapi.BaseBlockHeader) bool {
return false
}
if bh.blueScore != other.BlueScore() {
return false
}
if bh.blueWork.Cmp(other.BlueWork()) != 0 {
return false
}
if !bh.finalityPoint.Equal(other.FinalityPoint()) {
if !bh.pruningPoint.Equal(other.PruningPoint()) {
return false
}
@ -153,8 +162,9 @@ func (bh *blockHeader) clone() *blockHeader {
bits: bh.bits,
nonce: bh.nonce,
daaScore: bh.daaScore,
blueScore: bh.blueScore,
blueWork: bh.blueWork,
finalityPoint: bh.finalityPoint,
pruningPoint: bh.pruningPoint,
}
}
@ -173,8 +183,9 @@ func NewImmutableBlockHeader(
bits uint32,
nonce uint64,
daaScore uint64,
blueScore uint64,
blueWork *big.Int,
finalityPoint *externalapi.DomainHash,
pruningPoint *externalapi.DomainHash,
) externalapi.BlockHeader {
return &blockHeader{
version: version,
@ -186,7 +197,8 @@ func NewImmutableBlockHeader(
bits: bits,
nonce: nonce,
daaScore: daaScore,
blueScore: blueScore,
blueWork: blueWork,
finalityPoint: finalityPoint,
pruningPoint: pruningPoint,
}
}

View File

@ -33,8 +33,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
5,
6,
7,
big.NewInt(8),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{9}),
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
},
expectedResult: false,
},
@ -51,8 +52,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
headersToCompareTo: []headerToCompare{
{
@ -70,8 +72,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: true,
},
@ -86,15 +89,15 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
{
header: &blockHeader{
0,
// []*externalapi.DomainHash{{1}, {2}},
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{1}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{2})}},
@ -105,8 +108,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -121,8 +125,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -137,8 +142,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -153,8 +159,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -169,8 +176,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -185,8 +193,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -201,8 +210,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
100,
7,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -217,8 +227,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
100,
8,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -233,8 +244,9 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
100,
big.NewInt(9),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -249,8 +261,26 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
100,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
{
header: &blockHeader{
0,
[]externalapi.BlockLevelParents{[]*externalapi.DomainHash{externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{1})}},
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{2}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{3}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{4}),
5,
6,
7,
8,
9,
big.NewInt(100),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{10}),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{11}),
},
expectedResult: false,
},
@ -265,7 +295,8 @@ func TestDomainBlockHeader_Equal(t *testing.T) {
6,
7,
8,
big.NewInt(9),
9,
big.NewInt(10),
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{100}),
},
expectedResult: false,

View File

@ -51,5 +51,5 @@ func serializeHeader(w io.Writer, header externalapi.BaseBlockHeader) error {
}
}
return serialization.WriteElements(w, header.HashMerkleRoot(), header.AcceptedIDMerkleRoot(), header.UTXOCommitment(), timestamp,
header.Bits(), header.Nonce(), header.DAAScore(), blueWork, header.FinalityPoint())
header.Bits(), header.Nonce(), header.DAAScore(), header.BlueScore(), blueWork, header.PruningPoint())
}

View File

@ -38,7 +38,7 @@ const (
defaultMaxBlockParents = 10
// defaultGHOSTDAGK is a bound on the number of blue blocks in the anticone of a blue block. Approximates the maximal
// width of the network.
// Formula (1) in section 4.2 of the PHATOM paper shows how to calculate defaultGHOSTDAGK. The delta term represents a bound
// Formula (1) in section 4.2 of the PHANTOM paper shows how to calculate defaultGHOSTDAGK. The delta term represents a bound
// on the expected fraction of the network life in which the width was higher than defaultGHOSTDAGK. The current value of K
// was calculated for d = 5 seconds and delta = 0.05.
defaultGHOSTDAGK = 18

View File

@ -30,10 +30,10 @@ var genesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(0, []*externa
// genesisHash is the hash of the first block in the block DAG for the main
// network (genesis block).
var genesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x86, 0xd0, 0x2f, 0x43, 0xd9, 0xe2, 0x54, 0xf2,
0xda, 0x51, 0x26, 0x06, 0x2b, 0x06, 0xc4, 0xfd,
0xd2, 0x7b, 0x10, 0xd8, 0xe4, 0xb0, 0x10, 0x85,
0x60, 0xaf, 0x7b, 0x76, 0xb6, 0x81, 0xae, 0x27,
0x1a, 0x28, 0x9d, 0xe8, 0xd4, 0x60, 0xb7, 0xb0,
0xc6, 0x57, 0x7d, 0x21, 0x7b, 0x2f, 0x76, 0x98,
0xc4, 0x4f, 0xb1, 0xd6, 0xec, 0x4d, 0x75, 0xa3,
0x03, 0xf0, 0x0d, 0xe1, 0xe5, 0xe9, 0xd6, 0x67,
})
// genesisMerkleRoot is the hash of the first transaction in the genesis block
@ -54,9 +54,10 @@ var genesisBlock = externalapi.DomainBlock{
genesisMerkleRoot,
&externalapi.DomainHash{},
externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray()),
0x17adc150114,
0x17ae37f25e8,
0x207fffff,
0x1,
0x0,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
@ -83,10 +84,10 @@ var devnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(0,
// devGenesisHash is the hash of the first block in the block DAG for the development
// network (genesis block).
var devnetGenesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0xe4, 0xe1, 0xf7, 0xc2, 0x7e, 0xc8, 0x61, 0x94,
0x5d, 0x9d, 0xcb, 0x12, 0x4b, 0x77, 0xca, 0x57,
0x84, 0x2c, 0x90, 0x56, 0x06, 0x66, 0xc9, 0x47,
0xb7, 0x22, 0x4b, 0x73, 0xac, 0x63, 0x4f, 0x08,
0x70, 0xbc, 0x1c, 0x88, 0xd5, 0xd9, 0x70, 0x11,
0xf5, 0x90, 0x56, 0x71, 0x4f, 0x7b, 0x8b, 0x6a,
0x11, 0x95, 0x02, 0xe0, 0x12, 0xeb, 0x50, 0x46,
0xf6, 0xa0, 0xf3, 0xc3, 0x86, 0x29, 0x0e, 0x31,
})
// devnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
@ -109,7 +110,8 @@ var devnetGenesisBlock = externalapi.DomainBlock{
externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray()),
0x11e9db49828,
0x1e7fffff,
0x23694,
0x21a19,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
@ -135,10 +137,10 @@ var simnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(0,
// simnetGenesisHash is the hash of the first block in the block DAG for
// the simnet (genesis block).
var simnetGenesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x7a, 0x83, 0x0d, 0x9e, 0x29, 0x38, 0xb1, 0x7a,
0xfc, 0x85, 0xe4, 0x3f, 0xce, 0x1f, 0x37, 0xc4,
0x52, 0x97, 0xea, 0xba, 0x11, 0x70, 0xf5, 0x4e,
0xe3, 0x2f, 0xd3, 0xb0, 0x50, 0x08, 0x67, 0xa7,
0xce, 0xe9, 0x47, 0xa2, 0xe3, 0x4c, 0x0d, 0xc9,
0xbc, 0xa6, 0x37, 0x6d, 0x57, 0x3f, 0x02, 0xbb,
0x07, 0x0a, 0x5b, 0x45, 0x08, 0x7f, 0x09, 0xbd,
0x76, 0x42, 0x29, 0x75, 0x1f, 0x3f, 0xb4, 0x5f,
})
// simnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
@ -159,10 +161,11 @@ var simnetGenesisBlock = externalapi.DomainBlock{
simnetGenesisMerkleRoot,
&externalapi.DomainHash{},
externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray()),
0x17adc15022f,
0x17ae37f29f6,
0x207fffff,
0x1,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},
),
@ -187,10 +190,10 @@ var testnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(0,
// testnetGenesisHash is the hash of the first block in the block DAG for the test
// network (genesis block).
var testnetGenesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0x12, 0x35, 0x45, 0x64, 0x16, 0xac, 0x7b, 0x00,
0xe9, 0xa2, 0xc9, 0x97, 0x8d, 0x8b, 0xd3, 0x7c,
0xa2, 0xc2, 0x9b, 0x9e, 0x23, 0x62, 0x49, 0xb6,
0x41, 0x8a, 0xcc, 0x0a, 0x98, 0xd1, 0x10, 0x36,
0xb3, 0x8a, 0x60, 0x06, 0x8f, 0x44, 0xf2, 0xb1,
0x50, 0x96, 0x66, 0x1f, 0x37, 0xd5, 0x77, 0x60,
0xd2, 0x4a, 0xc9, 0xde, 0xa4, 0xac, 0x81, 0x1c,
0x22, 0x4c, 0xda, 0x8f, 0xbd, 0xe9, 0x01, 0x0f,
})
// testnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
@ -211,9 +214,10 @@ var testnetGenesisBlock = externalapi.DomainBlock{
testnetGenesisMerkleRoot,
&externalapi.DomainHash{},
externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray()),
0x17adc15022f,
0x17ae37f29f6,
0x1e7fffff,
0x2f291,
0xd4ad,
0,
0,
big.NewInt(0),
&externalapi.DomainHash{},

View File

@ -43,6 +43,7 @@ message KaspadMessage {
RequestPruningPointUTXOSetMessage requestPruningPointUTXOSet = 44;
RequestHeadersMessage requestHeaders = 45;
RequestBlockLocatorMessage requestBlockLocator = 46;
PruningPointsMessage pruningPoints = 47;
GetCurrentNetworkRequestMessage getCurrentNetworkRequest = 1001;
GetCurrentNetworkResponseMessage getCurrentNetworkResponse = 1002;

View File

@ -11,8 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const _ = grpc.SupportPackageIsVersion6
// P2PClient is the client API for P2P service.
//
@ -30,7 +29,7 @@ func NewP2PClient(cc grpc.ClientConnInterface) P2PClient {
}
func (c *p2PClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (P2P_MessageStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &P2P_ServiceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...)
stream, err := c.cc.NewStream(ctx, &_P2P_serviceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...)
if err != nil {
return nil, err
}
@ -72,20 +71,13 @@ type P2PServer interface {
type UnimplementedP2PServer struct {
}
func (UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
func (*UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
return status.Errorf(codes.Unimplemented, "method MessageStream not implemented")
}
func (UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {}
func (*UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {}
// UnsafeP2PServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to P2PServer will
// result in compilation errors.
type UnsafeP2PServer interface {
mustEmbedUnimplementedP2PServer()
}
func RegisterP2PServer(s grpc.ServiceRegistrar, srv P2PServer) {
s.RegisterService(&P2P_ServiceDesc, srv)
func RegisterP2PServer(s *grpc.Server, srv P2PServer) {
s.RegisterService(&_P2P_serviceDesc, srv)
}
func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
@ -114,10 +106,7 @@ func (x *p2PMessageStreamServer) Recv() (*KaspadMessage, error) {
return m, nil
}
// P2P_ServiceDesc is the grpc.ServiceDesc for P2P service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var P2P_ServiceDesc = grpc.ServiceDesc{
var _P2P_serviceDesc = grpc.ServiceDesc{
ServiceName: "protowire.P2P",
HandlerType: (*P2PServer)(nil),
Methods: []grpc.MethodDesc{},
@ -148,7 +137,7 @@ func NewRPCClient(cc grpc.ClientConnInterface) RPCClient {
}
func (c *rPCClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (RPC_MessageStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &RPC_ServiceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...)
stream, err := c.cc.NewStream(ctx, &_RPC_serviceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...)
if err != nil {
return nil, err
}
@ -190,20 +179,13 @@ type RPCServer interface {
type UnimplementedRPCServer struct {
}
func (UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
func (*UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
return status.Errorf(codes.Unimplemented, "method MessageStream not implemented")
}
func (UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {}
func (*UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {}
// UnsafeRPCServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to RPCServer will
// result in compilation errors.
type UnsafeRPCServer interface {
mustEmbedUnimplementedRPCServer()
}
func RegisterRPCServer(s grpc.ServiceRegistrar, srv RPCServer) {
s.RegisterService(&RPC_ServiceDesc, srv)
func RegisterRPCServer(s *grpc.Server, srv RPCServer) {
s.RegisterService(&_RPC_serviceDesc, srv)
}
func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
@ -232,10 +214,7 @@ func (x *rPCMessageStreamServer) Recv() (*KaspadMessage, error) {
return m, nil
}
// RPC_ServiceDesc is the grpc.ServiceDesc for RPC service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var RPC_ServiceDesc = grpc.ServiceDesc{
var _RPC_serviceDesc = grpc.ServiceDesc{
ServiceName: "protowire.RPC",
HandlerType: (*RPCServer)(nil),
Methods: []grpc.MethodDesc{},

View File

@ -1,12 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.25.0
// protoc v3.12.3
// source: p2p.proto
package protowire
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
@ -20,6 +21,10 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type RequestAddressesMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -680,7 +685,8 @@ type BlockHeader struct {
Nonce uint64 `protobuf:"varint,8,opt,name=nonce,proto3" json:"nonce,omitempty"`
DaaScore uint64 `protobuf:"varint,9,opt,name=daaScore,proto3" json:"daaScore,omitempty"`
BlueWork []byte `protobuf:"bytes,10,opt,name=blueWork,proto3" json:"blueWork,omitempty"`
FinalityPoint *Hash `protobuf:"bytes,11,opt,name=finalityPoint,proto3" json:"finalityPoint,omitempty"`
PruningPoint *Hash `protobuf:"bytes,14,opt,name=pruningPoint,proto3" json:"pruningPoint,omitempty"`
BlueScore uint64 `protobuf:"varint,13,opt,name=blueScore,proto3" json:"blueScore,omitempty"`
}
func (x *BlockHeader) Reset() {
@ -785,13 +791,20 @@ func (x *BlockHeader) GetBlueWork() []byte {
return nil
}
func (x *BlockHeader) GetFinalityPoint() *Hash {
func (x *BlockHeader) GetPruningPoint() *Hash {
if x != nil {
return x.FinalityPoint
return x.PruningPoint
}
return nil
}
func (x *BlockHeader) GetBlueScore() uint64 {
if x != nil {
return x.BlueScore
}
return 0
}
type BlockLevelParents struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -2705,6 +2718,53 @@ func (x *BlockBlueWorkMessage) GetBlueWork() []byte {
return nil
}
type PruningPointsMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Headers []*BlockHeader `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty"`
}
func (x *PruningPointsMessage) Reset() {
*x = PruningPointsMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_p2p_proto_msgTypes[50]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PruningPointsMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PruningPointsMessage) ProtoMessage() {}
func (x *PruningPointsMessage) ProtoReflect() protoreflect.Message {
mi := &file_p2p_proto_msgTypes[50]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PruningPointsMessage.ProtoReflect.Descriptor instead.
func (*PruningPointsMessage) Descriptor() ([]byte, []int) {
return file_p2p_proto_rawDescGZIP(), []int{50}
}
func (x *PruningPointsMessage) GetHeaders() []*BlockHeader {
if x != nil {
return x.Headers
}
return nil
}
var File_p2p_proto protoreflect.FileDescriptor
var file_p2p_proto_rawDesc = []byte{
@ -2788,7 +2848,7 @@ var file_p2p_proto_rawDesc = []byte{
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0c, 0x74, 0x72,
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xcd, 0x03, 0x0a, 0x0b, 0x42,
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe9, 0x03, 0x0a, 0x0b, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18,
@ -2814,228 +2874,234 @@ var file_p2p_proto_rawDesc = []byte{
0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64,
0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57,
0x6f, 0x72, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57,
0x6f, 0x72, 0x6b, 0x12, 0x35, 0x0a, 0x0d, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50,
0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0d, 0x66, 0x69, 0x6e,
0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x48, 0x0a, 0x11, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12,
0x33, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72,
0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61,
0x73, 0x68, 0x65, 0x73, 0x22, 0x1c, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05,
0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74,
0x65, 0x73, 0x22, 0x5f, 0x0a, 0x1a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x12, 0x2b, 0x0a, 0x08, 0x68, 0x69, 0x67, 0x68, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48,
0x61, 0x73, 0x68, 0x52, 0x08, 0x68, 0x69, 0x67, 0x68, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a,
0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69,
0x6d, 0x69, 0x74, 0x22, 0x3e, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61,
0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x68, 0x61,
0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x68, 0x61, 0x73,
0x68, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x15, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65,
0x61, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x07,
0x6c, 0x6f, 0x77, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07,
0x6c, 0x6f, 0x77, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x08, 0x68, 0x69, 0x67, 0x68, 0x48,
0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x68, 0x69, 0x67, 0x68,
0x48, 0x61, 0x73, 0x68, 0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e,
0x65, 0x78, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x6f, 0x6e, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x44, 0x0a, 0x19, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4d, 0x65, 0x73,
0x6f, 0x72, 0x6b, 0x12, 0x33, 0x0a, 0x0c, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f,
0x69, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x70, 0x72, 0x75, 0x6e,
0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65,
0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75,
0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x48, 0x0a, 0x11, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c,
0x65, 0x76, 0x65, 0x6c, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x0a, 0x0c, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61,
0x73, 0x68, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73,
0x22, 0x1c, 0x0a, 0x04, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65,
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, 0x5f,
0x0a, 0x1a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f,
0x63, 0x61, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x08,
0x68, 0x69, 0x67, 0x68, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52,
0x08, 0x68, 0x69, 0x67, 0x68, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d,
0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22,
0x3e, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22,
0x6f, 0x0a, 0x15, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x6c, 0x6f, 0x77, 0x48,
0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x6c, 0x6f, 0x77, 0x48,
0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x08, 0x68, 0x69, 0x67, 0x68, 0x48, 0x61, 0x73, 0x68, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72,
0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x68, 0x69, 0x67, 0x68, 0x48, 0x61, 0x73, 0x68,
0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x65, 0x78, 0x74, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x14, 0x0a,
0x12, 0x44, 0x6f, 0x6e, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x22, 0x44, 0x0a, 0x19, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65,
0x6c, 0x61, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x12, 0x27, 0x0a, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73,
0x68, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x48, 0x0a, 0x1a, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x03,
0x69, 0x64, 0x73, 0x22, 0x46, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x12, 0x28, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3b, 0x0a, 0x14, 0x49,
0x6e, 0x76, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61,
0x73, 0x68, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x44, 0x0a, 0x16, 0x49, 0x6e, 0x76, 0x54,
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e,
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x23,
0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a,
0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f,
0x6e, 0x63, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x50, 0x6f, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x04, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x61,
0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd2, 0x02, 0x0a, 0x0e, 0x56, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x0f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x12, 0x2f, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4e, 0x65,
0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69,
0x64, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x06,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12,
0x26, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x54,
0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
0x52, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x78, 0x12, 0x3b, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65,
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74,
0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f,
0x72, 0x6b, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x27,
0x0a, 0x0d, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x60, 0x0a, 0x21, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54,
0x58, 0x4f, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x10,
0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x10, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67,
0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x84, 0x01, 0x0a, 0x1f, 0x50, 0x72,
0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x53, 0x65,
0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x61, 0x0a,
0x19, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x55, 0x74, 0x78, 0x6f,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74,
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x19, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41,
0x6e, 0x64, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x61, 0x69, 0x72, 0x73,
0x22, 0x7f, 0x0a, 0x18, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x55,
0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x61, 0x69, 0x72, 0x12, 0x2f, 0x0a, 0x08,
0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x32, 0x0a,
0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x55, 0x74, 0x78,
0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x22, 0xaf, 0x01, 0x0a, 0x09, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70,
0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x63, 0x72,
0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x0f, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x24, 0x0a,
0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63,
0x6f, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69, 0x6e, 0x62,
0x61, 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x2a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4e, 0x65,
0x78, 0x74, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x74,
0x78, 0x6f, 0x53, 0x65, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x22, 0x26, 0x0a, 0x24, 0x44, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67,
0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x53, 0x65, 0x74, 0x43, 0x68, 0x75, 0x6e,
0x6b, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x42, 0x0a, 0x17, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x49, 0x42, 0x44, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x48, 0x0a,
0x1a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x69,
0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x49, 0x64, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x46, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73,
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x54, 0x72,
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x02, 0x69, 0x64, 0x22,
0x3b, 0x0a, 0x14, 0x49, 0x6e, 0x76, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18,
0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x1f, 0x0a,
0x1d, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x75, 0x6e, 0x69,
0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8a,
0x01, 0x0a, 0x16, 0x49, 0x62, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74,
0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0a,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3f, 0x0a, 0x12, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f,
0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x56, 0x0a, 0x21, 0x49,
0x62, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x69,
0x67, 0x68, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x12, 0x31, 0x0a, 0x0b, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72,
0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x44, 0x0a, 0x16,
0x49, 0x6e, 0x76, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e,
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x03, 0x69,
0x64, 0x73, 0x22, 0x23, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x50, 0x6f, 0x6e, 0x67, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x0f, 0x0a, 0x0d,
0x56, 0x65, 0x72, 0x61, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd2, 0x02,
0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x12, 0x28, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x12, 0x2f, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72,
0x65, 0x2e, 0x4e, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64,
0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65,
0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67,
0x65, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65,
0x6c, 0x61, 0x79, 0x54, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x69, 0x73,
0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x78, 0x12, 0x3b, 0x0a, 0x0c, 0x73,
0x75, 0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x53, 0x75,
0x62, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x6e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77,
0x6f, 0x72, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f,
0x72, 0x6b, 0x22, 0x27, 0x0a, 0x0d, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x60, 0x0a, 0x21, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69,
0x6e, 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x12, 0x3b, 0x0a, 0x10, 0x70, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74,
0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x10, 0x70, 0x72, 0x75,
0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x84, 0x01,
0x0a, 0x1f, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x74,
0x78, 0x6f, 0x53, 0x65, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x12, 0x61, 0x0a, 0x19, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64,
0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x55, 0x74, 0x78, 0x6f,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x19, 0x6f, 0x75, 0x74, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50,
0x61, 0x69, 0x72, 0x73, 0x22, 0x7f, 0x0a, 0x18, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x41, 0x6e, 0x64, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x61, 0x69, 0x72,
0x12, 0x2f, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4f,
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e,
0x74, 0x12, 0x32, 0x0a, 0x09, 0x75, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x75, 0x74, 0x78, 0x6f,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xaf, 0x01, 0x0a, 0x09, 0x55, 0x74, 0x78, 0x6f, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x0f, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79,
0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
0x79, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x61, 0x61, 0x53, 0x63, 0x6f,
0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x44,
0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x43, 0x6f, 0x69,
0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x43,
0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x22, 0x2c, 0x0a, 0x2a, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x4e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69,
0x6e, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x53, 0x65, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x26, 0x0a, 0x24, 0x44, 0x6f, 0x6e, 0x65, 0x50, 0x72, 0x75,
0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x53, 0x65, 0x74,
0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x42, 0x0a,
0x17, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x42, 0x44, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x68, 0x61, 0x73, 0x68,
0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65,
0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50,
0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x22, 0x8a, 0x01, 0x0a, 0x16, 0x49, 0x62, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c,
0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a,
0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61,
0x73, 0x68, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3f,
0x0a, 0x12, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x61,
0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x12, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22,
0x56, 0x0a, 0x21, 0x49, 0x62, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74,
0x6f, 0x72, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, 0x0b, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x48,
0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0b, 0x68, 0x69, 0x67, 0x68,
0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x2b, 0x0a, 0x29, 0x49, 0x62, 0x64, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73,
0x74, 0x48, 0x61, 0x73, 0x68, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x22, 0x51, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61,
0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x28, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e,
0x64, 0x49, 0x74, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x22, 0xe5, 0x01, 0x0a, 0x1b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74,
0x68, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x31,
0x0a, 0x09, 0x64, 0x61, 0x61, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x44, 0x61,
0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x09, 0x64, 0x61, 0x61, 0x57, 0x69, 0x6e, 0x64, 0x6f,
0x77, 0x12, 0x48, 0x0a, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74,
0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77,
0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61,
0x67, 0x44, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x50, 0x61, 0x69, 0x72, 0x52, 0x0c, 0x67,
0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0x77, 0x0a, 0x08, 0x44,
0x61, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65,
0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77,
0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52,
0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74,
0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64,
0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67,
0x44, 0x61, 0x74, 0x61, 0x22, 0x7d, 0x0a, 0x19, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f,
0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x50, 0x61, 0x69,
0x72, 0x12, 0x23, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68,
0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64,
0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61,
0x67, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44,
0x61, 0x74, 0x61, 0x22, 0xbc, 0x02, 0x0a, 0x0c, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67,
0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f,
0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x12, 0x37,
0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65,
0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65,
0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52,
0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x33,
0x0a, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x18, 0x05,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52,
0x65, 0x64, 0x73, 0x12, 0x4d, 0x0a, 0x12, 0x62, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69,
0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x75, 0x65,
0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x52, 0x12,
0x62, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a,
0x65, 0x73, 0x22, 0x65, 0x0a, 0x12, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63,
0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65,
0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x62, 0x6c, 0x75,
0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e,
0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6e, 0x74,
0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x22, 0x0a, 0x20, 0x44, 0x6f, 0x6e,
0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x57, 0x69, 0x74, 0x68, 0x54, 0x72, 0x75, 0x73, 0x74,
0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x44, 0x0a,
0x1b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75,
0x65, 0x57, 0x6f, 0x72, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x05,
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x05, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x22, 0x32, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65,
0x57, 0x6f, 0x72, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62,
0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62,
0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b,
0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0b, 0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x48,
0x61, 0x73, 0x68, 0x22, 0x2b, 0x0a, 0x29, 0x49, 0x62, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c,
0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73,
0x68, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x22, 0x51, 0x0a, 0x13, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48,
0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64,
0x65, 0x72, 0x73, 0x22, 0x2a, 0x0a, 0x28, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72,
0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x49, 0x74, 0x73,
0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
0xe5, 0x01, 0x0a, 0x1b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x57, 0x69, 0x74, 0x68, 0x54, 0x72, 0x75,
0x73, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
0x2d, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1a,
0x0a, 0x08, 0x64, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x52, 0x08, 0x64, 0x61, 0x61, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x64, 0x61,
0x61, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x44, 0x61, 0x61, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x52, 0x09, 0x64, 0x61, 0x61, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x48, 0x0a,
0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74,
0x61, 0x48, 0x61, 0x73, 0x68, 0x50, 0x61, 0x69, 0x72, 0x52, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74,
0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0x77, 0x0a, 0x08, 0x44, 0x61, 0x61, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61,
0x64, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44,
0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61,
0x74, 0x61, 0x52, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61,
0x22, 0x7d, 0x0a, 0x19, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61,
0x67, 0x44, 0x61, 0x74, 0x61, 0x48, 0x61, 0x73, 0x68, 0x50, 0x61, 0x69, 0x72, 0x12, 0x23, 0x0a,
0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x04, 0x68, 0x61,
0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61,
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x77, 0x69, 0x72, 0x65, 0x2e, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74,
0x61, 0x52, 0x0c, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61, 0x22,
0xbc, 0x02, 0x0a, 0x0c, 0x47, 0x68, 0x6f, 0x73, 0x74, 0x64, 0x61, 0x67, 0x44, 0x61, 0x74, 0x61,
0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x09, 0x62, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a,
0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x12, 0x37, 0x0a, 0x0e, 0x73, 0x65,
0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48,
0x61, 0x73, 0x68, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x42,
0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0d, 0x6d, 0x65, 0x72,
0x67, 0x65, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x0c, 0x6d, 0x65,
0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73,
0x68, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x64, 0x73, 0x12,
0x4d, 0x0a, 0x12, 0x62, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65,
0x53, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74,
0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x52, 0x12, 0x62, 0x6c, 0x75, 0x65,
0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x22, 0x65,
0x0a, 0x12, 0x42, 0x6c, 0x75, 0x65, 0x73, 0x41, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53,
0x69, 0x7a, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73, 0x68,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x48, 0x61, 0x73,
0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x7a,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x6f, 0x6e,
0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x22, 0x0a, 0x20, 0x44, 0x6f, 0x6e, 0x65, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x73, 0x57, 0x69, 0x74, 0x68, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x44, 0x61,
0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x44, 0x0a, 0x1b, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72,
0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77,
0x69, 0x72, 0x65, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22,
0x32, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65, 0x57, 0x6f, 0x72, 0x6b,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57,
0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x6c, 0x75, 0x65, 0x57,
0x6f, 0x72, 0x6b, 0x22, 0x48, 0x0a, 0x14, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f,
0x69, 0x6e, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x68,
0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65,
0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x42, 0x26, 0x5a,
0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70,
0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -3050,7 +3116,7 @@ func file_p2p_proto_rawDescGZIP() []byte {
return file_p2p_proto_rawDescData
}
var file_p2p_proto_msgTypes = make([]protoimpl.MessageInfo, 50)
var file_p2p_proto_msgTypes = make([]protoimpl.MessageInfo, 51)
var file_p2p_proto_goTypes = []interface{}{
(*RequestAddressesMessage)(nil), // 0: protowire.RequestAddressesMessage
(*AddressesMessage)(nil), // 1: protowire.AddressesMessage
@ -3102,6 +3168,7 @@ var file_p2p_proto_goTypes = []interface{}{
(*DoneBlocksWithTrustedDataMessage)(nil), // 47: protowire.DoneBlocksWithTrustedDataMessage
(*RequestBlockBlueWorkMessage)(nil), // 48: protowire.RequestBlockBlueWorkMessage
(*BlockBlueWorkMessage)(nil), // 49: protowire.BlockBlueWorkMessage
(*PruningPointsMessage)(nil), // 50: protowire.PruningPointsMessage
}
var file_p2p_proto_depIdxs = []int32{
3, // 0: protowire.RequestAddressesMessage.subnetworkId:type_name -> protowire.SubnetworkId
@ -3118,7 +3185,7 @@ var file_p2p_proto_depIdxs = []int32{
13, // 11: protowire.BlockHeader.hashMerkleRoot:type_name -> protowire.Hash
13, // 12: protowire.BlockHeader.acceptedIdMerkleRoot:type_name -> protowire.Hash
13, // 13: protowire.BlockHeader.utxoCommitment:type_name -> protowire.Hash
13, // 14: protowire.BlockHeader.finalityPoint:type_name -> protowire.Hash
13, // 14: protowire.BlockHeader.pruningPoint:type_name -> protowire.Hash
13, // 15: protowire.BlockLevelParents.parentHashes:type_name -> protowire.Hash
13, // 16: protowire.RequestBlockLocatorMessage.highHash:type_name -> protowire.Hash
13, // 17: protowire.BlockLocatorMessage.hashes:type_name -> protowire.Hash
@ -3154,11 +3221,12 @@ var file_p2p_proto_depIdxs = []int32{
46, // 47: protowire.GhostdagData.bluesAnticoneSizes:type_name -> protowire.BluesAnticoneSizes
13, // 48: protowire.BluesAnticoneSizes.blueHash:type_name -> protowire.Hash
13, // 49: protowire.RequestBlockBlueWorkMessage.block:type_name -> protowire.Hash
50, // [50:50] is the sub-list for method output_type
50, // [50:50] is the sub-list for method input_type
50, // [50:50] is the sub-list for extension type_name
50, // [50:50] is the sub-list for extension extendee
0, // [0:50] is the sub-list for field type_name
11, // 50: protowire.PruningPointsMessage.headers:type_name -> protowire.BlockHeader
51, // [51:51] is the sub-list for method output_type
51, // [51:51] is the sub-list for method input_type
51, // [51:51] is the sub-list for extension type_name
51, // [51:51] is the sub-list for extension extendee
0, // [0:51] is the sub-list for field type_name
}
func init() { file_p2p_proto_init() }
@ -3767,6 +3835,18 @@ func file_p2p_proto_init() {
return nil
}
}
file_p2p_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PruningPointsMessage); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -3774,7 +3854,7 @@ func file_p2p_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_p2p_proto_rawDesc,
NumEnums: 0,
NumMessages: 50,
NumMessages: 51,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -73,7 +73,8 @@ message BlockHeader{
uint64 nonce = 8;
uint64 daaScore = 9;
bytes blueWork = 10;
Hash finalityPoint = 11;
Hash pruningPoint = 14;
uint64 blueScore = 13;
}
message BlockLevelParents {
@ -244,3 +245,7 @@ message RequestBlockBlueWorkMessage {
message BlockBlueWorkMessage {
bytes blueWork = 1;
}
message PruningPointsMessage {
repeated BlockHeader headers = 1;
}

View File

@ -29,7 +29,7 @@ func (x *BlockHeader) toAppMessage() (*appmessage.MsgBlockHeader, error) {
if err != nil {
return nil, err
}
finalityPoint, err := x.FinalityPoint.toDomain()
pruningPoint, err := x.PruningPoint.toDomain()
if err != nil {
return nil, err
}
@ -46,8 +46,9 @@ func (x *BlockHeader) toAppMessage() (*appmessage.MsgBlockHeader, error) {
Bits: x.Bits,
Nonce: x.Nonce,
DAAScore: x.DaaScore,
BlueScore: x.BlueScore,
BlueWork: new(big.Int).SetBytes(x.BlueWork),
FinalityPoint: finalityPoint,
PruningPoint: pruningPoint,
}, nil
}
@ -62,8 +63,9 @@ func (x *BlockHeader) fromAppMessage(msgBlockHeader *appmessage.MsgBlockHeader)
Bits: msgBlockHeader.Bits,
Nonce: msgBlockHeader.Nonce,
DaaScore: msgBlockHeader.DAAScore,
BlueScore: msgBlockHeader.BlueScore,
BlueWork: msgBlockHeader.BlueWork.Bytes(),
FinalityPoint: domainHashToProto(msgBlockHeader.FinalityPoint),
PruningPoint: domainHashToProto(msgBlockHeader.PruningPoint),
}
return nil
}

View File

@ -0,0 +1,44 @@
package protowire
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/pkg/errors"
)
func (x *KaspadMessage_PruningPoints) toAppMessage() (appmessage.Message, error) {
if x == nil {
return nil, errors.Wrapf(errorNil, "KaspadMessage_PruningPoints is nil")
}
if x.PruningPoints == nil {
return nil, errors.Wrapf(errorNil, "x.PruningPoints is nil")
}
blockHeaders := make([]*appmessage.MsgBlockHeader, len(x.PruningPoints.Headers))
for i, blockHeader := range x.PruningPoints.Headers {
var err error
blockHeaders[i], err = blockHeader.toAppMessage()
if err != nil {
return nil, err
}
}
return &appmessage.MsgPruningPoints{
Headers: blockHeaders,
}, nil
}
func (x *KaspadMessage_PruningPoints) fromAppMessage(msgPruningPoints *appmessage.MsgPruningPoints) error {
blockHeaders := make([]*BlockHeader, len(msgPruningPoints.Headers))
for i, blockHeader := range msgPruningPoints.Headers {
blockHeaders[i] = &BlockHeader{}
err := blockHeaders[i].fromAppMessage(blockHeader)
if err != nil {
return err
}
}
x.PruningPoints = &PruningPointsMessage{
Headers: blockHeaders,
}
return nil
}

View File

@ -36,11 +36,12 @@ message RpcBlockHeader {
uint64 nonce = 8;
uint64 daaScore = 9;
string blueWork = 10;
string finalityPoint = 11;
string pruningPoint = 14;
uint64 blueScore = 13;
}
message RpcBlockLevelParents {
repeated string parentHashes = 1;
repeated string parentHashes = 1;
}
message RpcBlockVerboseData{

View File

@ -144,7 +144,8 @@ func (x *RpcBlockHeader) toAppMessage() (*appmessage.RPCBlockHeader, error) {
Nonce: x.Nonce,
DAAScore: x.DaaScore,
BlueWork: x.BlueWork,
FinalityPoint: x.FinalityPoint,
BlueScore: x.BlueScore,
PruningPoint: x.PruningPoint,
}, nil
}
@ -165,7 +166,8 @@ func (x *RpcBlockHeader) fromAppMessage(message *appmessage.RPCBlockHeader) {
Nonce: message.Nonce,
DaaScore: message.DAAScore,
BlueWork: message.BlueWork,
FinalityPoint: message.FinalityPoint,
BlueScore: message.BlueScore,
PruningPoint: message.PruningPoint,
}
}

View File

@ -303,6 +303,13 @@ func toP2PPayload(message appmessage.Message) (isKaspadMessage_Payload, error) {
return nil, err
}
return payload, nil
case *appmessage.MsgPruningPoints:
payload := new(KaspadMessage_PruningPoints)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
default:
return nil, nil
}

View File

@ -124,7 +124,7 @@ func TestIBDWithPruning(t *testing.T) {
}
if synceeSelectedTip.SelectedTipHash != consensushashing.BlockHash(syncerTip).String() {
t.Fatalf("Unexpected selected tip")
t.Fatalf("Unexpected selected tip: expected %s but got %s", consensushashing.BlockHash(syncerTip).String(), synceeSelectedTip.SelectedTipHash)
}
}
@ -135,6 +135,12 @@ func TestIBDWithPruning(t *testing.T) {
// This is done to make a pruning depth of 6 blocks
overrideDAGParams.FinalityDuration = 2 * overrideDAGParams.TargetTimePerBlock
overrideDAGParams.K = 0
expectedPruningDepth := uint64(6)
if overrideDAGParams.PruningDepth() != expectedPruningDepth {
t.Fatalf("Unexpected pruning depth: expected %d but got %d", expectedPruningDepth, overrideDAGParams.PruningDepth())
}
harnesses, teardown := setupHarnesses(t, []*harnessParams{
{
p2pAddress: p2pAddress1,