From c3902ed7a8ea4a46deb41b1db4fa07807d73729d Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Sun, 6 Dec 2020 14:45:21 +0200 Subject: [PATCH] Replace blue score with blue work in ghostdag (#1172) * Replace blueScore with blueWork in ghostDAG SelectedParent selection * Add blueWork to protopuf ghostdag data * Auto generate protobuf go code * Serialize/Deserialize blueWork when converting to protobuf * pass block header store to ghostdagmanager * Convert tal's ghostdag2 implementation to blueWork * Change finality test to check the blueWork instead of blueScore * Update ghostdag_test to pass blockHeaderStore to ghostdag, and test all networks genesis headers * Add sanity blueWork check to ghostdag_test --- .../serialization/block_ghostdag_data.go | 3 + .../database/serialization/dbobjects.pb.go | 232 ++++++------- .../database/serialization/dbobjects.proto | 9 +- domain/consensus/factory.go | 1 + domain/consensus/finality_test.go | 2 +- domain/consensus/model/ghostdag.go | 7 +- .../processes/ghostdag2/ghostdagimpl.go | 43 ++- .../processes/ghostdagmanager/compare.go | 13 +- .../processes/ghostdagmanager/ghostdag.go | 14 + .../ghostdagmanager/ghostdag_data.go | 8 + .../ghostdagmanager/ghostdag_test.go | 305 +++++++++++------- .../ghostdagmanager/ghostdagmanager.go | 3 + 12 files changed, 391 insertions(+), 249 deletions(-) diff --git a/domain/consensus/database/serialization/block_ghostdag_data.go b/domain/consensus/database/serialization/block_ghostdag_data.go index 2b4a2544d..29f9df9d6 100644 --- a/domain/consensus/database/serialization/block_ghostdag_data.go +++ b/domain/consensus/database/serialization/block_ghostdag_data.go @@ -4,6 +4,7 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager" + "math/big" ) // BlockGHOSTDAGDataToDBBlockGHOSTDAGData converts BlockGHOSTDAGData to DbBlockGhostdagData @@ -15,6 +16,7 @@ func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData model.BlockGHOSTDA return &DbBlockGhostdagData{ BlueScore: blockGHOSTDAGData.BlueScore(), + BlueWork: blockGHOSTDAGData.BlueWork().Bytes(), SelectedParent: selectedParent, MergeSetBlues: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetBlues()), MergeSetReds: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetReds()), @@ -50,6 +52,7 @@ func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdag return ghostdagmanager.NewBlockGHOSTDAGData( dbBlockGHOSTDAGData.BlueScore, + new(big.Int).SetBytes(dbBlockGHOSTDAGData.BlueWork), selectedParent, mergetSetBlues, mergetSetReds, diff --git a/domain/consensus/database/serialization/dbobjects.pb.go b/domain/consensus/database/serialization/dbobjects.pb.go index fa19c7c1e..731b42013 100644 --- a/domain/consensus/database/serialization/dbobjects.pb.go +++ b/domain/consensus/database/serialization/dbobjects.pb.go @@ -865,10 +865,11 @@ type DbBlockGhostdagData struct { unknownFields protoimpl.UnknownFields BlueScore uint64 `protobuf:"varint,1,opt,name=blueScore,proto3" json:"blueScore,omitempty"` - SelectedParent *DbHash `protobuf:"bytes,2,opt,name=selectedParent,proto3" json:"selectedParent,omitempty"` - MergeSetBlues []*DbHash `protobuf:"bytes,3,rep,name=mergeSetBlues,proto3" json:"mergeSetBlues,omitempty"` - MergeSetReds []*DbHash `protobuf:"bytes,4,rep,name=mergeSetReds,proto3" json:"mergeSetReds,omitempty"` - BluesAnticoneSizes []*DbBluesAnticoneSizes `protobuf:"bytes,5,rep,name=bluesAnticoneSizes,proto3" json:"bluesAnticoneSizes,omitempty"` + BlueWork []byte `protobuf:"bytes,2,opt,name=blueWork,proto3" json:"blueWork,omitempty"` + SelectedParent *DbHash `protobuf:"bytes,3,opt,name=selectedParent,proto3" json:"selectedParent,omitempty"` + MergeSetBlues []*DbHash `protobuf:"bytes,4,rep,name=mergeSetBlues,proto3" json:"mergeSetBlues,omitempty"` + MergeSetReds []*DbHash `protobuf:"bytes,5,rep,name=mergeSetReds,proto3" json:"mergeSetReds,omitempty"` + BluesAnticoneSizes []*DbBluesAnticoneSizes `protobuf:"bytes,6,rep,name=bluesAnticoneSizes,proto3" json:"bluesAnticoneSizes,omitempty"` } func (x *DbBlockGhostdagData) Reset() { @@ -910,6 +911,13 @@ func (x *DbBlockGhostdagData) GetBlueScore() uint64 { return 0 } +func (x *DbBlockGhostdagData) GetBlueWork() []byte { + if x != nil { + return x.BlueWork + } + return nil +} + func (x *DbBlockGhostdagData) GetSelectedParent() *DbHash { if x != nil { return x.SelectedParent @@ -1848,119 +1856,121 @@ var file_dbobjects_proto_rawDesc = []byte{ 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, 0xbf, 0x02, 0x0a, + 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, 0x3d, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 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, 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, 0x03, 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, 0x04, + 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, 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, - 0x05, 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, 0x97, 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, 0x28, 0x0a, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65, 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, 0x9c, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x08, 0x74, 0x72, - 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x01, 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, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x43, 0x0a, - 0x11, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, - 0x65, 0x74, 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, - 0x11, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, - 0x65, 0x74, 0x22, 0xbd, 0x01, 0x0a, 0x16, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 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, + 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, 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, 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, - 0x32, 0x0a, 0x1a, 0x44, 0x62, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x55, 0x54, 0x58, 0x4f, 0x53, 0x65, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x22, 0x39, 0x0a, 0x0c, 0x44, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 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, 0x5d, 0x0a, 0x14, 0x44, 0x62, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, - 0x44, 0x69, 0x66, 0x66, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x12, 0x76, - 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x50, 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, 0x12, - 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x50, 0x61, 0x72, 0x65, 0x6e, - 0x74, 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, + 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, 0x97, 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, 0x28, 0x0a, + 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x42, 0x6c, 0x75, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6c, 0x75, 0x65, 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, + 0x9c, 0x01, 0x0a, 0x12, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x08, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x18, 0x01, 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, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x08, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x75, 0x74, + 0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 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, 0x11, 0x66, 0x75, 0x74, + 0x75, 0x72, 0x65, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x22, 0xbd, + 0x01, 0x0a, 0x16, 0x44, 0x62, 0x52, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x64, 0x65, 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, 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, 0x32, 0x0a, 0x1a, 0x44, + 0x62, 0x50, 0x72, 0x75, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x55, 0x54, 0x58, + 0x4f, 0x53, 0x65, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, + 0x39, 0x0a, 0x0c, 0x44, 0x62, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 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, 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, + 0x5d, 0x0a, 0x14, 0x44, 0x62, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, + 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x12, 0x76, 0x69, 0x72, 0x74, 0x75, + 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x50, 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, 0x12, 0x76, 0x69, 0x72, 0x74, + 0x75, 0x61, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 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, 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, + 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, + 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 ( diff --git a/domain/consensus/database/serialization/dbobjects.proto b/domain/consensus/database/serialization/dbobjects.proto index 65a84bcb7..2e2061bce 100644 --- a/domain/consensus/database/serialization/dbobjects.proto +++ b/domain/consensus/database/serialization/dbobjects.proto @@ -83,10 +83,11 @@ message DbBlockStatus { message DbBlockGhostdagData { uint64 blueScore = 1; - DbHash selectedParent = 2; - repeated DbHash mergeSetBlues = 3; - repeated DbHash mergeSetReds = 4; - repeated DbBluesAnticoneSizes bluesAnticoneSizes = 5; + bytes blueWork = 2; + DbHash selectedParent = 3; + repeated DbHash mergeSetBlues = 4; + repeated DbHash mergeSetReds = 5; + repeated DbBluesAnticoneSizes bluesAnticoneSizes = 6; } message DbBluesAnticoneSizes { diff --git a/domain/consensus/factory.go b/domain/consensus/factory.go index ca0db772f..a528811ff 100644 --- a/domain/consensus/factory.go +++ b/domain/consensus/factory.go @@ -95,6 +95,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat dbManager, dagTopologyManager, ghostdagDataStore, + blockHeaderStore, dagParams.K) dagTraversalManager := dagtraversalmanager.New( dbManager, diff --git a/domain/consensus/finality_test.go b/domain/consensus/finality_test.go index 61b0c3c12..856a02dce 100644 --- a/domain/consensus/finality_test.go +++ b/domain/consensus/finality_test.go @@ -155,7 +155,7 @@ func TestFinality(t *testing.T) { t.Fatalf("TestFinality: Failed getting the ghost dag data of the sidechain tip: %v", err) } - if selectedTipGhostDagData.BlueScore() > sideChainTipGhostDagData.BlueScore() { + if selectedTipGhostDagData.BlueWork().Cmp(sideChainTipGhostDagData.BlueWork()) == 1 { t.Fatalf("sideChainTip is not the bluest tip when it is expected to be") } diff --git a/domain/consensus/model/ghostdag.go b/domain/consensus/model/ghostdag.go index 2f1b4370d..d4967df71 100644 --- a/domain/consensus/model/ghostdag.go +++ b/domain/consensus/model/ghostdag.go @@ -1,10 +1,15 @@ package model -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +import ( + "math/big" + + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +) // BlockGHOSTDAGData represents GHOSTDAG data for some block type BlockGHOSTDAGData interface { BlueScore() uint64 + BlueWork() *big.Int SelectedParent() *externalapi.DomainHash MergeSetBlues() []*externalapi.DomainHash MergeSetReds() []*externalapi.DomainHash diff --git a/domain/consensus/processes/ghostdag2/ghostdagimpl.go b/domain/consensus/processes/ghostdag2/ghostdagimpl.go index abaaf183e..6a84f7b70 100644 --- a/domain/consensus/processes/ghostdag2/ghostdagimpl.go +++ b/domain/consensus/processes/ghostdag2/ghostdagimpl.go @@ -7,6 +7,8 @@ import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + "github.com/kaspanet/kaspad/util" + "math/big" ) type ghostdagHelper struct { @@ -14,6 +16,7 @@ type ghostdagHelper struct { dataStore model.GHOSTDAGDataStore dbAccess model.DBReader dagTopologyManager model.DAGTopologyManager + headerStore model.BlockHeaderStore } // New creates a new instance of this alternative ghostdag impl @@ -21,12 +24,14 @@ func New( databaseContext model.DBReader, dagTopologyManager model.DAGTopologyManager, ghostdagDataStore model.GHOSTDAGDataStore, + headerStore model.BlockHeaderStore, k model.KType) model.GHOSTDAGManager { return &ghostdagHelper{ dbAccess: databaseContext, dagTopologyManager: dagTopologyManager, dataStore: ghostdagDataStore, + headerStore: headerStore, k: k, } } @@ -34,8 +39,10 @@ func New( /* --------------------------------------------- */ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error { - var maxNum uint64 = 0 - var myScore uint64 = 0 + myWork := new(big.Int) + maxWork := new(big.Int) + var myScore uint64 + var spScore uint64 /* find the selectedParent */ blockParents, err := gh.dagTopologyManager.Parents(blockCandidate) if err != nil { @@ -47,16 +54,21 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error if err != nil { return err } + blockWork := blockData.BlueWork() blockScore := blockData.BlueScore() - if blockScore > maxNum { + if blockWork.Cmp(maxWork) == 1 { selectedParent = parent - maxNum = blockScore + maxWork = blockWork + spScore = blockScore } - if blockScore == maxNum && ismoreHash(parent, selectedParent) { + if blockWork.Cmp(maxWork) == 0 && ismoreHash(parent, selectedParent) { selectedParent = parent + maxWork = blockWork + spScore = blockScore } } - myScore = maxNum + myWork.Set(maxWork) + myScore = spScore /* Goal: iterate blockCandidate's mergeSet and divide it to : blue, blues, reds. */ var mergeSetBlues = make([]*externalapi.DomainHash, 0) @@ -70,7 +82,7 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error return err } - err = gh.sortByBlueScore(mergeSetArr) + err = gh.sortByBlueWork(mergeSetArr) if err != nil { return err } @@ -94,7 +106,16 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error } myScore += uint64(len(mergeSetBlues)) - e := ghostdagmanager.NewBlockGHOSTDAGData(myScore, selectedParent, mergeSetBlues, mergeSetReds, nil) + // We add up all the *work*(not blueWork) that all our blues and selected parent did + for _, blue := range mergeSetBlues { + header, err := gh.headerStore.BlockHeader(gh.dbAccess, blue) + if err != nil { + return err + } + myWork.Add(myWork, util.CalcWork(header.Bits)) + } + + e := ghostdagmanager.NewBlockGHOSTDAGData(myScore, myWork, selectedParent, mergeSetBlues, mergeSetReds, nil) gh.dataStore.Stage(blockCandidate, e) return nil } @@ -337,7 +358,7 @@ func (gh *ghostdagHelper) findBlueSet(blueSet *[]*externalapi.DomainHash, select } /* ----------------sortByBlueScore------------------- */ -func (gh *ghostdagHelper) sortByBlueScore(arr []*externalapi.DomainHash) error { +func (gh *ghostdagHelper) sortByBlueWork(arr []*externalapi.DomainHash) error { var err error = nil sort.Slice(arr, func(i, j int) bool { @@ -354,10 +375,10 @@ func (gh *ghostdagHelper) sortByBlueScore(arr []*externalapi.DomainHash) error { return false } - if blockLeft.BlueScore() < blockRight.BlueScore() { + if blockLeft.BlueWork().Cmp(blockRight.BlueWork()) == -1 { return true } - if blockLeft.BlueScore() == blockRight.BlueScore() { + if blockLeft.BlueWork().Cmp(blockRight.BlueWork()) == 0 { return ismoreHash(arr[j], arr[i]) } return false diff --git a/domain/consensus/processes/ghostdagmanager/compare.go b/domain/consensus/processes/ghostdagmanager/compare.go index 76ad1844a..d5143513c 100644 --- a/domain/consensus/processes/ghostdagmanager/compare.go +++ b/domain/consensus/processes/ghostdagmanager/compare.go @@ -56,11 +56,14 @@ func (gm *ghostdagManager) ChooseSelectedParent(blockHashes ...*externalapi.Doma func (gm *ghostdagManager) Less(blockHashA *externalapi.DomainHash, ghostdagDataA model.BlockGHOSTDAGData, blockHashB *externalapi.DomainHash, ghostdagDataB model.BlockGHOSTDAGData) bool { - blockBlueScoreA := ghostdagDataA.BlueScore() - blockBlueScoreB := ghostdagDataB.BlueScore() - if blockBlueScoreA == blockBlueScoreB { + switch ghostdagDataA.BlueWork().Cmp(ghostdagDataB.BlueWork()) { + case -1: + return true + case 1: + return false + case 0: return hashes.Less(blockHashA, blockHashB) + default: + panic("big.Int.Cmp is defined to always return -1/1/0 and nothing else") } - - return blockBlueScoreA < blockBlueScoreB } diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag.go b/domain/consensus/processes/ghostdagmanager/ghostdag.go index 8e24ea4c1..f82fceb36 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdag.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdag.go @@ -3,7 +3,9 @@ package ghostdagmanager import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + "github.com/kaspanet/kaspad/util" "github.com/pkg/errors" + "math/big" ) // GHOSTDAG runs the GHOSTDAG protocol and calculates the block BlockGHOSTDAGData by the given parents. @@ -26,6 +28,7 @@ import ( // For further details see the article https://eprint.iacr.org/2018/104.pdf func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error { newBlockData := &blockGHOSTDAGData{ + blueWork: new(big.Int), mergeSetBlues: make([]*externalapi.DomainHash, 0), mergeSetReds: make([]*externalapi.DomainHash, 0), bluesAnticoneSizes: make(map[externalapi.DomainHash]model.KType), @@ -77,9 +80,20 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error { return err } newBlockData.blueScore = selectedParentGHOSTDAGData.BlueScore() + uint64(len(newBlockData.mergeSetBlues)) + // We inherit the bluework from the selected parent + newBlockData.blueWork.Set(selectedParentGHOSTDAGData.BlueWork()) + // Then we add up all the *work*(not blueWork) that all of newBlock merge set blues and selected parent did + for _, blue := range newBlockData.mergeSetBlues { + header, err := gm.headerStore.BlockHeader(gm.databaseContext, blue) + if err != nil { + return err + } + newBlockData.blueWork.Add(newBlockData.blueWork, util.CalcWork(header.Bits)) + } } else { // Genesis's blue score is defined to be 0. newBlockData.blueScore = 0 + newBlockData.blueWork.SetUint64(0) } gm.ghostdagDataStore.Stage(blockHash, newBlockData) diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag_data.go b/domain/consensus/processes/ghostdagmanager/ghostdag_data.go index b708241be..a488542c0 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdag_data.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdag_data.go @@ -3,10 +3,12 @@ package ghostdagmanager import ( "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + "math/big" ) type blockGHOSTDAGData struct { blueScore uint64 + blueWork *big.Int selectedParent *externalapi.DomainHash mergeSetBlues []*externalapi.DomainHash mergeSetReds []*externalapi.DomainHash @@ -16,6 +18,7 @@ type blockGHOSTDAGData struct { // NewBlockGHOSTDAGData creates a new instance of model.BlockGHOSTDAGData func NewBlockGHOSTDAGData( blueScore uint64, + blueWork *big.Int, selectedParent *externalapi.DomainHash, mergeSetBlues []*externalapi.DomainHash, mergeSetReds []*externalapi.DomainHash, @@ -23,6 +26,7 @@ func NewBlockGHOSTDAGData( return &blockGHOSTDAGData{ blueScore: blueScore, + blueWork: blueWork, selectedParent: selectedParent, mergeSetBlues: mergeSetBlues, mergeSetReds: mergeSetReds, @@ -34,6 +38,10 @@ func (bgd *blockGHOSTDAGData) BlueScore() uint64 { return bgd.blueScore } +func (bgd *blockGHOSTDAGData) BlueWork() *big.Int { + return bgd.blueWork +} + func (bgd *blockGHOSTDAGData) SelectedParent() *externalapi.DomainHash { return bgd.selectedParent } diff --git a/domain/consensus/processes/ghostdagmanager/ghostdag_test.go b/domain/consensus/processes/ghostdagmanager/ghostdag_test.go index 6afcf6091..49208549a 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdag_test.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdag_test.go @@ -2,147 +2,173 @@ package ghostdagmanager_test import ( "encoding/json" + "github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager" + "github.com/kaspanet/kaspad/util" + "math/big" "os" "path/filepath" "reflect" "testing" - "github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager" - "github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/processes/ghostdag2" + "github.com/kaspanet/kaspad/domain/consensus/utils/testutils" + "github.com/kaspanet/kaspad/domain/dagconfig" + "github.com/pkg/errors" ) +type block struct { + ID string `json:"ID"` + Score uint64 `json:"ExpectedScore"` + SelectedParent string `json:"ExpectedSelectedParent"` + MergeSetReds []string `json:"ExpectedReds"` + MergeSetBlues []string `json:"ExpectedBlues"` + Parents []string `json:"Parents"` +} + +// json struct: +type testDag struct { + K model.KType `json:"K"` + GenesisID string `json:"GenesisID"` + ExpectedMergeSetReds []string `json:"ExpectedReds"` + Blocks []block `json:"Blocks"` +} + +type implManager struct { + function func( + databaseContext model.DBReader, + dagTopologyManager model.DAGTopologyManager, + ghostdagDataStore model.GHOSTDAGDataStore, + headerStore model.BlockHeaderStore, + k model.KType) model.GHOSTDAGManager + implName string +} + // TestGHOSTDAG iterates over several dag simulations, and checks // that the blue score, blue set and selected parent of each // block are calculated as expected. func TestGHOSTDAG(t *testing.T) { - - type block struct { - ID string `json:"ID"` - Score uint64 `json:"ExpectedScore"` - SelectedParent string `json:"ExpectedSelectedParent"` - MergeSetReds []string `json:"ExpectedReds"` - MergeSetBlues []string `json:"ExpectedBlues"` - Parents []string `json:"Parents"` + //NOTE: FOR ADDING/REMOVING AN IMPLEMENTATION CHANGE BELOW: + implementationFactories := []implManager{ + {ghostdagmanager.New, "Original"}, + {ghostdag2.New, "Tal's impl"}, } + testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) { - // json struct: - type testDag struct { - K model.KType `json:"K"` - GenesisID string `json:"GenesisID"` - ExpectedMergeSetReds []string `json:"ExpectedReds"` - Blocks []block `json:"Blocks"` - } - - type implManager struct { - function func( - databaseContext model.DBReader, - dagTopologyManager model.DAGTopologyManager, - ghostdagDataStore model.GHOSTDAGDataStore, - k model.KType) model.GHOSTDAGManager - implName string - } - - dagTopology := &DAGTopologyManagerImpl{ - parentsMap: make(map[externalapi.DomainHash][]*externalapi.DomainHash), - } - - ghostdagDataStore := &GHOSTDAGDataStoreImpl{ - dagMap: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData), - } - blockGHOSTDAGDataGenesis := ghostdagmanager.NewBlockGHOSTDAGData(0, nil, nil, nil, nil) - - var testsCounter int - err := filepath.Walk("../../testdata/dags", func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - jsonFile, err := os.Open(path) - if err != nil { - t.Fatalf("TestGHOSTDAG : failed opening the json file %s: %v", info.Name(), err) - } - defer jsonFile.Close() - var test testDag - decoder := json.NewDecoder(jsonFile) - decoder.DisallowUnknownFields() - err = decoder.Decode(&test) - if err != nil { - t.Fatalf("TestGHOSTDAG:failed decoding json: %v", err) + dagTopology := &DAGTopologyManagerImpl{ + parentsMap: make(map[externalapi.DomainHash][]*externalapi.DomainHash), } - var genesisHash externalapi.DomainHash - copy(genesisHash[:], test.GenesisID) - - dagTopology.parentsMap[genesisHash] = nil - - ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis - - //NOTE: FOR ADDING/REMOVING AN IMPLEMENTATION CHANGE BELOW: - implementationFactories := []implManager{ - {ghostdagmanager.New, "Original"}, - {ghostdag2.New, "Tal's impl"}, + ghostdagDataStore := &GHOSTDAGDataStoreImpl{ + dagMap: make(map[externalapi.DomainHash]model.BlockGHOSTDAGData), } - for _, factory := range implementationFactories { + blockHeadersStore := &blockHeadersStore{ + dagMap: make(map[externalapi.DomainHash]*externalapi.DomainBlockHeader), + } - g := factory.function(nil, dagTopology, ghostdagDataStore, model.KType(test.K)) - for _, testBlockData := range test.Blocks { - - blockID := StringToByte(testBlockData.ID) - dagTopology.parentsMap[*blockID] = StringToByteArray(testBlockData.Parents) - - err := g.GHOSTDAG(blockID) - if err != nil { - t.Fatalf("Test failed: \n Impl: %s,FileName: %s \n error on GHOSTDAG - block %s: %s.", - factory.implName, info.Name(), testBlockData.ID, err) - } - ghostdagData, err := ghostdagDataStore.Get(nil, blockID) - if err != nil { - t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: ghostdagDataStore error: %v.", - factory.implName, info.Name(), testBlockData.ID, err) - } - - if testBlockData.Score != (ghostdagData.BlueScore()) { - t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected blue score %d but got %d.", - factory.implName, info.Name(), testBlockData.ID, testBlockData.Score, ghostdagData.BlueScore()) - } - - if *StringToByte(testBlockData.SelectedParent) != *ghostdagData.SelectedParent() { - t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected selected parent %v but got %v.", - factory.implName, info.Name(), testBlockData.ID, testBlockData.SelectedParent, ghostdagData.SelectedParent()) - } - - if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetBlues), ghostdagData.MergeSetBlues()) { - t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set blues %v but got %v.", - factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetBlues, hashesToStrings(ghostdagData.MergeSetBlues())) - } - - if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetReds), ghostdagData.MergeSetReds()) { - t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set reds %v but got %v.", - factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetReds, hashesToStrings(ghostdagData.MergeSetReds())) - } + blockGHOSTDAGDataGenesis := ghostdagmanager.NewBlockGHOSTDAGData(0, new(big.Int), nil, nil, nil, nil) + genesisHeader := params.GenesisBlock.Header + genesisWork := util.CalcWork(genesisHeader.Bits) + var testsCounter int + err := filepath.Walk("../../testdata/dags", func(path string, info os.FileInfo, err error) error { + if err != nil { + return err } - dagTopology.parentsMap = make(map[externalapi.DomainHash][]*externalapi.DomainHash) - dagTopology.parentsMap[genesisHash] = nil - ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]model.BlockGHOSTDAGData) - ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis - } + if info.IsDir() { + return nil + } + jsonFile, err := os.Open(path) + if err != nil { + t.Fatalf("TestGHOSTDAG : failed opening the json file %s: %v", info.Name(), err) + } + defer jsonFile.Close() + var test testDag + decoder := json.NewDecoder(jsonFile) + decoder.DisallowUnknownFields() + err = decoder.Decode(&test) + if err != nil { + t.Fatalf("TestGHOSTDAG:failed decoding json: %v", err) + } + params.K = test.K - testsCounter++ - return nil + var genesisHash externalapi.DomainHash + copy(genesisHash[:], test.GenesisID) + + dagTopology.parentsMap[genesisHash] = nil + + ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis + blockHeadersStore.dagMap[genesisHash] = genesisHeader + + for _, factory := range implementationFactories { + + g := factory.function(nil, dagTopology, ghostdagDataStore, blockHeadersStore, test.K) + for _, testBlockData := range test.Blocks { + + blockID := StringToByte(testBlockData.ID) + dagTopology.parentsMap[*blockID] = StringToByteArray(testBlockData.Parents) + blockHeadersStore.dagMap[*blockID] = &externalapi.DomainBlockHeader{ + ParentHashes: StringToByteArray(testBlockData.Parents), + Bits: genesisHeader.Bits, + } + + err := g.GHOSTDAG(blockID) + if err != nil { + t.Fatalf("Test failed: \n Impl: %s,FileName: %s \n error on GHOSTDAG - block %s: %s.", + factory.implName, info.Name(), testBlockData.ID, err) + } + ghostdagData, err := ghostdagDataStore.Get(nil, blockID) + if err != nil { + t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: ghostdagDataStore error: %v.", + factory.implName, info.Name(), testBlockData.ID, err) + } + + // because the difficulty is constant and equal to genesis the work should be blueScore*genesisWork. + expectedWork := new(big.Int).Mul(genesisWork, new(big.Int).SetUint64(testBlockData.Score)) + if expectedWork.Cmp(ghostdagData.BlueWork()) != 0 { + t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected blue work %d but got %d.", + factory.implName, info.Name(), testBlockData.ID, expectedWork, ghostdagData.BlueWork()) + } + if testBlockData.Score != (ghostdagData.BlueScore()) { + t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected blue score %d but got %d.", + factory.implName, info.Name(), testBlockData.ID, testBlockData.Score, ghostdagData.BlueScore()) + } + + if *StringToByte(testBlockData.SelectedParent) != *ghostdagData.SelectedParent() { + t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected selected parent %v but got %v.", + factory.implName, info.Name(), testBlockData.ID, testBlockData.SelectedParent, string(ghostdagData.SelectedParent()[:])) + } + + if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetBlues), ghostdagData.MergeSetBlues()) { + t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set blues %v but got %v.", + factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetBlues, hashesToStrings(ghostdagData.MergeSetBlues())) + } + + if !reflect.DeepEqual(StringToByteArray(testBlockData.MergeSetReds), ghostdagData.MergeSetReds()) { + t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected merge set reds %v but got %v.", + factory.implName, info.Name(), testBlockData.ID, testBlockData.MergeSetReds, hashesToStrings(ghostdagData.MergeSetReds())) + } + } + dagTopology.parentsMap = make(map[externalapi.DomainHash][]*externalapi.DomainHash) + dagTopology.parentsMap[genesisHash] = nil + ghostdagDataStore.dagMap = make(map[externalapi.DomainHash]model.BlockGHOSTDAGData) + ghostdagDataStore.dagMap[genesisHash] = blockGHOSTDAGDataGenesis + blockHeadersStore.dagMap = make(map[externalapi.DomainHash]*externalapi.DomainBlockHeader) + blockHeadersStore.dagMap[genesisHash] = genesisHeader + } + + testsCounter++ + return nil + }) + if err != nil { + t.Fatal(err) + } + if testsCounter != 3 { + t.Fatalf("Expected 3 test files, ran %d instead", testsCounter) + } }) - if err != nil { - t.Fatal(err) - } - if testsCounter != 3 { - t.Fatalf("Expected 3 test files, ran %d instead", testsCounter) - } } func hashesToStrings(arr []*externalapi.DomainHash) []string { @@ -268,3 +294,50 @@ func (dt *DAGTopologyManagerImpl) IsInSelectedParentChainOf(blockHashA *external func (dt *DAGTopologyManagerImpl) SetParents(blockHash *externalapi.DomainHash, parentHashes []*externalapi.DomainHash) error { panic("unimplemented") } + +type blockHeadersStore struct { + dagMap map[externalapi.DomainHash]*externalapi.DomainBlockHeader +} + +func (b *blockHeadersStore) Discard() { panic("unimplemented") } + +func (b *blockHeadersStore) Commit(_ model.DBTransaction) error { panic("unimplemented") } + +func (b *blockHeadersStore) Stage(blockHash *externalapi.DomainHash, blockHeader *externalapi.DomainBlockHeader) { + b.dagMap[*blockHash] = blockHeader +} + +func (b *blockHeadersStore) IsStaged() bool { panic("unimplemented") } + +func (b *blockHeadersStore) BlockHeader(_ model.DBReader, blockHash *externalapi.DomainHash) (*externalapi.DomainBlockHeader, error) { + header, ok := b.dagMap[*blockHash] + if ok { + return header, nil + } + return nil, errors.New("Header isn't in the store") +} + +func (b *blockHeadersStore) HasBlockHeader(_ model.DBReader, blockHash *externalapi.DomainHash) (bool, error) { + _, ok := b.dagMap[*blockHash] + return ok, nil +} + +func (b *blockHeadersStore) BlockHeaders(_ model.DBReader, blockHashes []*externalapi.DomainHash) ([]*externalapi.DomainBlockHeader, error) { + res := make([]*externalapi.DomainBlockHeader, 0, len(blockHashes)) + for _, hash := range blockHashes { + header, err := b.BlockHeader(nil, hash) + if err != nil { + return nil, err + } + res = append(res, header) + } + return res, nil +} + +func (b *blockHeadersStore) Delete(blockHash *externalapi.DomainHash) { + delete(b.dagMap, *blockHash) +} + +func (b blockHeadersStore) Count() uint64 { + return uint64(len(b.dagMap)) +} diff --git a/domain/consensus/processes/ghostdagmanager/ghostdagmanager.go b/domain/consensus/processes/ghostdagmanager/ghostdagmanager.go index 821bdb81c..c47dfebc5 100644 --- a/domain/consensus/processes/ghostdagmanager/ghostdagmanager.go +++ b/domain/consensus/processes/ghostdagmanager/ghostdagmanager.go @@ -9,6 +9,7 @@ type ghostdagManager struct { databaseContext model.DBReader dagTopologyManager model.DAGTopologyManager ghostdagDataStore model.GHOSTDAGDataStore + headerStore model.BlockHeaderStore k model.KType } @@ -17,12 +18,14 @@ func New( databaseContext model.DBReader, dagTopologyManager model.DAGTopologyManager, ghostdagDataStore model.GHOSTDAGDataStore, + headerStore model.BlockHeaderStore, k model.KType) model.GHOSTDAGManager { return &ghostdagManager{ databaseContext: databaseContext, dagTopologyManager: dagTopologyManager, ghostdagDataStore: ghostdagDataStore, + headerStore: headerStore, k: k, } }