diff --git a/api/service/blockApiService_test.go b/api/service/blockApiService_test.go index c182a0b1a..30b766c45 100644 --- a/api/service/blockApiService_test.go +++ b/api/service/blockApiService_test.go @@ -99,6 +99,9 @@ func (*mockQueryExecutorGetBlocksSuccess) ExecuteSelect(qe string, tx bool, args mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ).AddRow( mockGoodBlock.GetHeight(), mockGoodBlock.GetID(), @@ -115,6 +118,9 @@ func (*mockQueryExecutorGetBlocksSuccess) ExecuteSelect(qe string, tx bool, args mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), )) rows, _ := db.Query(qe) return rows, nil @@ -149,6 +155,9 @@ func (*mockQueryGetBlockByIDSuccess) ExecuteSelectRow(qStr string, tx bool, args mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -259,6 +268,9 @@ func (*mockQueryGetBlockByHeightSuccess) ExecuteSelectRow(qStr string, tx bool, mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -374,6 +386,9 @@ func (*mockQueryGetBlocksSuccess) ExecuteSelect(qStr string, tx bool, args ...in mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ), ) return db.Query(qStr) diff --git a/cmd/genesisblock/cmd.go b/cmd/genesisblock/cmd.go index 5e78786cf..c8a0a9ea6 100644 --- a/cmd/genesisblock/cmd.go +++ b/cmd/genesisblock/cmd.go @@ -584,6 +584,7 @@ func getGenesisBlockID(genesisEntries []genesisEntry) (mainBlockID, spineBlockID nil, nil, nil, + bs, ) spine, err := sb.GenerateGenesisBlock(genesisConfig) if err != nil { diff --git a/common/auth/nodeAuthValidation_test.go b/common/auth/nodeAuthValidation_test.go index 353b623fd..40a2e9a99 100644 --- a/common/auth/nodeAuthValidation_test.go +++ b/common/auth/nodeAuthValidation_test.go @@ -48,6 +48,9 @@ func (*mockExecutorValidateSuccess) ExecuteSelectRow(qStr string, tx bool, args 10000000, 1, 0, + []byte{}, + []byte{}, + 0, ) mock.ExpectQuery("SELECT").WillReturnRows(mockedRows) return db.QueryRow(qStr), nil diff --git a/common/constant/smith.go b/common/constant/smith.go index 484c32a2b..0e5a3d5fa 100644 --- a/common/constant/smith.go +++ b/common/constant/smith.go @@ -42,7 +42,8 @@ var ( Spinechain smithing */ - SpineSmithingBlockCreationTime = int64(30) - SpineSmithingNetworkTolerance = int64(15) - SpineSmithingBlocksmithTimeGap = int64(10) + SpineSmithingBlockCreationTime = int64(30) + SpineSmithingNetworkTolerance = int64(15) + SpineSmithingBlocksmithTimeGap = int64(10) + SpineReferenceBlockHeightOffset = uint32(5) ) diff --git a/common/database/migration.go b/common/database/migration.go index c2f55dff7..17064a41f 100644 --- a/common/database/migration.go +++ b/common/database/migration.go @@ -449,6 +449,30 @@ func (m *Migration) Init() error { ` CREATE INDEX "transaction_block_id_idx" ON "transaction" ("block_id") `, + ` + ALTER TABLE "main_block" + ADD COLUMN "merkle_root" BLOB AFTER "payload_hash" + `, + ` + ALTER TABLE "main_block" + ADD COLUMN "merkle_tree" BLOB AFTER "merkle_root" + `, + ` + ALTER TABLE "main_block" + ADD COLUMN "reference_block_height" INTEGER AFTER "merkle_tree" + `, + ` + ALTER TABLE "spine_block" + ADD COLUMN "merkle_root" BLOB AFTER "payload_hash" + `, + ` + ALTER TABLE "spine_block" + ADD COLUMN "merkle_tree" BLOB AFTER "merkle_root" + `, + ` + ALTER TABLE "spine_block" + ADD COLUMN "reference_block_height" INTEGER AFTER "merkle_tree" + `, } return nil } diff --git a/common/model/block.pb.go b/common/model/block.pb.go index 548080677..52784c726 100644 --- a/common/model/block.pb.go +++ b/common/model/block.pb.go @@ -37,11 +37,14 @@ type Block struct { Version uint32 `protobuf:"varint,13,opt,name=Version,proto3" json:"Version,omitempty"` PayloadLength uint32 `protobuf:"varint,14,opt,name=PayloadLength,proto3" json:"PayloadLength,omitempty"` PayloadHash []byte `protobuf:"bytes,15,opt,name=PayloadHash,proto3" json:"PayloadHash,omitempty"` - Transactions []*Transaction `protobuf:"bytes,16,rep,name=Transactions,proto3" json:"Transactions,omitempty"` - PublishedReceipts []*PublishedReceipt `protobuf:"bytes,17,rep,name=PublishedReceipts,proto3" json:"PublishedReceipts,omitempty"` - SpinePublicKeys []*SpinePublicKey `protobuf:"bytes,18,rep,name=SpinePublicKeys,proto3" json:"SpinePublicKeys,omitempty"` - SpineBlockManifests []*SpineBlockManifest `protobuf:"bytes,19,rep,name=SpineBlockManifests,proto3" json:"SpineBlockManifests,omitempty"` - TransactionIDs []int64 `protobuf:"varint,20,rep,packed,name=TransactionIDs,proto3" json:"TransactionIDs,omitempty"` + MerkleRoot []byte `protobuf:"bytes,16,opt,name=MerkleRoot,proto3" json:"MerkleRoot,omitempty"` + MerkleTree []byte `protobuf:"bytes,17,opt,name=MerkleTree,proto3" json:"MerkleTree,omitempty"` + ReferenceBlockHeight uint32 `protobuf:"varint,18,opt,name=ReferenceBlockHeight,proto3" json:"ReferenceBlockHeight,omitempty"` + Transactions []*Transaction `protobuf:"bytes,19,rep,name=Transactions,proto3" json:"Transactions,omitempty"` + PublishedReceipts []*PublishedReceipt `protobuf:"bytes,20,rep,name=PublishedReceipts,proto3" json:"PublishedReceipts,omitempty"` + SpinePublicKeys []*SpinePublicKey `protobuf:"bytes,21,rep,name=SpinePublicKeys,proto3" json:"SpinePublicKeys,omitempty"` + SpineBlockManifests []*SpineBlockManifest `protobuf:"bytes,22,rep,name=SpineBlockManifests,proto3" json:"SpineBlockManifests,omitempty"` + TransactionIDs []int64 `protobuf:"varint,23,rep,packed,name=TransactionIDs,proto3" json:"TransactionIDs,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -177,6 +180,27 @@ func (m *Block) GetPayloadHash() []byte { return nil } +func (m *Block) GetMerkleRoot() []byte { + if m != nil { + return m.MerkleRoot + } + return nil +} + +func (m *Block) GetMerkleTree() []byte { + if m != nil { + return m.MerkleTree + } + return nil +} + +func (m *Block) GetReferenceBlockHeight() uint32 { + if m != nil { + return m.ReferenceBlockHeight + } + return 0 +} + func (m *Block) GetTransactions() []*Transaction { if m != nil { return m.Transactions @@ -830,61 +854,64 @@ func init() { } var fileDescriptor_baa78346dbb08dbe = []byte{ - // 888 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdf, 0x6f, 0xda, 0x46, - 0x1c, 0x17, 0x50, 0x48, 0xf8, 0x02, 0x4d, 0xb8, 0xb0, 0xf6, 0x56, 0x65, 0x11, 0xb2, 0xa2, 0x0a, - 0x4d, 0x5d, 0x52, 0x65, 0xd2, 0x26, 0xf5, 0x65, 0x0a, 0xd0, 0x35, 0xa8, 0xd9, 0x84, 0x0c, 0xea, - 0xc3, 0x26, 0x4d, 0x32, 0xf6, 0x37, 0xf8, 0x56, 0xec, 0xf3, 0x7c, 0xe7, 0x2a, 0xd9, 0xc3, 0xde, - 0xf6, 0x07, 0xed, 0x7f, 0xd9, 0x1f, 0x34, 0xf9, 0x7c, 0xd8, 0x67, 0x87, 0x68, 0x79, 0xe8, 0x0b, - 0xe2, 0x3e, 0x9f, 0xef, 0xef, 0x5f, 0x00, 0xfd, 0x80, 0x7b, 0xb8, 0x39, 0x5f, 0x6d, 0xb8, 0xfb, - 0xf1, 0x2c, 0x8a, 0xb9, 0xe4, 0xa4, 0xa9, 0xa0, 0x17, 0xcf, 0x33, 0x46, 0xc6, 0x4e, 0x28, 0x1c, - 0x57, 0x32, 0x1e, 0x66, 0xfc, 0x0b, 0xaa, 0x55, 0x1c, 0xe9, 0xfa, 0x36, 0xba, 0xc8, 0x22, 0xa9, - 0x99, 0xe3, 0x8c, 0x89, 0x92, 0xd5, 0x86, 0x09, 0x1f, 0xbd, 0x32, 0xfb, 0x55, 0xc6, 0x8a, 0x8f, - 0x2c, 0x8a, 0xd0, 0x1b, 0xa7, 0x1e, 0x45, 0xc0, 0xa4, 0xaf, 0x69, 0x1d, 0x89, 0x88, 0x58, 0x88, - 0x1a, 0x3a, 0x31, 0x20, 0x25, 0xff, 0x93, 0x13, 0xb2, 0x1b, 0x14, 0xda, 0xa2, 0xf5, 0x6f, 0x0b, - 0x9a, 0x0a, 0x27, 0x04, 0xea, 0xb3, 0x29, 0xad, 0x0d, 0x6b, 0xa3, 0xc6, 0xb8, 0xfe, 0xba, 0x66, - 0xd7, 0x67, 0x53, 0x72, 0x0c, 0x6d, 0x45, 0x5e, 0x39, 0xc2, 0xa7, 0xf5, 0x61, 0x6d, 0xd4, 0xb5, - 0x0b, 0x80, 0xbc, 0x82, 0xfe, 0x3c, 0xc6, 0x4f, 0x8c, 0x27, 0xa2, 0x90, 0x6a, 0x28, 0xa9, 0xfb, - 0x04, 0x79, 0x06, 0xad, 0x2b, 0x64, 0x6b, 0x5f, 0xd2, 0x27, 0xc3, 0xda, 0xa8, 0x67, 0xeb, 0x17, - 0x19, 0x42, 0x7b, 0xc9, 0x02, 0x14, 0xd2, 0x09, 0x22, 0xda, 0xcc, 0xdd, 0x17, 0x60, 0x1e, 0xc5, - 0x02, 0xd1, 0xa3, 0x2d, 0x23, 0x8a, 0x14, 0x20, 0x2f, 0xe1, 0x69, 0xf6, 0x60, 0xeb, 0xd0, 0x91, - 0x49, 0x8c, 0x74, 0x4f, 0x89, 0x54, 0x50, 0x72, 0x01, 0x83, 0x49, 0x12, 0x24, 0x1b, 0x47, 0xb2, - 0x4f, 0x38, 0x65, 0x37, 0x37, 0xcc, 0x4d, 0x36, 0xf2, 0x8e, 0xee, 0x0f, 0x6b, 0xa3, 0xb6, 0xbd, - 0x93, 0x23, 0xaf, 0xe1, 0xa8, 0x28, 0xf2, 0x3c, 0xed, 0x89, 0xfb, 0x1e, 0xef, 0x68, 0x5b, 0x39, - 0xd8, 0x45, 0x91, 0x53, 0xe8, 0x2c, 0xb9, 0x74, 0x36, 0x97, 0x01, 0x4f, 0x42, 0x49, 0x21, 0xcf, - 0xc7, 0x84, 0xc9, 0x09, 0xec, 0xab, 0xe7, 0x8f, 0x88, 0xb4, 0x93, 0x8b, 0xe4, 0x18, 0x19, 0x41, - 0x4f, 0x7d, 0x9f, 0x70, 0x16, 0x8e, 0x1d, 0x81, 0xb4, 0x9b, 0x0b, 0x95, 0x09, 0x42, 0x61, 0xef, - 0x03, 0xc6, 0x82, 0xf1, 0x90, 0xf6, 0x54, 0x59, 0xb7, 0x4f, 0x72, 0x0a, 0xbd, 0xb9, 0x73, 0xb7, - 0xe1, 0x8e, 0x77, 0x8d, 0xe1, 0x5a, 0xfa, 0xf4, 0xa9, 0xe2, 0xcb, 0x20, 0x19, 0x42, 0x47, 0x03, - 0xaa, 0x7b, 0x07, 0x2a, 0x33, 0x13, 0x22, 0xdf, 0x41, 0x77, 0x59, 0x0c, 0xb0, 0xa0, 0x87, 0xc3, - 0xc6, 0xa8, 0x73, 0x41, 0xce, 0xd4, 0x60, 0x9d, 0x19, 0x94, 0x5d, 0x92, 0x23, 0x6f, 0xa1, 0x3f, - 0xaf, 0x4c, 0xb1, 0xa0, 0x7d, 0xa5, 0xfc, 0x5c, 0x2b, 0x57, 0x79, 0xfb, 0xbe, 0x06, 0xf9, 0x01, - 0x0e, 0x16, 0xe9, 0xf0, 0xe6, 0x25, 0x16, 0x94, 0x28, 0x23, 0x5f, 0x68, 0x23, 0x65, 0xd6, 0xae, - 0x4a, 0x93, 0xf7, 0x70, 0xb4, 0xb8, 0x37, 0xfd, 0x82, 0x1e, 0x29, 0x23, 0x5f, 0x9a, 0x46, 0x4a, - 0x12, 0xf6, 0x2e, 0xad, 0x74, 0xd8, 0x8c, 0x24, 0x67, 0x53, 0x41, 0x07, 0xc3, 0xc6, 0xa8, 0x61, - 0x57, 0x50, 0xeb, 0x9f, 0x3a, 0xf4, 0x95, 0xea, 0xdb, 0x5b, 0x89, 0xa1, 0x87, 0xde, 0x2c, 0xbc, - 0xe1, 0xc4, 0xd2, 0xbb, 0xa6, 0xb6, 0xac, 0x73, 0xd1, 0xd5, 0xce, 0x15, 0x66, 0xeb, 0x35, 0xdc, - 0xb6, 0x3e, 0x2f, 0x59, 0xbd, 0xd2, 0xfa, 0xbc, 0x32, 0x2f, 0xa1, 0xab, 0xbf, 0x7f, 0x70, 0x36, - 0x09, 0xaa, 0xcd, 0xcb, 0x04, 0x4b, 0x38, 0x79, 0x03, 0xb4, 0x98, 0xd4, 0x4b, 0xd7, 0x4d, 0x27, - 0xf0, 0xd2, 0xf3, 0x62, 0x14, 0x42, 0xad, 0x62, 0xdb, 0x7e, 0x90, 0x4f, 0x97, 0x73, 0xce, 0xa3, - 0x89, 0xef, 0x84, 0x6b, 0x34, 0x97, 0x33, 0x07, 0xc9, 0x15, 0x90, 0x45, 0xf5, 0x1c, 0x09, 0xda, - 0x52, 0xd5, 0xa5, 0xdb, 0xea, 0x56, 0x05, 0xec, 0x1d, 0x3a, 0xd6, 0xaf, 0x70, 0xf0, 0x0e, 0x65, - 0x56, 0x0c, 0xfc, 0x23, 0x41, 0x21, 0xd3, 0xcd, 0x9f, 0xf8, 0x0e, 0x0b, 0x97, 0x77, 0x11, 0xaa, - 0xa2, 0x35, 0xed, 0x02, 0xd0, 0x17, 0xab, 0x5e, 0xba, 0x58, 0xc5, 0x95, 0x69, 0x98, 0x57, 0xc6, - 0x5a, 0xc2, 0x61, 0x61, 0x5c, 0x44, 0x3c, 0x14, 0xf8, 0x3f, 0xd6, 0xf3, 0x66, 0xd5, 0x1f, 0x6c, - 0x96, 0xf5, 0x5b, 0x61, 0x55, 0x3c, 0x2e, 0xe6, 0x01, 0x34, 0xaf, 0x59, 0xc0, 0xa4, 0xb2, 0xda, - 0xb3, 0xb3, 0xc7, 0x83, 0x51, 0xff, 0x5d, 0x83, 0xbe, 0xe1, 0xe0, 0x51, 0x71, 0x0f, 0xa0, 0x39, - 0x51, 0xb7, 0x47, 0x7b, 0x50, 0x8f, 0x87, 0x3c, 0x90, 0x53, 0x68, 0x65, 0xd6, 0xe9, 0x13, 0xd5, - 0xb2, 0x72, 0x9a, 0x9a, 0xb3, 0x7e, 0x87, 0x67, 0xef, 0x50, 0xfe, 0x8c, 0xb7, 0x59, 0x28, 0x33, - 0xef, 0x91, 0xd9, 0x1e, 0xc3, 0x9e, 0x56, 0x30, 0xda, 0xb4, 0x85, 0x8a, 0x5a, 0x34, 0x8c, 0x5a, - 0x58, 0x17, 0x70, 0x58, 0x38, 0xd1, 0x19, 0x9f, 0xc0, 0xfe, 0x16, 0xa3, 0xb5, 0x74, 0xe1, 0xb2, - 0x7b, 0xb9, 0xc5, 0xac, 0x18, 0x06, 0x66, 0x7c, 0x9f, 0x25, 0x3a, 0xd3, 0x67, 0x63, 0x87, 0xcf, - 0x37, 0x00, 0x99, 0xb3, 0xa9, 0x23, 0x1d, 0xf2, 0x0a, 0xa0, 0x70, 0xaf, 0x62, 0xac, 0xd6, 0xd2, - 0xe0, 0xad, 0xbf, 0xe0, 0x70, 0x81, 0xa1, 0x57, 0x9a, 0xf5, 0xc7, 0x1c, 0x87, 0x52, 0x3e, 0xf5, - 0x6a, 0x3e, 0x23, 0x38, 0x48, 0xad, 0x62, 0x5c, 0xfc, 0x52, 0x65, 0xbf, 0xc6, 0x55, 0xd8, 0xba, - 0x86, 0xbe, 0xe1, 0x5f, 0x17, 0xf9, 0x7b, 0xe8, 0x8e, 0x8d, 0x3f, 0x24, 0x3a, 0x8e, 0xa3, 0x6d, - 0x1c, 0x06, 0x65, 0x97, 0x04, 0xc7, 0x5f, 0xff, 0x32, 0x5a, 0x33, 0xe9, 0x27, 0xab, 0x33, 0x97, - 0x07, 0xe7, 0x7f, 0x72, 0xbe, 0x72, 0xb3, 0xcf, 0x6f, 0x5c, 0x1e, 0xe3, 0xb9, 0xcb, 0x83, 0x80, - 0x87, 0xe7, 0xca, 0xcc, 0xaa, 0xa5, 0xfe, 0x76, 0x7c, 0xfb, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xd7, 0x4a, 0x6b, 0x95, 0x35, 0x09, 0x00, 0x00, + // 930 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdd, 0x6e, 0xe2, 0x46, + 0x1b, 0x16, 0xb0, 0x90, 0xf0, 0x02, 0x9b, 0x30, 0x61, 0x93, 0xf9, 0x56, 0xf9, 0x22, 0x64, 0x45, + 0x2b, 0x54, 0x6d, 0x93, 0x55, 0x2a, 0xb5, 0xd2, 0x9e, 0x54, 0x01, 0xb6, 0x1b, 0xb4, 0xd9, 0x0a, + 0x19, 0xb4, 0x07, 0xad, 0x54, 0xc9, 0xd8, 0x2f, 0x30, 0x0d, 0xf6, 0xb8, 0x9e, 0xf1, 0x6a, 0xd3, + 0x83, 0x9e, 0xf5, 0x82, 0x7a, 0x17, 0xbd, 0xac, 0xca, 0xe3, 0xc1, 0x1e, 0x3b, 0x44, 0xcd, 0x41, + 0x4f, 0x22, 0xe6, 0x79, 0xde, 0xff, 0xbf, 0x18, 0xba, 0x3e, 0xf7, 0x70, 0x73, 0xb9, 0xd8, 0x70, + 0xf7, 0xee, 0x22, 0x8c, 0xb8, 0xe4, 0xa4, 0xae, 0xa0, 0x97, 0x27, 0x29, 0x23, 0x23, 0x27, 0x10, + 0x8e, 0x2b, 0x19, 0x0f, 0x52, 0xfe, 0x25, 0xd5, 0x2a, 0x8e, 0x74, 0xd7, 0x36, 0xba, 0xc8, 0x42, + 0xa9, 0x99, 0xd3, 0x94, 0x09, 0xe3, 0xc5, 0x86, 0x89, 0x35, 0x7a, 0x45, 0xf6, 0xff, 0x29, 0x2b, + 0xee, 0x58, 0x18, 0xa2, 0x37, 0x4c, 0x3c, 0x0a, 0x9f, 0xc9, 0xb5, 0xa6, 0x75, 0x24, 0x22, 0x64, + 0x01, 0x6a, 0xe8, 0xcc, 0x80, 0x94, 0xfc, 0x47, 0x27, 0x60, 0x4b, 0x14, 0xda, 0xa2, 0xf5, 0xf7, + 0x1e, 0xd4, 0x15, 0x4e, 0x08, 0x54, 0x27, 0x63, 0x5a, 0xe9, 0x57, 0x06, 0xb5, 0x61, 0xf5, 0x4d, + 0xc5, 0xae, 0x4e, 0xc6, 0xe4, 0x14, 0x9a, 0x8a, 0xbc, 0x71, 0xc4, 0x9a, 0x56, 0xfb, 0x95, 0x41, + 0xdb, 0xce, 0x01, 0xf2, 0x1a, 0xba, 0xd3, 0x08, 0x3f, 0x33, 0x1e, 0x8b, 0x5c, 0xaa, 0xa6, 0xa4, + 0x1e, 0x12, 0xe4, 0x18, 0x1a, 0x37, 0xc8, 0x56, 0x6b, 0x49, 0x9f, 0xf5, 0x2b, 0x83, 0x8e, 0xad, + 0x5f, 0xa4, 0x0f, 0xcd, 0x39, 0xf3, 0x51, 0x48, 0xc7, 0x0f, 0x69, 0x3d, 0x73, 0x9f, 0x83, 0x59, + 0x14, 0x33, 0x44, 0x8f, 0x36, 0x8c, 0x28, 0x12, 0x80, 0xbc, 0x82, 0xe7, 0xe9, 0x83, 0xad, 0x02, + 0x47, 0xc6, 0x11, 0xd2, 0x3d, 0x25, 0x52, 0x42, 0xc9, 0x15, 0xf4, 0x46, 0xb1, 0x1f, 0x6f, 0x1c, + 0xc9, 0x3e, 0xe3, 0x98, 0x2d, 0x97, 0xcc, 0x8d, 0x37, 0xf2, 0x9e, 0xee, 0xf7, 0x2b, 0x83, 0xa6, + 0xbd, 0x93, 0x23, 0x6f, 0xe0, 0x28, 0x2f, 0xf2, 0x34, 0xe9, 0x89, 0xfb, 0x01, 0xef, 0x69, 0x53, + 0x39, 0xd8, 0x45, 0x91, 0x73, 0x68, 0xcd, 0xb9, 0x74, 0x36, 0xd7, 0x3e, 0x8f, 0x03, 0x49, 0x21, + 0xcb, 0xc7, 0x84, 0xc9, 0x19, 0xec, 0xab, 0xe7, 0x0f, 0x88, 0xb4, 0x95, 0x89, 0x64, 0x18, 0x19, + 0x40, 0x47, 0xfd, 0x1e, 0x71, 0x16, 0x0c, 0x1d, 0x81, 0xb4, 0x9d, 0x09, 0x15, 0x09, 0x42, 0x61, + 0xef, 0x13, 0x46, 0x82, 0xf1, 0x80, 0x76, 0x54, 0x59, 0xb7, 0x4f, 0x72, 0x0e, 0x9d, 0xa9, 0x73, + 0xbf, 0xe1, 0x8e, 0x77, 0x8b, 0xc1, 0x4a, 0xae, 0xe9, 0x73, 0xc5, 0x17, 0x41, 0xd2, 0x87, 0x96, + 0x06, 0x54, 0xf7, 0x0e, 0x54, 0x66, 0x26, 0x44, 0xce, 0x00, 0x3e, 0x62, 0x74, 0xb7, 0x41, 0x9b, + 0x73, 0x49, 0x0f, 0x95, 0x80, 0x81, 0xe4, 0xfc, 0x3c, 0x42, 0xa4, 0x5d, 0x93, 0x4f, 0x90, 0xa4, + 0xee, 0x36, 0x2e, 0x31, 0xc2, 0xc0, 0x4d, 0x27, 0x50, 0x4f, 0x01, 0x51, 0xe1, 0xec, 0xe4, 0xc8, + 0xb7, 0xd0, 0x9e, 0xe7, 0x4b, 0x23, 0xe8, 0x51, 0xbf, 0x36, 0x68, 0x5d, 0x91, 0x0b, 0x35, 0xcc, + 0x17, 0x06, 0x65, 0x17, 0xe4, 0xc8, 0x3b, 0xe8, 0x4e, 0x4b, 0x9b, 0x23, 0x68, 0x4f, 0x29, 0x9f, + 0x68, 0xe5, 0x32, 0x6f, 0x3f, 0xd4, 0x20, 0xdf, 0xc3, 0xc1, 0x2c, 0x59, 0x98, 0xac, 0xad, 0x82, + 0xbe, 0x50, 0x46, 0x5e, 0x68, 0x23, 0x45, 0xd6, 0x2e, 0x4b, 0x93, 0x0f, 0x70, 0x34, 0x7b, 0xb0, + 0x71, 0x82, 0x1e, 0x2b, 0x23, 0xff, 0x33, 0x8d, 0x14, 0x24, 0xec, 0x5d, 0x5a, 0xc9, 0x80, 0x1b, + 0x49, 0x4e, 0xc6, 0x82, 0x9e, 0xf4, 0x6b, 0x83, 0x9a, 0x5d, 0x42, 0xad, 0xbf, 0xaa, 0xd0, 0x55, + 0xaa, 0xef, 0xbe, 0x48, 0x0c, 0x3c, 0xf4, 0x26, 0xc1, 0x92, 0x13, 0x4b, 0xef, 0xb7, 0xda, 0xec, + 0xd6, 0x55, 0x5b, 0x3b, 0x57, 0x98, 0xad, 0x57, 0x7f, 0x3b, 0x6e, 0x59, 0xc9, 0xaa, 0xa5, 0x71, + 0xcb, 0x2a, 0xf3, 0x0a, 0xda, 0xfa, 0xf7, 0x27, 0x67, 0x13, 0xa3, 0xda, 0xf6, 0x54, 0xb0, 0x80, + 0x93, 0xb7, 0x40, 0xf3, 0xed, 0xb8, 0x76, 0xdd, 0x64, 0xea, 0xaf, 0x3d, 0x2f, 0x42, 0x21, 0xd4, + 0xfa, 0x37, 0xed, 0x47, 0xf9, 0xe4, 0x20, 0x4c, 0x79, 0x38, 0x5a, 0x3b, 0xc1, 0x0a, 0xcd, 0x83, + 0x90, 0x81, 0xe4, 0x06, 0xc8, 0xac, 0x7c, 0x02, 0x05, 0x6d, 0xa8, 0xea, 0xd2, 0x6d, 0x75, 0xcb, + 0x02, 0xf6, 0x0e, 0x1d, 0xeb, 0x67, 0x38, 0x78, 0x8f, 0x32, 0x2d, 0x06, 0xfe, 0x16, 0xa3, 0x90, + 0xc9, 0xb5, 0x19, 0xad, 0x1d, 0x16, 0xcc, 0xef, 0x43, 0x54, 0x45, 0xab, 0xdb, 0x39, 0xa0, 0xaf, + 0x64, 0xb5, 0x70, 0x25, 0xf3, 0xcb, 0x56, 0x33, 0x2f, 0x9b, 0x35, 0x87, 0xc3, 0xdc, 0xb8, 0x08, + 0x79, 0x20, 0xf0, 0x5f, 0xac, 0x67, 0xcd, 0xaa, 0x3e, 0xda, 0x2c, 0xeb, 0x97, 0xdc, 0xaa, 0x78, + 0x5a, 0xcc, 0x3d, 0xa8, 0xdf, 0x32, 0x9f, 0x49, 0x65, 0xb5, 0x63, 0xa7, 0x8f, 0x47, 0xa3, 0xfe, + 0xb3, 0x02, 0x5d, 0xc3, 0xc1, 0x93, 0xe2, 0xee, 0x41, 0x7d, 0xa4, 0xee, 0x9d, 0xf6, 0xa0, 0x1e, + 0x8f, 0x79, 0x20, 0xe7, 0xd0, 0x48, 0xad, 0xd3, 0x67, 0xaa, 0x65, 0xc5, 0x34, 0x35, 0x67, 0xfd, + 0x0a, 0xc7, 0xef, 0x51, 0xfe, 0x88, 0x5f, 0xd2, 0x50, 0x26, 0xde, 0x13, 0xb3, 0x3d, 0x85, 0x3d, + 0xad, 0x60, 0xb4, 0x69, 0x0b, 0xe5, 0xb5, 0xa8, 0x19, 0xb5, 0xb0, 0xae, 0xe0, 0x30, 0x77, 0xa2, + 0x33, 0x3e, 0x83, 0xfd, 0x2d, 0x46, 0x2b, 0xc9, 0xc2, 0xa5, 0x37, 0x7a, 0x8b, 0x59, 0x11, 0xf4, + 0xcc, 0xf8, 0xfe, 0x93, 0xe8, 0x4c, 0x9f, 0xb5, 0x1d, 0x3e, 0xdf, 0x02, 0xa4, 0xce, 0xc6, 0x8e, + 0x74, 0xc8, 0x6b, 0x80, 0xdc, 0xbd, 0x8a, 0xb1, 0x5c, 0x4b, 0x83, 0xb7, 0xfe, 0x80, 0xc3, 0x19, + 0x06, 0x5e, 0x61, 0xd6, 0x9f, 0x72, 0x1c, 0x0a, 0xf9, 0x54, 0xcb, 0xf9, 0x0c, 0xe0, 0x20, 0xb1, + 0x8a, 0x51, 0xfe, 0xdf, 0x31, 0xfd, 0x02, 0x28, 0xc3, 0xd6, 0x2d, 0x74, 0x0d, 0xff, 0xba, 0xc8, + 0xdf, 0x41, 0x7b, 0x68, 0x7c, 0x04, 0xe9, 0x38, 0x8e, 0xb6, 0x71, 0x18, 0x94, 0x5d, 0x10, 0x1c, + 0x7e, 0xf5, 0xd3, 0x60, 0xc5, 0xe4, 0x3a, 0x5e, 0x5c, 0xb8, 0xdc, 0xbf, 0xfc, 0x9d, 0xf3, 0x85, + 0x9b, 0xfe, 0xfd, 0xda, 0xe5, 0x11, 0x5e, 0xba, 0xdc, 0xf7, 0x79, 0x70, 0xa9, 0xcc, 0x2c, 0x1a, + 0xea, 0x53, 0xe7, 0x9b, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xff, 0xb8, 0x48, 0xbb, 0xa9, 0x09, + 0x00, 0x00, } diff --git a/common/query/blockQuery.go b/common/query/blockQuery.go index 163fbe59d..ffc753ded 100644 --- a/common/query/blockQuery.go +++ b/common/query/blockQuery.go @@ -54,6 +54,9 @@ func NewBlockQuery(chaintype chaintype.ChainType) *BlockQuery { "total_fee", "total_coinbase", "version", + "merkle_root", + "merkle_tree", + "reference_block_height", }, TableName: "block", ChainType: chaintype, @@ -175,6 +178,9 @@ func (*BlockQuery) ExtractModel(block *model.Block) []interface{} { block.TotalFee, block.TotalCoinBase, block.Version, + block.MerkleRoot, + block.MerkleTree, + block.ReferenceBlockHeight, } } @@ -201,6 +207,9 @@ func (*BlockQuery) BuildModel(blocks []*model.Block, rows *sql.Rows) ([]*model.B &block.TotalFee, &block.TotalCoinBase, &block.Version, + &block.MerkleRoot, + &block.MerkleTree, + &block.ReferenceBlockHeight, ) if err != nil { return nil, err @@ -227,6 +236,9 @@ func (*BlockQuery) Scan(block *model.Block, row *sql.Row) error { &block.TotalFee, &block.TotalCoinBase, &block.Version, + &block.MerkleRoot, + &block.MerkleTree, + &block.ReferenceBlockHeight, ) if err != nil { return err diff --git a/common/query/blockQuery_test.go b/common/query/blockQuery_test.go index 8c170078e..fcb4a3212 100644 --- a/common/query/blockQuery_test.go +++ b/common/query/blockQuery_test.go @@ -75,7 +75,8 @@ func TestBlockQuery_GetBlocks(t *testing.T) { q := mockBlockQuery.GetBlocks(0, 10) wantQ := "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE height >= 0 ORDER BY height ASC LIMIT 10" + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height " + + "FROM main_block WHERE height >= 0 ORDER BY height ASC LIMIT 10" if q != wantQ { t.Errorf("query returned wrong: get: \n%s\nwant: \n%s", q, wantQ) } @@ -87,7 +88,7 @@ func TestBlockQuery_GetLastBlock(t *testing.T) { q := mockBlockQuery.GetLastBlock() wantQ := "SELECT MAX(height), id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block" + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block" if q != wantQ { t.Errorf("query returned wrong: get: \n%swant: \n%s", q, wantQ) } @@ -99,7 +100,7 @@ func TestBlockQuery_GetGenesisBlock(t *testing.T) { q := mockBlockQuery.GetGenesisBlock() wantQ := "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE height = 0" + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE height = 0" if q != wantQ { t.Errorf("query returned wrong: get: \n%swant: \n%s", q, wantQ) } @@ -112,14 +113,14 @@ func TestBlockQuery_InsertBlock(t *testing.T) { wantQ := "INSERT INTO main_block (height, id, block_hash, previous_block_hash, timestamp, block_seed, " + "block_signature, cumulative_difficulty, payload_length, payload_hash, " + "blocksmith_public_key, total_amount, total_fee, total_coinbase, " + - "version) VALUES(? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + "version, merkle_root, merkle_tree, reference_block_height) VALUES(? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" wantArg := mockBlockQuery.ExtractModel(mockBlock) if q != wantQ { t.Errorf("query returned wrong: get: \n%swant: \n%s", q, wantQ) } if !reflect.DeepEqual(args, wantArg) { - t.Errorf("arguments returned wrong: get: %v\nwant: %v", args, wantArg) + t.Errorf("arguments returned wrong: get: \n%v\nwant: \n%v", args, wantArg) } }) } @@ -129,7 +130,8 @@ func TestBlockQuery_GetBlockByID(t *testing.T) { q := mockBlockQuery.GetBlockByID(1) wantQ := "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, " + - "total_amount, total_fee, total_coinbase, version FROM main_block WHERE id = 1" + "total_amount, total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height " + + "FROM main_block WHERE id = 1" if q != wantQ { t.Errorf("query returned wrong: get: %s\nwant: %s", q, wantQ) } @@ -141,7 +143,8 @@ func TestBlockQuery_GetBlockByHeight(t *testing.T) { q := mockBlockQuery.GetBlockByHeight(0) wantQ := "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, " + - "total_amount, total_fee, total_coinbase, version FROM main_block WHERE height = 0" + "total_amount, total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height " + + "FROM main_block WHERE height = 0" if q != wantQ { t.Errorf("query returned wrong: get: %s\nwant: %s", q, wantQ) } @@ -167,6 +170,9 @@ func TestBlockQuery_ExtractModel(t *testing.T) { mockBlock.TotalFee, mockBlock.TotalCoinBase, mockBlock.Version, + mockBlock.MerkleRoot, + mockBlock.MerkleTree, + mockBlock.ReferenceBlockHeight, } if !reflect.DeepEqual(res, want) { t.Errorf("arguments returned wrong: get: %v\nwant: %v", res, want) @@ -195,7 +201,10 @@ func TestBlockQuery_BuildModel(t *testing.T) { mockBlock.TotalAmount, mockBlock.TotalFee, mockBlock.TotalCoinBase, - mockBlock.Version)) + mockBlock.Version, + mockBlock.MerkleRoot, + mockBlock.MerkleTree, + mockBlock.ReferenceBlockHeight)) rows, _ := db.Query("foo") var tempBlock []*model.Block @@ -274,7 +283,7 @@ func TestBlockQuery_GetBlockFromHeight(t *testing.T) { }, want: "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, " + - "total_coinbase, version FROM main_block WHERE height >= 1 ORDER BY height LIMIT 1", + "total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE height >= 1 ORDER BY height LIMIT 1", }, } for _, tt := range tests { @@ -316,7 +325,8 @@ func TestBlockQuery_GetBlockFromTimestamp(t *testing.T) { }, want: "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, " + - "total_coinbase, version FROM main_block WHERE timestamp >= 15875392 ORDER BY timestamp LIMIT 1", + "total_coinbase, version, merkle_root, merkle_tree, reference_block_height " + + "FROM main_block WHERE timestamp >= 15875392 ORDER BY timestamp LIMIT 1", }, } for _, tt := range tests { @@ -357,8 +367,9 @@ func TestBlockQuery_SelectDataForSnapshot(t *testing.T) { toHeight: 10, }, want: "SELECT height,id,block_hash,previous_block_hash,timestamp,block_seed,block_signature," + - "cumulative_difficulty,payload_length,payload_hash,blocksmith_public_key,total_amount,total_fee,total_coinbase," + - "version FROM main_block WHERE height >= 0 AND height <= 10 AND height != 0", + "cumulative_difficulty,payload_length,payload_hash,blocksmith_public_key,total_amount," + + "total_fee,total_coinbase,version,merkle_root,merkle_tree,reference_block_height " + + "FROM main_block WHERE height >= 0 AND height <= 10 AND height != 0", }, } for _, tt := range tests { @@ -450,8 +461,9 @@ func TestBlockQuery_InsertBlocks(t *testing.T) { }, wantStr: "INSERT INTO main_block " + "(height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, " + + "merkle_root, merkle_tree, reference_block_height) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", wantArgs: NewBlockQuery(&chaintype.MainChain{}).ExtractModel(mockBlock), }, } @@ -464,11 +476,11 @@ func TestBlockQuery_InsertBlocks(t *testing.T) { } gotStr, gotArgs := bq.InsertBlocks(tt.args.blocks) if gotStr != tt.wantStr { - t.Errorf("InsertBlocks() gotStr = %v, want %v", gotStr, tt.wantStr) + t.Errorf("InsertBlocks() gotStr = \n%v want \n%v", gotStr, tt.wantStr) return } if !reflect.DeepEqual(gotArgs, tt.wantArgs) { - t.Errorf("InsertBlocks() gotArgs = %v, want %v", gotArgs, tt.wantArgs) + t.Errorf("InsertBlocks() gotArgs = \n%v, want \n%v", gotArgs, tt.wantArgs) } }) } diff --git a/common/util/block_test.go b/common/util/block_test.go index ed7359a82..6c5c2c656 100644 --- a/common/util/block_test.go +++ b/common/util/block_test.go @@ -179,6 +179,9 @@ func (*mockExecutorGetLastBlockSuccess) ExecuteSelectRow(qStr string, tx bool, a mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), ) mock.ExpectQuery("").WillReturnRows(mockRows) return db.QueryRow(""), nil @@ -308,6 +311,9 @@ func (*mockedQueryExecutorGetBlockByHeightSuccess) ExecuteSelectRow(qe string, _ mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qe), nil } diff --git a/common/util/merkleTree.go b/common/util/merkleTree.go index 0c943a1c7..1c23cd8ce 100644 --- a/common/util/merkleTree.go +++ b/common/util/merkleTree.go @@ -2,9 +2,11 @@ package util import ( "bytes" - "github.com/zoobc/zoobc-core/common/constant" "math" + "github.com/zoobc/zoobc-core/common/blocker" + "github.com/zoobc/zoobc-core/common/constant" + "golang.org/x/crypto/sha3" ) @@ -16,6 +18,9 @@ type MerkleRoot struct { // GenerateMerkleRoot generate the root of merkle and build the tree in MerkleRoot.HashTree // return only the root func (mr *MerkleRoot) GenerateMerkleRoot(items []*bytes.Buffer) (*bytes.Buffer, error) { + if len(items) == 0 { + return nil, blocker.NewBlocker(blocker.ValidationErr, "LeafOfMerkleRequired") + } treeLevelLength := math.Log2(float64(len(items))) if treeLevelLength != math.Floor(treeLevelLength) { // find `n` of lacking element and append until condition fulfilled diff --git a/core/service/blockCoreService.go b/core/service/blockCoreService.go index 5be763048..c88930253 100644 --- a/core/service/blockCoreService.go +++ b/core/service/blockCoreService.go @@ -12,8 +12,8 @@ import ( type ( BlockServiceInterface interface { - NewGenesisBlock(version uint32, previousBlockHash []byte, blockSeed, blockSmithPublicKey []byte, - previousBlockHeight uint32, timestamp int64, totalAmount int64, totalFee int64, totalCoinBase int64, + NewGenesisBlock(version uint32, previousBlockHash []byte, blockSeed, blockSmithPublicKey []byte, mRoot, mTree []byte, + previousBlockHeight, referenceBlockHeight uint32, timestamp int64, totalAmount int64, totalFee int64, totalCoinBase int64, transactions []*model.Transaction, blockReceipts []*model.PublishedReceipt, spinePublicKeys []*model.SpinePublicKey, payloadHash []byte, payloadLength uint32, cumulativeDifficulty *big.Int, genesisSignature []byte) (*model.Block, error) GenerateBlock( diff --git a/core/service/blockMainService.go b/core/service/blockMainService.go index ffa5de367..7d1833dbe 100644 --- a/core/service/blockMainService.go +++ b/core/service/blockMainService.go @@ -245,8 +245,8 @@ func (bs *BlockService) ChainWriteUnlock(actionType int) { // NewGenesisBlock create new block that is fixed in the value of cumulative difficulty, smith scale, and the block signature func (bs *BlockService) NewGenesisBlock( version uint32, - previousBlockHash, blockSeed, blockSmithPublicKey []byte, - previousBlockHeight uint32, + previousBlockHash, blockSeed, blockSmithPublicKey, merkleRoot, merkleTree []byte, + previousBlockHeight, referenceBlockHeight uint32, timestamp, totalAmount, totalFee, totalCoinBase int64, transactions []*model.Transaction, publishedReceipts []*model.PublishedReceipt, @@ -273,6 +273,9 @@ func (bs *BlockService) NewGenesisBlock( PayloadHash: payloadHash, CumulativeDifficulty: cumulativeDifficulty.String(), BlockSignature: genesisSignature, + ReferenceBlockHeight: referenceBlockHeight, + MerkleRoot: merkleRoot, + MerkleTree: merkleTree, } blockHash, err := commonUtils.GetBlockHash(block, bs.Chaintype) if err != nil { @@ -994,7 +997,7 @@ func (bs *BlockService) GetBlockByHeight(height uint32) (*model.Block, error) { block, err = commonUtils.GetBlockByHeight(height, bs.QueryExecutor, bs.BlockQuery) if err != nil { - return nil, blocker.NewBlocker(blocker.DBErr, err.Error()) + return nil, err } transactions, err = bs.TransactionCoreService.GetTransactionsByBlockID(block.ID) @@ -1234,6 +1237,10 @@ func (bs *BlockService) GenerateGenesisBlock(genesisEntries []constant.GenesisCo nil, bs.Chaintype.GetGenesisBlockSeed(), bs.Chaintype.GetGenesisNodePublicKey(), + // TODO: Generate merkle root genesis + nil, + nil, + 0, 0, bs.Chaintype.GetGenesisBlockTimestamp(), totalAmount, diff --git a/core/service/blockMainService_test.go b/core/service/blockMainService_test.go index 8dbae085f..310638b96 100644 --- a/core/service/blockMainService_test.go +++ b/core/service/blockMainService_test.go @@ -8,7 +8,6 @@ import ( "reflect" "regexp" "strings" - "sync" "testing" "github.com/DATA-DOG/go-sqlmock" @@ -424,15 +423,16 @@ func (*mockQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ...inter "account_address", "registration_height", "locked_balance", "registration_status", "latest", "height", }).AddRow(1, bcsNodePubKey1, bcsAddress1, 10, 100000000, uint32(model.NodeRegistrationState_NodeQueued), true, 100)) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version FROM main_block WHERE height = 0": + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, merkle_root, " + + "merkle_tree, reference_block_height FROM main_block WHERE height = 0": mock.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(sqlmock.NewRows([]string{ "ID", "BlockHash", "PreviousBlockHash", "Height", "Timestamp", "BlockSeed", "BlockSignature", "CumulativeDifficulty", "PayloadLength", "PayloadHash", "BlocksmithPublicKey", "TotalAmount", "TotalFee", "TotalCoinBase", "Version"}, ).AddRow(1, []byte{}, []byte{}, 1, 10000, []byte{}, []byte{}, "", 2, []byte{}, bcsNodePubKey1, 0, 0, 0, 1)) case fmt.Sprintf("SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, "+ - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version "+ - "FROM main_block WHERE height = %d", mockBlockData.GetHeight()+1): + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, "+ + "merkle_root, merkle_tree, reference_block_height FROM main_block WHERE height = %d", mockBlockData.GetHeight()+1): mock.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(sqlmock.NewRows([]string{ "ID", "BlockHash", "PreviousBlockHash", "Height", "Timestamp", "BlockSeed", "BlockSignature", "CumulativeDifficulty", "PayloadLength", "PayloadHash", "BlocksmithPublicKey", "TotalAmount", "TotalFee", "TotalCoinBase", @@ -448,8 +448,8 @@ func (*mockQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ...inter }, ).AddRow(-1, 100000, true, 0)) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version FROM main_block ORDER BY " + - "height DESC LIMIT 1": + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, merkle_root, " + + "merkle_tree, reference_block_height FROM main_block ORDER BY height DESC LIMIT 1": mock.ExpectQuery(regexp.QuoteMeta(qe)). WillReturnRows(sqlmock.NewRows( query.NewBlockQuery(&chaintype.MainChain{}).Fields, @@ -469,6 +469,9 @@ func (*mockQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ...inter mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, fee, timestamp, " + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version, " + @@ -764,20 +767,52 @@ func TestBlockService_NewBlock(t *testing.T) { func TestBlockService_NewGenesisBlock(t *testing.T) { type fields struct { - Chaintype chaintype.ChainType - QueryExecutor query.ExecutorInterface - BlockQuery query.BlockQueryInterface - MempoolQuery query.MempoolQueryInterface - TransactionQuery query.TransactionQueryInterface - Signature crypto.SignatureInterface - ActionTypeSwitcher transaction.TypeActionSwitcher + Chaintype chaintype.ChainType + QueryExecutor query.ExecutorInterface + BlockQuery query.BlockQueryInterface + MempoolQuery query.MempoolQueryInterface + TransactionQuery query.TransactionQueryInterface + PublishedReceiptQuery query.PublishedReceiptQueryInterface + SkippedBlocksmithQuery query.SkippedBlocksmithQueryInterface + Signature crypto.SignatureInterface + MempoolService MempoolServiceInterface + ReceiptService ReceiptServiceInterface + NodeRegistrationService NodeRegistrationServiceInterface + NodeAddressInfoService NodeAddressInfoServiceInterface + BlocksmithService BlocksmithServiceInterface + FeeScaleService fee.FeeScaleServiceInterface + ActionTypeSwitcher transaction.TypeActionSwitcher + AccountBalanceQuery query.AccountBalanceQueryInterface + ParticipationScoreQuery query.ParticipationScoreQueryInterface + NodeRegistrationQuery query.NodeRegistrationQueryInterface + AccountLedgerQuery query.AccountLedgerQueryInterface + FeeVoteRevealVoteQuery query.FeeVoteRevealVoteQueryInterface + BlocksmithStrategy strategy.BlocksmithStrategyInterface + BlockIncompleteQueueService BlockIncompleteQueueServiceInterface + BlockPoolService BlockPoolServiceInterface + Observer *observer.Observer + Logger *log.Logger + TransactionUtil transaction.UtilInterface + ReceiptUtil coreUtil.ReceiptUtilInterface + PublishedReceiptUtil coreUtil.PublishedReceiptUtilInterface + TransactionCoreService TransactionCoreServiceInterface + CoinbaseService CoinbaseServiceInterface + ParticipationScoreService ParticipationScoreServiceInterface + PublishedReceiptService PublishedReceiptServiceInterface + PruneQuery []query.PruneQuery + BlockStateStorage storage.CacheStorageInterface + BlockchainStatusService BlockchainStatusServiceInterface + ScrambleNodeService ScrambleNodeServiceInterface } type args struct { version uint32 previousBlockHash []byte blockSeed []byte blockSmithPublicKey []byte + merkleRoot []byte + merkleTree []byte previousBlockHeight uint32 + referenceBlockHeight uint32 timestamp int64 totalAmount int64 totalFee int64 @@ -791,10 +826,11 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { genesisSignature []byte } tests := []struct { - name string - fields fields - args args - want *model.Block + name string + fields fields + args args + want *model.Block + wantErr bool }{ { name: "wantSuccess", @@ -807,7 +843,10 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { previousBlockHash: []byte{}, blockSeed: []byte{}, blockSmithPublicKey: bcsNodePubKey1, + merkleRoot: []byte{}, + merkleTree: []byte{}, previousBlockHeight: 0, + referenceBlockHeight: 0, timestamp: 15875392, totalAmount: 0, totalFee: 0, @@ -825,6 +864,8 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { PreviousBlockHash: []byte{}, BlockSeed: []byte{}, BlocksmithPublicKey: bcsNodePubKey1, + MerkleRoot: []byte{}, + MerkleTree: []byte{}, Timestamp: 15875392, TotalAmount: 0, TotalFee: 0, @@ -844,20 +885,52 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { bs := &BlockService{ - Chaintype: tt.fields.Chaintype, - QueryExecutor: tt.fields.QueryExecutor, - BlockQuery: tt.fields.BlockQuery, - MempoolQuery: tt.fields.MempoolQuery, - TransactionQuery: tt.fields.TransactionQuery, - Signature: tt.fields.Signature, - ActionTypeSwitcher: tt.fields.ActionTypeSwitcher, + Chaintype: tt.fields.Chaintype, + QueryExecutor: tt.fields.QueryExecutor, + BlockQuery: tt.fields.BlockQuery, + MempoolQuery: tt.fields.MempoolQuery, + TransactionQuery: tt.fields.TransactionQuery, + PublishedReceiptQuery: tt.fields.PublishedReceiptQuery, + SkippedBlocksmithQuery: tt.fields.SkippedBlocksmithQuery, + Signature: tt.fields.Signature, + MempoolService: tt.fields.MempoolService, + ReceiptService: tt.fields.ReceiptService, + NodeRegistrationService: tt.fields.NodeRegistrationService, + NodeAddressInfoService: tt.fields.NodeAddressInfoService, + BlocksmithService: tt.fields.BlocksmithService, + FeeScaleService: tt.fields.FeeScaleService, + ActionTypeSwitcher: tt.fields.ActionTypeSwitcher, + AccountBalanceQuery: tt.fields.AccountBalanceQuery, + ParticipationScoreQuery: tt.fields.ParticipationScoreQuery, + NodeRegistrationQuery: tt.fields.NodeRegistrationQuery, + AccountLedgerQuery: tt.fields.AccountLedgerQuery, + FeeVoteRevealVoteQuery: tt.fields.FeeVoteRevealVoteQuery, + BlocksmithStrategy: tt.fields.BlocksmithStrategy, + BlockIncompleteQueueService: tt.fields.BlockIncompleteQueueService, + BlockPoolService: tt.fields.BlockPoolService, + Observer: tt.fields.Observer, + Logger: tt.fields.Logger, + TransactionUtil: tt.fields.TransactionUtil, + ReceiptUtil: tt.fields.ReceiptUtil, + PublishedReceiptUtil: tt.fields.PublishedReceiptUtil, + TransactionCoreService: tt.fields.TransactionCoreService, + CoinbaseService: tt.fields.CoinbaseService, + ParticipationScoreService: tt.fields.ParticipationScoreService, + PublishedReceiptService: tt.fields.PublishedReceiptService, + PruneQuery: tt.fields.PruneQuery, + BlockStateStorage: tt.fields.BlockStateStorage, + BlockchainStatusService: tt.fields.BlockchainStatusService, + ScrambleNodeService: tt.fields.ScrambleNodeService, } - if got, _ := bs.NewGenesisBlock( + got, err := bs.NewGenesisBlock( tt.args.version, tt.args.previousBlockHash, tt.args.blockSeed, tt.args.blockSmithPublicKey, + tt.args.merkleRoot, + tt.args.merkleTree, tt.args.previousBlockHeight, + tt.args.referenceBlockHeight, tt.args.timestamp, tt.args.totalAmount, tt.args.totalFee, @@ -869,8 +942,13 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { tt.args.payloadLength, tt.args.cumulativeDifficulty, tt.args.genesisSignature, - ); !reflect.DeepEqual(got, tt.want) { - t.Errorf("BlockService.NewGenesisBlock() = %v, want %v", got, tt.want) + ) + if (err != nil) != tt.wantErr { + t.Errorf("BlockService.NewGenesisBlock() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("BlockService.NewGenesisBlock() = \n%v, want \n%v", got, tt.want) } }) } @@ -1392,6 +1470,9 @@ func (*mockQueryExecutorGetGenesisBlockSuccess) ExecuteSelectRow(qStr string, tx mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -1494,6 +1575,9 @@ func (*mockQueryExecutorGetBlocksSuccess) ExecuteSelect(qStr string, tx bool, ar mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.Query(qStr) } @@ -2128,6 +2212,9 @@ func (*mockQueryExecutorCheckGenesisTrue) ExecuteSelect(qStr string, tx bool, ar mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.Query("") } @@ -2153,6 +2240,9 @@ func (*mockQueryExecutorCheckGenesisTrue) ExecuteSelectRow(qStr string, tx bool, mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -2245,6 +2335,9 @@ func (*mockQueryExecutorGetBlockByHeightSuccess) ExecuteSelectRow(qStr string, _ mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -2255,7 +2348,7 @@ func (*mockQueryExecutorGetBlockByHeightSuccess) ExecuteSelect(qStr string, tx b switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE height = 0": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE height = 0": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(sqlmock.NewRows( query.NewBlockQuery(&chaintype.MainChain{}).Fields).AddRow( mockBlockData.GetHeight(), @@ -2273,6 +2366,9 @@ func (*mockQueryExecutorGetBlockByHeightSuccess) ExecuteSelect(qStr string, tx b mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, " + "fee, timestamp, transaction_hash, transaction_body_length, transaction_body_bytes, " + @@ -2425,7 +2521,7 @@ func (*mockQueryExecutorGetBlockByIDSuccess) ExecuteSelect(qStr string, tx bool, switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, " + - "version FROM main_block WHERE id = 1": + "version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE id = 1": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(sqlmock.NewRows( query.NewBlockQuery(&chaintype.MainChain{}).Fields).AddRow( mockBlockData.GetHeight(), @@ -2443,6 +2539,9 @@ func (*mockQueryExecutorGetBlockByIDSuccess) ExecuteSelect(qStr string, tx bool, mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, " + "fee, timestamp, transaction_hash, transaction_body_length, transaction_body_bytes, " + @@ -2477,6 +2576,9 @@ func (*mockQueryExecutorGetBlockByIDSuccess) ExecuteSelectRow(qStr string, tx bo mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -2637,6 +2739,9 @@ func (*mockQueryExecutorGetBlocksFromHeightSuccess) ExecuteSelect(qStr string, t mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), ).AddRow( mockBlockData.GetHeight(), mockBlockData.GetID(), @@ -2653,6 +2758,9 @@ func (*mockQueryExecutorGetBlocksFromHeightSuccess) ExecuteSelect(qStr string, t mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), ), ) return db.Query(qStr) @@ -3525,6 +3633,9 @@ func (*mockQueryExecutorValidateBlockSuccess) ExecuteSelect(qStr string, tx bool mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) rows, _ := db.Query(qStr) return rows, nil @@ -3923,7 +4034,7 @@ func (*mockExecutorBlockPopFailCommonNotFound) ExecuteSelect( switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE id = 0": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE id = 0": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields)) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, fee, " + @@ -3945,7 +4056,7 @@ func (*mockExecutorBlockPopFailCommonNotFound) ExecuteSelectRow( switch qStr { case "SELECT MAX(height), id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields[:len(blockQ.Fields)-1]).AddRow( mockGoodBlock.GetHeight(), @@ -3962,11 +4073,16 @@ func (*mockExecutorBlockPopFailCommonNotFound) ExecuteSelectRow( mockGoodBlock.GetTotalAmount(), mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), + mockGoodBlock.GetTotalCoinBase(), + mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ), ) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE id = 1": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE id = 1": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields)) default: @@ -3983,7 +4099,7 @@ func (*mockExecutorBlockPopGetLastBlockFail) ExecuteSelectRow(qStr string, tx bo switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE id = 0": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block WHERE id = 0": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields)) default: @@ -4003,6 +4119,10 @@ func (*mockExecutorBlockPopGetLastBlockFail) ExecuteSelectRow(qStr string, tx bo mockGoodBlock.GetTotalAmount(), mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), + mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ), ) } @@ -4071,7 +4191,8 @@ func (*mockExecutorBlockPopSuccess) ExecuteSelect(qStr string, tx bool, args ... switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE height = 999": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height " + + "FROM main_block WHERE height = 999": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields).AddRow( mockGoodCommonBlock.GetHeight(), @@ -4089,11 +4210,15 @@ func (*mockExecutorBlockPopSuccess) ExecuteSelect(qStr string, tx bool, args ... mockGoodCommonBlock.GetTotalFee(), mockGoodCommonBlock.GetTotalCoinBase(), mockGoodCommonBlock.GetVersion(), + mockGoodCommonBlock.GetMerkleRoot(), + mockGoodCommonBlock.GetMerkleTree(), + mockGoodCommonBlock.GetReferenceBlockHeight(), ), ) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block WHERE id = 0": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height " + + "FROM main_block WHERE id = 0": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields).AddRow( mockGoodCommonBlock.GetHeight(), @@ -4111,6 +4236,9 @@ func (*mockExecutorBlockPopSuccess) ExecuteSelect(qStr string, tx bool, args ... mockGoodCommonBlock.GetTotalFee(), mockGoodCommonBlock.GetTotalCoinBase(), mockGoodCommonBlock.GetVersion(), + mockGoodCommonBlock.GetMerkleRoot(), + mockGoodCommonBlock.GetMerkleTree(), + mockGoodCommonBlock.GetReferenceBlockHeight(), ), ) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, fee, " + @@ -4149,6 +4277,9 @@ func (*mockExecutorBlockPopSuccess) ExecuteSelectRow(qStr string, tx bool, args mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ), ) return db.QueryRow(qStr), nil @@ -4234,6 +4365,9 @@ func (*mockedExecutorPopOffToBlockSuccessPopping) ExecuteSelectRow(qStr string, mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ) default: mockedRows.AddRow( @@ -4252,6 +4386,9 @@ func (*mockedExecutorPopOffToBlockSuccessPopping) ExecuteSelectRow(qStr string, mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ) } @@ -5124,7 +5261,6 @@ func TestBlockService_ValidatePayloadHash(t *testing.T) { PublishedReceipts: mockPublishedReceipt, } type fields struct { - RWMutex sync.RWMutex Chaintype chaintype.ChainType QueryExecutor query.ExecutorInterface BlockQuery query.BlockQueryInterface @@ -5195,7 +5331,6 @@ func TestBlockService_ValidatePayloadHash(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { bs := &BlockService{ - RWMutex: tt.fields.RWMutex, Chaintype: tt.fields.Chaintype, QueryExecutor: tt.fields.QueryExecutor, BlockQuery: tt.fields.BlockQuery, diff --git a/core/service/blockSpineService.go b/core/service/blockSpineService.go index 4e619ba3e..79f94f70e 100644 --- a/core/service/blockSpineService.go +++ b/core/service/blockSpineService.go @@ -47,6 +47,7 @@ type ( SnapshotMainBlockService SnapshotBlockServiceInterface BlockStateStorage storage.CacheStorageInterface BlockchainStatusService BlockchainStatusServiceInterface + MainBlockService BlockServiceInterface } ) @@ -64,6 +65,7 @@ func NewBlockSpineService( blockStateStorage storage.CacheStorageInterface, blockchainStatusService BlockchainStatusServiceInterface, spinePublicKeyService BlockSpinePublicKeyServiceInterface, + mainBlockService BlockServiceInterface, ) *BlockSpineService { return &BlockSpineService{ Chaintype: ct, @@ -84,6 +86,7 @@ func NewBlockSpineService( SnapshotMainBlockService: snapshotMainblockService, BlockStateStorage: blockStateStorage, BlockchainStatusService: blockchainStatusService, + MainBlockService: mainBlockService, } } @@ -91,8 +94,8 @@ func NewBlockSpineService( func (bs *BlockSpineService) NewSpineBlock( version uint32, previousBlockHash, - blockSeed, blockSmithPublicKey []byte, - previousBlockHeight uint32, + blockSeed, blockSmithPublicKey, merkleRoot, merkleTree []byte, + previousBlockHeight, referenceBlockHeight uint32, timestamp int64, secretPhrase string, spinePublicKeys []*model.SpinePublicKey, @@ -103,15 +106,18 @@ func (bs *BlockSpineService) NewSpineBlock( err error ) block := &model.Block{ - Version: version, - PreviousBlockHash: previousBlockHash, - BlockSeed: blockSeed, - BlocksmithPublicKey: blockSmithPublicKey, - Height: previousBlockHeight, - Timestamp: timestamp, - PayloadLength: payloadLength, - SpinePublicKeys: spinePublicKeys, - SpineBlockManifests: spineBlockManifests, + Version: version, + PreviousBlockHash: previousBlockHash, + BlockSeed: blockSeed, + BlocksmithPublicKey: blockSmithPublicKey, + Height: previousBlockHeight, + Timestamp: timestamp, + PayloadLength: payloadLength, + SpinePublicKeys: spinePublicKeys, + SpineBlockManifests: spineBlockManifests, + ReferenceBlockHeight: referenceBlockHeight, + MerkleRoot: merkleRoot, + MerkleTree: merkleTree, } // compute block's payload hash and length and add it to block struct @@ -158,8 +164,8 @@ func (bs *BlockSpineService) ChainWriteUnlock(actionType int) { // NewGenesisBlock create new block that is fixed in the value of cumulative difficulty, smith scale, and the block signature func (bs *BlockSpineService) NewGenesisBlock( version uint32, - previousBlockHash, blockSeed, blockSmithPublicKey []byte, - previousBlockHeight uint32, + previousBlockHash, blockSeed, blockSmithPublicKey, merkleRoot, merkleTree []byte, + previousBlockHeight, referenceBlockHeight uint32, timestamp, totalAmount, totalFee, totalCoinBase int64, transactions []*model.Transaction, publishedReceipts []*model.PublishedReceipt, @@ -169,25 +175,31 @@ func (bs *BlockSpineService) NewGenesisBlock( cumulativeDifficulty *big.Int, genesisSignature []byte, ) (*model.Block, error) { - block := &model.Block{ - Version: version, - PreviousBlockHash: previousBlockHash, - BlockSeed: blockSeed, - BlocksmithPublicKey: blockSmithPublicKey, - Height: previousBlockHeight, - Timestamp: timestamp, - TotalAmount: totalAmount, - TotalFee: totalFee, - TotalCoinBase: totalCoinBase, - Transactions: transactions, - SpinePublicKeys: spinePublicKeys, - PublishedReceipts: publishedReceipts, - PayloadLength: payloadLength, - PayloadHash: payloadHash, - CumulativeDifficulty: cumulativeDifficulty.String(), - BlockSignature: genesisSignature, - } - blockHash, err := commonUtils.GetBlockHash(block, bs.Chaintype) + var ( + block = &model.Block{ + Version: version, + PreviousBlockHash: previousBlockHash, + BlockSeed: blockSeed, + BlocksmithPublicKey: blockSmithPublicKey, + Height: previousBlockHeight, + Timestamp: timestamp, + TotalAmount: totalAmount, + TotalFee: totalFee, + TotalCoinBase: totalCoinBase, + Transactions: transactions, + SpinePublicKeys: spinePublicKeys, + PublishedReceipts: publishedReceipts, + PayloadLength: payloadLength, + PayloadHash: payloadHash, + CumulativeDifficulty: cumulativeDifficulty.String(), + BlockSignature: genesisSignature, + ReferenceBlockHeight: referenceBlockHeight, + MerkleRoot: merkleRoot, + MerkleTree: merkleTree, + } + + blockHash, err = commonUtils.GetBlockHash(block, bs.Chaintype) + ) if err != nil { return nil, err } @@ -588,6 +600,7 @@ func (bs *BlockSpineService) GenerateBlock( if fromTimestamp == bs.GetChainType().GetGenesisBlockTimestamp() { fromTimestamp++ } + // TODO: spine public key should in the range of included main block spinePublicKeys, err = bs.SpinePublicKeyService.BuildSpinePublicKeysFromNodeRegistry(fromTimestamp, timestamp, newBlockHeight) if err != nil { return nil, err @@ -616,12 +629,41 @@ func (bs *BlockSpineService) GenerateBlock( if err != nil { return nil, err } + // select main block to be include in spine block + lastMainBlock, err := bs.MainBlockService.GetLastBlock() + if err != nil { + return nil, err + } + newReferenceBlock := lastMainBlock.Height - constant.SpineReferenceBlockHeightOffset + limit := newReferenceBlock - previousBlock.ReferenceBlockHeight + 1 + inlcludedBlocks, err := bs.MainBlockService.GetBlocksFromHeight(previousBlock.ReferenceBlockHeight+1, limit, false) + if err != nil { + return nil, err + } + if len(inlcludedBlocks) == 0 { + return nil, blocker.NewBlocker(blocker.ValidationErr, "NoNewMainBlocks") + } + var ( + merkleRoot commonUtils.MerkleRoot + hashedMainBlock []*bytes.Buffer + ) + for i := 0; i < len(inlcludedBlocks); i++ { + hashedMainBlock = append(hashedMainBlock, bytes.NewBuffer(inlcludedBlocks[i].BlockHash)) + } + _, err = merkleRoot.GenerateMerkleRoot(hashedMainBlock) + if err != nil { + return nil, err + } + mRoot, mTree := merkleRoot.ToBytes() block, err := bs.NewSpineBlock( 1, previousBlockHash, blockSeed, blockSmithPublicKey, + mRoot, + mTree, newBlockHeight, + newReferenceBlock, timestamp, secretPhrase, spinePublicKeys, @@ -661,11 +703,25 @@ func (bs *BlockSpineService) GenerateGenesisBlock(genesisEntries []constant.Gene } payloadHash := digest.Sum([]byte{}) + mainGenesisBlock, err := bs.MainBlockService.GetGenesisBlock() + if err != nil { + return nil, err + } + var merkleRoot commonUtils.MerkleRoot + _, err = merkleRoot.GenerateMerkleRoot([]*bytes.Buffer{bytes.NewBuffer(mainGenesisBlock.BlockHash)}) + if err != nil { + return nil, err + } + mRoot, mTree := merkleRoot.ToBytes() + block, err := bs.NewGenesisBlock( 1, nil, bs.Chaintype.GetGenesisBlockSeed(), bs.Chaintype.GetGenesisNodePublicKey(), + mRoot, + mTree, + 0, 0, bs.Chaintype.GetGenesisBlockTimestamp(), totalAmount, @@ -734,6 +790,11 @@ func (bs *BlockSpineService) ReceiveBlock( "last block hash does not exist", ) } + // check existing last main block + err = bs.validateIncludedMainBlock(lastBlock, block) + if err != nil { + return nil, err + } // check equality last block hash with previous block hash from received block if !bytes.Equal(lastBlock.BlockHash, block.PreviousBlockHash) { // check if incoming block is of higher quality @@ -821,6 +882,22 @@ func (bs *BlockSpineService) ReceiveBlock( return nil, nil } +// validateIncludedMainBlock to validate included main block in spine block +func (bs *BlockSpineService) validateIncludedMainBlock(lastBlock, incomingBlock *model.Block) error { + if incomingBlock.GetReferenceBlockHeight() == 0 { + return blocker.NewBlocker(blocker.ValidationErr, "NoIncludedMainBlock") + } + if (incomingBlock.ReferenceBlockHeight - lastBlock.ReferenceBlockHeight) == 0 { + return blocker.NewBlocker(blocker.ValidationErr, "InValidReferenceBlockHeight") + } + var _, err = bs.MainBlockService.GetBlockByHeight(incomingBlock.ReferenceBlockHeight) + if err != nil { + return err + } + // TODO: check hashes of reference main block + return nil +} + func (bs *BlockSpineService) PopOffToBlock(commonBlock *model.Block) ([]*model.Block, error) { var ( err error diff --git a/core/service/blockSpineService_test.go b/core/service/blockSpineService_test.go index aa4931761..c07fa1221 100644 --- a/core/service/blockSpineService_test.go +++ b/core/service/blockSpineService_test.go @@ -8,7 +8,6 @@ import ( "reflect" "regexp" "strings" - "sync" "testing" "github.com/DATA-DOG/go-sqlmock" @@ -299,8 +298,8 @@ func (*mockSpineQueryExecutorSuccess) ExecuteSelectRow(qStr string, tx bool, arg "ID", "BlockHeight", "Tree", "Timestamp", })) case "SELECT MAX(height), id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version " + - "FROM spine_block": + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, " + + "merkle_root, merkle_tree, reference_block_height FROM spine_block": mockSpineRows := mockSpine.NewRows(query.NewBlockQuery(&chaintype.SpineChain{}).Fields) mockSpineRows.AddRow( mockSpineBlockData.GetHeight(), @@ -318,6 +317,9 @@ func (*mockSpineQueryExecutorSuccess) ExecuteSelectRow(qStr string, tx bool, arg mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), ) mockSpine.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(mockSpineRows) default: @@ -374,12 +376,11 @@ func (*mockSpineQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ... "account_address", "registration_height", "locked_balance", "registration_status", "latest", "height", }).AddRow(1, bcsNodePubKey1, bcsAddress1, 10, 100000000, uint32(model.NodeRegistrationState_NodeQueued), true, 100)) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version FROM spine_block WHERE height = 0": - mockSpine.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(sqlmock.NewRows([]string{ - "Height", "ID", "BlockHash", "PreviousBlockHash", "Timestamp", "BlockSeed", "BlockSignature", "CumulativeDifficulty", - "PayloadLength", "PayloadHash", "BlocksmithPublicKey", "TotalAmount", "TotalFee", "TotalCoinBase", - "Version"}, - ).AddRow(1, 1, []byte{}, []byte{}, 10000, []byte{}, []byte{}, "", 2, []byte{}, bcsNodePubKey1, 0, 0, 0, 1)) + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, merkle_root, " + + "merkle_tree, reference_block_height FROM spine_block WHERE height = 0": + mockSpine.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(sqlmock.NewRows( + query.NewBlockQuery(&chaintype.SpineChain{}).Fields, + ).AddRow(1, 1, []byte{}, []byte{}, 10000, []byte{}, []byte{}, "", 2, []byte{}, bcsNodePubKey1, 0, 0, 0, 1, []byte{}, []byte{}, 0)) case "SELECT A.node_id, A.score, A.latest, A.height FROM participation_score as A INNER JOIN node_registry as B " + "ON A.node_id = B.id WHERE B.node_public_key=? AND B.latest=1 AND B.registration_status=0 AND A.latest=1": mockSpine.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(sqlmock.NewRows([]string{ @@ -390,7 +391,8 @@ func (*mockSpineQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ... }, ).AddRow(-1, 100000, true, 0)) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + - "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version FROM spine_block ORDER BY " + + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, version, merkle_root, " + + "merkle_tree, reference_block_height FROM spine_block ORDER BY " + "height DESC LIMIT 1": mockSpine.ExpectQuery(regexp.QuoteMeta(qe)). WillReturnRows(sqlmock.NewRows( @@ -411,6 +413,9 @@ func (*mockSpineQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ... mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) case "SELECT node_public_key, node_id, public_key_action, main_block_height, latest, height FROM spine_public_key WHERE height = 1": mockSpine.ExpectQuery(regexp.QuoteMeta(qe)). @@ -543,24 +548,34 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { mockSpineBlock.BlockHash = mockSpineBlockHash type fields struct { - Chaintype chaintype.ChainType - QueryExecutor query.ExecutorInterface - BlockQuery query.BlockQueryInterface - MempoolQuery query.MempoolQueryInterface - TransactionQuery query.TransactionQueryInterface - Signature crypto.SignatureInterface - ActionTypeSwitcher transaction.TypeActionSwitcher + Chaintype chaintype.ChainType + QueryExecutor query.ExecutorInterface + BlockQuery query.BlockQueryInterface + Signature crypto.SignatureInterface + BlocksmithStrategy strategy.BlocksmithStrategyInterface + Observer *observer.Observer + Logger *log.Logger + SpinePublicKeyService BlockSpinePublicKeyServiceInterface + SpineBlockManifestService SpineBlockManifestServiceInterface + BlocksmithService BlocksmithServiceInterface + SnapshotMainBlockService SnapshotBlockServiceInterface + BlockStateStorage storage.CacheStorageInterface + BlockchainStatusService BlockchainStatusServiceInterface + MainBlockService BlockServiceInterface } type args struct { - version uint32 - previousBlockHash []byte - blockSeed []byte - blockSmithPublicKey []byte - previousBlockHeight uint32 - timestamp int64 - spinePublicKeys []*model.SpinePublicKey - secretPhrase string - spineBlockManifests []*model.SpineBlockManifest + version uint32 + previousBlockHash []byte + blockSeed []byte + blockSmithPublicKey []byte + merkleRoot []byte + merkleTree []byte + previousBlockHeight uint32 + referenceBlockHeight uint32 + timestamp int64 + secretPhrase string + spinePublicKeys []*model.SpinePublicKey + spineBlockManifests []*model.SpineBlockManifest } tests := []struct { name string @@ -591,28 +606,41 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { bs := &BlockSpineService{ - Chaintype: tt.fields.Chaintype, - QueryExecutor: tt.fields.QueryExecutor, - BlockQuery: tt.fields.BlockQuery, - Signature: tt.fields.Signature, + Chaintype: tt.fields.Chaintype, + QueryExecutor: tt.fields.QueryExecutor, + BlockQuery: tt.fields.BlockQuery, + Signature: tt.fields.Signature, + BlocksmithStrategy: tt.fields.BlocksmithStrategy, + Observer: tt.fields.Observer, + Logger: tt.fields.Logger, + SpinePublicKeyService: tt.fields.SpinePublicKeyService, + SpineBlockManifestService: tt.fields.SpineBlockManifestService, + BlocksmithService: tt.fields.BlocksmithService, + SnapshotMainBlockService: tt.fields.SnapshotMainBlockService, + BlockStateStorage: tt.fields.BlockStateStorage, + BlockchainStatusService: tt.fields.BlockchainStatusService, + MainBlockService: tt.fields.MainBlockService, } got, err := bs.NewSpineBlock( tt.args.version, tt.args.previousBlockHash, tt.args.blockSeed, tt.args.blockSmithPublicKey, + tt.args.merkleRoot, + tt.args.merkleTree, tt.args.previousBlockHeight, + tt.args.referenceBlockHeight, tt.args.timestamp, tt.args.secretPhrase, tt.args.spinePublicKeys, tt.args.spineBlockManifests, ) if (err != nil) != tt.wantErr { - t.Errorf("BlockSpineService.NewBlock() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("BlockSpineService.NewSpineBlock() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("BlockSpineService.NewBlock() = %v, want %v", got, tt.want) + t.Errorf("BlockSpineService.NewSpineBlock() = %v, want %v", got, tt.want) } }) } @@ -620,20 +648,30 @@ func TestBlockSpineService_NewSpineBlock(t *testing.T) { func TestBlockSpineService_NewGenesisBlock(t *testing.T) { type fields struct { - Chaintype chaintype.ChainType - QueryExecutor query.ExecutorInterface - BlockQuery query.BlockQueryInterface - MempoolQuery query.MempoolQueryInterface - TransactionQuery query.TransactionQueryInterface - Signature crypto.SignatureInterface - ActionTypeSwitcher transaction.TypeActionSwitcher + Chaintype chaintype.ChainType + QueryExecutor query.ExecutorInterface + BlockQuery query.BlockQueryInterface + Signature crypto.SignatureInterface + BlocksmithStrategy strategy.BlocksmithStrategyInterface + Observer *observer.Observer + Logger *log.Logger + SpinePublicKeyService BlockSpinePublicKeyServiceInterface + SpineBlockManifestService SpineBlockManifestServiceInterface + BlocksmithService BlocksmithServiceInterface + SnapshotMainBlockService SnapshotBlockServiceInterface + BlockStateStorage storage.CacheStorageInterface + BlockchainStatusService BlockchainStatusServiceInterface + MainBlockService BlockServiceInterface } type args struct { version uint32 previousBlockHash []byte blockSeed []byte blockSmithPublicKey []byte + merkleRoot []byte + merkleTree []byte previousBlockHeight uint32 + referenceBlockHeight uint32 timestamp int64 totalAmount int64 totalFee int64 @@ -647,70 +685,41 @@ func TestBlockSpineService_NewGenesisBlock(t *testing.T) { genesisSignature []byte } tests := []struct { - name string - fields fields - args args - want *model.Block + name string + fields fields + args args + want *model.Block + wantErr bool }{ - { - name: "wantSuccess", - fields: fields{ - Chaintype: &chaintype.SpineChain{}, - Signature: &mockSpineSignature{}, - }, - args: args{ - version: 1, - previousBlockHash: []byte{}, - blockSeed: []byte{}, - blockSmithPublicKey: bcsNodePubKey1, - previousBlockHeight: 0, - timestamp: 15875392, - totalAmount: 0, - totalFee: 0, - totalCoinBase: 0, - transactions: []*model.Transaction{}, - publishedReceipts: []*model.PublishedReceipt{}, - spinePublicKeys: []*model.SpinePublicKey{}, - payloadHash: []byte{}, - payloadLength: 8, - cumulativeDifficulty: big.NewInt(1), - genesisSignature: []byte{}, - }, - want: &model.Block{ - Version: 1, - PreviousBlockHash: []byte{}, - BlockSeed: []byte{}, - BlocksmithPublicKey: bcsNodePubKey1, - Timestamp: 15875392, - TotalAmount: 0, - TotalFee: 0, - TotalCoinBase: 0, - Transactions: []*model.Transaction{}, - PublishedReceipts: []*model.PublishedReceipt{}, - SpinePublicKeys: []*model.SpinePublicKey{}, - PayloadHash: []byte{}, - PayloadLength: 8, - CumulativeDifficulty: "1", - BlockSignature: []byte{}, - BlockHash: []byte{222, 81, 44, 228, 147, 156, 145, 104, 1, 97, 62, 138, 253, 90, 55, 41, 29, 150, 230, 196, - 68, 216, 14, 244, 224, 161, 132, 157, 229, 68, 33, 147}, - }, - }, + // TODO: Add test cases. } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { bs := &BlockSpineService{ - Chaintype: tt.fields.Chaintype, - QueryExecutor: tt.fields.QueryExecutor, - BlockQuery: tt.fields.BlockQuery, - Signature: tt.fields.Signature, + Chaintype: tt.fields.Chaintype, + QueryExecutor: tt.fields.QueryExecutor, + BlockQuery: tt.fields.BlockQuery, + Signature: tt.fields.Signature, + BlocksmithStrategy: tt.fields.BlocksmithStrategy, + Observer: tt.fields.Observer, + Logger: tt.fields.Logger, + SpinePublicKeyService: tt.fields.SpinePublicKeyService, + SpineBlockManifestService: tt.fields.SpineBlockManifestService, + BlocksmithService: tt.fields.BlocksmithService, + SnapshotMainBlockService: tt.fields.SnapshotMainBlockService, + BlockStateStorage: tt.fields.BlockStateStorage, + BlockchainStatusService: tt.fields.BlockchainStatusService, + MainBlockService: tt.fields.MainBlockService, } - if got, _ := bs.NewGenesisBlock( + got, err := bs.NewGenesisBlock( tt.args.version, tt.args.previousBlockHash, tt.args.blockSeed, tt.args.blockSmithPublicKey, + tt.args.merkleRoot, + tt.args.merkleTree, tt.args.previousBlockHeight, + tt.args.referenceBlockHeight, tt.args.timestamp, tt.args.totalAmount, tt.args.totalFee, @@ -722,7 +731,12 @@ func TestBlockSpineService_NewGenesisBlock(t *testing.T) { tt.args.payloadLength, tt.args.cumulativeDifficulty, tt.args.genesisSignature, - ); !reflect.DeepEqual(got, tt.want) { + ) + if (err != nil) != tt.wantErr { + t.Errorf("BlockSpineService.NewGenesisBlock() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { t.Errorf("BlockSpineService.NewGenesisBlock() = %v, want %v", got, tt.want) } }) @@ -1097,6 +1111,9 @@ func (*mockSpineQueryExecutorGetGenesisBlockSuccess) ExecuteSelectRow(qStr strin mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -1196,6 +1213,9 @@ func (*mockSpineQueryExecutorGetBlocksSuccess) ExecuteSelect(qStr string, tx boo mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) return db.Query(qStr) } @@ -1399,6 +1419,28 @@ func (*mockSpineMempoolServiceSelectWrongTransactionBytes) SelectTransactionsFro }, nil } +type ( + mockSpineGenerateblockMainBlockServiceSuccess struct { + BlockServiceInterface + } +) + +var ( + mockGenerateBlockMainBlock = model.Block{ + Height: 1 + constant.SpineReferenceBlockHeightOffset, + } +) + +func (*mockSpineGenerateblockMainBlockServiceSuccess) GetLastBlock() (*model.Block, error) { + return &mockGenerateBlockMainBlock, nil +} + +func (*mockSpineGenerateblockMainBlockServiceSuccess) GetBlocksFromHeight(startHeight, limit uint32, withAttachedData bool) ([]*model.Block, error) { + return []*model.Block{ + &mockGenerateBlockMainBlock, + }, nil +} + func TestBlockSpineService_GenerateBlock(t *testing.T) { type fields struct { Chaintype chaintype.ChainType @@ -1414,6 +1456,7 @@ func TestBlockSpineService_GenerateBlock(t *testing.T) { ActionTypeSwitcher transaction.TypeActionSwitcher SpinePublicKeyService BlockSpinePublicKeyServiceInterface SpineBlockManifestService SpineBlockManifestServiceInterface + MainBlockService BlockServiceInterface } type args struct { previousBlock *model.Block @@ -1465,6 +1508,7 @@ func TestBlockSpineService_GenerateBlock(t *testing.T) { }, }, }, + MainBlockService: &mockSpineGenerateblockMainBlockServiceSuccess{}, }, args: args{ previousBlock: &model.Block{ @@ -1497,6 +1541,7 @@ func TestBlockSpineService_GenerateBlock(t *testing.T) { BlocksmithStrategy: tt.fields.BlocksmithStrategy, SpinePublicKeyService: tt.fields.SpinePublicKeyService, SpineBlockManifestService: tt.fields.SpineBlockManifestService, + MainBlockService: tt.fields.MainBlockService, } _, err := bs.GenerateBlock( tt.args.previousBlock, @@ -1546,6 +1591,16 @@ func (*mockSpineBlocksmithServiceAddGenesisSuccess) SortBlocksmiths(block *model } +type ( + mockAddGenesisBlockMainBlockServiceSuccess struct { + BlockServiceInterface + } +) + +func (*mockAddGenesisBlockMainBlockServiceSuccess) GetGenesisBlock() (*model.Block, error) { + return &model.Block{}, nil +} + func TestBlockSpineService_AddGenesis(t *testing.T) { type fields struct { Chaintype chaintype.ChainType @@ -1566,6 +1621,7 @@ func TestBlockSpineService_AddGenesis(t *testing.T) { SpineBlockManifestService SpineBlockManifestServiceInterface BlockStateStorage storage.CacheStorageInterface BlockchainStatusService BlockchainStatusServiceInterface + MainBlockService BlockServiceInterface } tests := []struct { name string @@ -1604,6 +1660,7 @@ func TestBlockSpineService_AddGenesis(t *testing.T) { }, BlockStateStorage: storage.NewBlockStateStorage(), BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockAddGenesisBlockMainBlockServiceSuccess{}, }, wantErr: false, }, @@ -1622,6 +1679,7 @@ func TestBlockSpineService_AddGenesis(t *testing.T) { SpineBlockManifestService: tt.fields.SpineBlockManifestService, BlockStateStorage: tt.fields.BlockStateStorage, BlockchainStatusService: tt.fields.BlockchainStatusService, + MainBlockService: tt.fields.MainBlockService, } if err := bs.AddGenesis(); (err != nil) != tt.wantErr { t.Errorf("BlockSpineService.AddGenesis() error = %v, wantErr %v", err, tt.wantErr) @@ -1681,6 +1739,9 @@ func (*mockSpineQueryExecutorCheckGenesisTrue) ExecuteSelect(qStr string, tx boo mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) return db.Query("") } @@ -1706,6 +1767,9 @@ func (*mockSpineQueryExecutorCheckGenesisTrue) ExecuteSelectRow(qStr string, tx mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -1794,6 +1858,9 @@ func (*mockSpineQueryExecutorGetBlockByHeightSuccess) ExecuteSelectRow(qStr stri mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -1944,7 +2011,7 @@ func (*mockSpineQueryExecutorGetBlockByIDSuccess) ExecuteSelect(qStr string, tx sqlmock.NewRows(query.NewSpinePublicKeyQuery().Fields)) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, " + - "version FROM spine_block WHERE id = 1": + "version, merkle_root, merkle_tree, reference_block_height FROM spine_block WHERE id = 1": mockSpine.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(sqlmock.NewRows( query.NewBlockQuery(&chaintype.SpineChain{}).Fields).AddRow( mockSpineBlockData.GetHeight(), @@ -1962,6 +2029,9 @@ func (*mockSpineQueryExecutorGetBlockByIDSuccess) ExecuteSelect(qStr string, tx mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, " + "fee, timestamp, transaction_hash, transaction_body_length, transaction_body_bytes, " + @@ -1996,6 +2066,9 @@ func (*mockSpineQueryExecutorGetBlockByIDSuccess) ExecuteSelectRow(qStr string, mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -2137,6 +2210,9 @@ func (*mockSpineQueryExecutorGetBlocksFromHeightSuccess) ExecuteSelect(qStr stri mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), ).AddRow( mockSpineBlockData.GetHeight(), mockSpineBlockData.GetID(), @@ -2153,6 +2229,9 @@ func (*mockSpineQueryExecutorGetBlocksFromHeightSuccess) ExecuteSelect(qStr stri mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), ), ) return db.Query(qStr) @@ -2256,6 +2335,16 @@ func (*mockSpineReceiveBlockBlockStateStorageSuccess) SetItem(lastChange, item i return nil } +type ( + mockReceiveBlockMainBlockServiceSuccess struct { + BlockServiceInterface + } +) + +func (*mockReceiveBlockMainBlockServiceSuccess) GetBlockByHeight(uint32) (*model.Block, error) { + return &model.Block{}, nil +} + func TestBlockSpineService_ReceiveBlock(t *testing.T) { mockSpineLastBlockData := model.Block{ @@ -2278,6 +2367,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpinePublicKeys: []*model.SpinePublicKey{ mockSpinePublicKey, }, + ReferenceBlockHeight: 10, } mockSpineGoodLastBlockHash, _ := util.GetBlockHash(&mockSpineLastBlockData, &chaintype.SpineChain{}) @@ -2293,6 +2383,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { PayloadLength: 44, PayloadHash: []byte{55, 140, 121, 255, 150, 51, 177, 63, 86, 185, 40, 206, 151, 168, 77, 67, 61, 43, 54, 73, 162, 230, 10, 202, 83, 1, 185, 208, 203, 232, 73, 215}, + ReferenceBlockHeight: 11, } mockSpineBlockData.BlockHash = mockSpineGoodLastBlockHash @@ -2318,6 +2409,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService SpineBlockManifestServiceInterface BlockStateStorage storage.CacheStorageInterface BlockchainStatusService BlockchainStatusServiceInterface + MainBlockService BlockServiceInterface } type args struct { senderPublicKey []byte @@ -2364,6 +2456,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: &mockSpineBlockManifestService{}, BlockStateStorage: storage.NewBlockStateStorage(), BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockReceiveBlockMainBlockServiceSuccess{}, }, wantErr: true, want: nil, @@ -2405,6 +2498,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: &mockSpineBlockManifestService{}, BlockStateStorage: storage.NewBlockStateStorage(), BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockReceiveBlockMainBlockServiceSuccess{}, }, wantErr: true, want: nil, @@ -2441,6 +2535,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: &mockSpineBlockManifestService{}, BlockStateStorage: storage.NewBlockStateStorage(), BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockReceiveBlockMainBlockServiceSuccess{}, }, wantErr: true, want: nil, @@ -2484,6 +2579,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: &mockSpineBlockManifestService{}, BlockStateStorage: storage.NewBlockStateStorage(), BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockReceiveBlockMainBlockServiceSuccess{}, }, wantErr: true, want: nil, @@ -2520,6 +2616,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: &mockSpineBlockManifestService{}, BlockStateStorage: storage.NewBlockStateStorage(), BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockReceiveBlockMainBlockServiceSuccess{}, }, wantErr: true, want: nil, @@ -2560,6 +2657,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: &mockSpineBlockManifestService{}, BlockStateStorage: &mockSpineReceiveBlockBlockStateStorageSuccess{}, BlockchainStatusService: &mockBlockchainStatusService{}, + MainBlockService: &mockReceiveBlockMainBlockServiceSuccess{}, }, wantErr: false, want: nil, @@ -2579,6 +2677,7 @@ func TestBlockSpineService_ReceiveBlock(t *testing.T) { SpineBlockManifestService: tt.fields.SpineBlockManifestService, BlockStateStorage: tt.fields.BlockStateStorage, BlockchainStatusService: tt.fields.BlockchainStatusService, + MainBlockService: tt.fields.MainBlockService, } got, err := bs.ReceiveBlock( tt.args.senderPublicKey, tt.args.lastBlock, tt.args.block, tt.args.nodeSecretPhrase, @@ -2618,6 +2717,16 @@ func (*mockSpineBlocksmithService) GetSortedBlocksmiths(block *model.Block) []*m }, } } + +type ( + mockGenerateGenesisBlockMainBlockServiceSuccess struct { + BlockServiceInterface + } +) + +func (*mockGenerateGenesisBlockMainBlockServiceSuccess) GetGenesisBlock() (*model.Block, error) { + return &model.Block{}, nil +} func TestBlockSpineService_GenerateGenesisBlock(t *testing.T) { type fields struct { Chaintype chaintype.ChainType @@ -2632,6 +2741,7 @@ func TestBlockSpineService_GenerateGenesisBlock(t *testing.T) { AccountBalanceQuery query.AccountBalanceQueryInterface ParticipationScoreQuery query.ParticipationScoreQueryInterface NodeRegistrationQuery query.NodeRegistrationQueryInterface + MainBlockService BlockServiceInterface Observer *observer.Observer Logger *log.Logger } @@ -2661,6 +2771,7 @@ func TestBlockSpineService_GenerateGenesisBlock(t *testing.T) { ParticipationScoreQuery: nil, NodeRegistrationQuery: nil, Observer: nil, + MainBlockService: &mockGenerateGenesisBlockMainBlockServiceSuccess{}, }, args: args{ genesisEntries: constant.GenesisConfig, @@ -2672,12 +2783,13 @@ func TestBlockSpineService_GenerateGenesisBlock(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { bs := &BlockSpineService{ - Chaintype: tt.fields.Chaintype, - QueryExecutor: tt.fields.QueryExecutor, - BlockQuery: tt.fields.BlockQuery, - Signature: tt.fields.Signature, - Observer: tt.fields.Observer, - Logger: tt.fields.Logger, + Chaintype: tt.fields.Chaintype, + QueryExecutor: tt.fields.QueryExecutor, + BlockQuery: tt.fields.BlockQuery, + Signature: tt.fields.Signature, + Observer: tt.fields.Observer, + Logger: tt.fields.Logger, + MainBlockService: tt.fields.MainBlockService, } got, err := bs.GenerateGenesisBlock(tt.args.genesisEntries) if (err != nil) != tt.wantErr { @@ -2717,6 +2829,9 @@ func (*mockSpineQueryExecutorValidateBlockSuccess) ExecuteSelect(qStr string, tx mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) rows, _ := db.Query(qStr) return rows, nil @@ -3095,12 +3210,12 @@ func (*mockSpineExecutorBlockPopFailCommonNotFound) ExecuteSelectRow( switch qStr { case "SELECT MAX(height), id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM spine_block": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM spine_block": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields)) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM spine_block WHERE id = 1": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM spine_block WHERE id = 1": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields)) default: @@ -3120,7 +3235,7 @@ func (*mockSpineExecutorBlockPopFailCommonNotFound) ExecuteSelect( switch qStr { case "SELECT MAX(height), id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM spine_block": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM spine_block": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields).AddRow( mockSpineGoodBlock.GetHeight(), @@ -3137,11 +3252,15 @@ func (*mockSpineExecutorBlockPopFailCommonNotFound) ExecuteSelect( mockSpineGoodBlock.GetTotalAmount(), mockSpineGoodBlock.GetTotalFee(), mockSpineGoodBlock.GetTotalCoinBase(), + mockSpineGoodBlock.GetVersion(), + mockSpineGoodBlock.GetMerkleRoot(), + mockSpineGoodBlock.GetMerkleTree(), + mockSpineGoodBlock.GetReferenceBlockHeight(), ), ) case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM spine_block WHERE id = 0": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM spine_block WHERE id = 0": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields)) case "SELECT id, block_id, block_height, sender_account_address, recipient_account_address, transaction_type, fee, " + @@ -3228,7 +3347,7 @@ func (*mockSpineExecutorBlockPopSuccess) ExecuteSelect(qStr string, tx bool, arg switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM spine_block WHERE id = 0": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM spine_block WHERE id = 0": mockSpine.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows( sqlmock.NewRows(blockQ.Fields).AddRow( mockSpineGoodCommonBlock.GetHeight(), @@ -3246,6 +3365,9 @@ func (*mockSpineExecutorBlockPopSuccess) ExecuteSelect(qStr string, tx bool, arg mockSpineGoodCommonBlock.GetTotalFee(), mockSpineGoodCommonBlock.GetTotalCoinBase(), mockSpineGoodCommonBlock.GetVersion(), + mockSpineGoodCommonBlock.GetMerkleRoot(), + mockSpineGoodCommonBlock.GetMerkleTree(), + mockSpineGoodCommonBlock.GetReferenceBlockHeight(), ), ) case "SELECT node_public_key, node_id, public_key_action, latest, height FROM spine_public_key " + @@ -3288,6 +3410,9 @@ func (*mockSpineExecutorBlockPopSuccess) ExecuteSelectRow(qStr string, tx bool, mockSpineGoodBlock.GetTotalFee(), mockSpineGoodBlock.GetTotalCoinBase(), mockSpineGoodBlock.GetVersion(), + mockSpineGoodBlock.GetMerkleRoot(), + mockSpineGoodBlock.GetMerkleTree(), + mockSpineGoodBlock.GetReferenceBlockHeight(), ), ) return db.QueryRow(qStr), nil @@ -3406,6 +3531,9 @@ func (*mockSpineExecutorBlockPopSuccessPoppedBlocks) ExecuteSelectRow(qStr strin mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ) default: mockedRows.AddRow( @@ -3424,6 +3552,9 @@ func (*mockSpineExecutorBlockPopSuccessPoppedBlocks) ExecuteSelectRow(qStr strin mockGoodBlock.GetTotalFee(), mockGoodBlock.GetTotalCoinBase(), mockGoodBlock.GetVersion(), + mockGoodBlock.GetMerkleRoot(), + mockGoodBlock.GetMerkleTree(), + mockGoodBlock.GetReferenceBlockHeight(), ) } @@ -3786,7 +3917,7 @@ func (msExQ *mockSpineExecutorValidateSpineBlockManifest) ExecuteSelectRow(qStr switch qStr { case "SELECT height, id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, cumulative_difficulty, " + "payload_length, payload_hash, blocksmith_public_key, total_amount, total_fee, total_coinbase, " + - "version FROM spine_block WHERE timestamp >= 15875392 ORDER BY timestamp LIMIT 1": + "version, merkle_root, merkle_tree, reference_block_height FROM spine_block WHERE timestamp >= 15875392 ORDER BY timestamp LIMIT 1": mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(sqlmock.NewRows(query.NewBlockQuery(&chaintype.SpineChain{}).Fields). AddRow( mockSpineBlockData.GetHeight(), @@ -3805,6 +3936,9 @@ func (msExQ *mockSpineExecutorValidateSpineBlockManifest) ExecuteSelectRow(qStr mockSpineBlockData.GetTotalFee(), mockSpineBlockData.GetTotalCoinBase(), mockSpineBlockData.GetVersion(), + mockSpineBlockData.GetMerkleRoot(), + mockSpineBlockData.GetMerkleTree(), + mockSpineBlockData.GetReferenceBlockHeight(), )) default: return nil, errors.New("UnmockedQuery") @@ -3822,7 +3956,6 @@ func (ss *mockSpineBlockManifestService) GetSpineBlockManifestBytes(spineBlockMa func TestBlockSpineService_ValidateSpineBlockManifest(t *testing.T) { type fields struct { - RWMutex sync.RWMutex Chaintype chaintype.ChainType QueryExecutor query.ExecutorInterface BlockQuery query.BlockQueryInterface @@ -3960,7 +4093,6 @@ func TestBlockSpineService_ValidateSpineBlockManifest(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { bs := &BlockSpineService{ - RWMutex: tt.fields.RWMutex, Chaintype: tt.fields.Chaintype, QueryExecutor: tt.fields.QueryExecutor, BlockQuery: tt.fields.BlockQuery, diff --git a/core/service/receiptService_test.go b/core/service/receiptService_test.go index e4ec525ac..854fec8c4 100644 --- a/core/service/receiptService_test.go +++ b/core/service/receiptService_test.go @@ -376,6 +376,9 @@ func (*mockQueryExecutorSuccessOneLinkedReceipts) ExecuteSelectRow( mockBlockDataSelectReceipt.GetTotalFee(), mockBlockDataSelectReceipt.GetTotalCoinBase(), mockBlockDataSelectReceipt.GetVersion(), + mockBlockDataSelectReceipt.GetMerkleRoot(), + mockBlockDataSelectReceipt.GetMerkleTree(), + mockBlockDataSelectReceipt.GetReferenceBlockHeight(), )) } row := db.QueryRow(qe) @@ -441,6 +444,9 @@ func (*mockQueryExecutorSuccessOneLinkedReceiptsAndMore) ExecuteSelectRow( mockBlockDataSelectReceipt.GetTotalFee(), mockBlockDataSelectReceipt.GetTotalCoinBase(), mockBlockDataSelectReceipt.GetVersion(), + mockBlockDataSelectReceipt.GetMerkleRoot(), + mockBlockDataSelectReceipt.GetMerkleTree(), + mockBlockDataSelectReceipt.GetReferenceBlockHeight(), )) } row := db.QueryRow(qe) @@ -820,7 +826,7 @@ func (*mockQueryExecutorGenerateReceiptsMerkleRootSuccess) ExecuteSelectRow( switch qStr { case "SELECT MAX(height), id, block_hash, previous_block_hash, timestamp, block_seed, block_signature, " + "cumulative_difficulty, payload_length, payload_hash, blocksmith_public_key, total_amount, " + - "total_fee, total_coinbase, version FROM main_block": + "total_fee, total_coinbase, version, merkle_root, merkle_tree, reference_block_height FROM main_block": mock.ExpectQuery(regexp.QuoteMeta(qStr)). WillReturnRows(sqlmock.NewRows( query.NewBlockQuery(&chaintype.MainChain{}).Fields, @@ -840,6 +846,9 @@ func (*mockQueryExecutorGenerateReceiptsMerkleRootSuccess) ExecuteSelectRow( mockBlockData.GetTotalFee(), mockBlockData.GetTotalCoinBase(), mockBlockData.GetVersion(), + mockBlockData.GetMerkleRoot(), + mockBlockData.GetMerkleTree(), + mockBlockData.GetReferenceBlockHeight(), )) default: mock.ExpectQuery(regexp.QuoteMeta(qStr)). @@ -978,6 +987,9 @@ func (*mockExecutorPruningNodeReceiptsSuccess) ExecuteSelectRow(qStr string, tx mockBlockDataSelectReceipt.GetTotalFee(), mockBlockDataSelectReceipt.GetTotalCoinBase(), mockBlockDataSelectReceipt.GetVersion(), + mockBlockDataSelectReceipt.GetMerkleRoot(), + mockBlockDataSelectReceipt.GetMerkleTree(), + mockBlockDataSelectReceipt.GetReferenceBlockHeight(), ) mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(mockRow) return db.QueryRow(qStr), nil diff --git a/core/smith/strategy/blocksmithStrategySpine_test.go b/core/smith/strategy/blocksmithStrategySpine_test.go index d7c5b59be..4325bc9d3 100644 --- a/core/smith/strategy/blocksmithStrategySpine_test.go +++ b/core/smith/strategy/blocksmithStrategySpine_test.go @@ -63,6 +63,9 @@ func (*mockQueryGetBlocksmithsSpineFail) ExecuteSelectRow(qStr string, tx bool, mockBlock.GetTotalFee(), mockBlock.GetTotalCoinBase(), mockBlock.GetVersion(), + mockBlock.GetMerkleRoot(), + mockBlock.GetMerkleTree(), + mockBlock.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -164,6 +167,9 @@ func (*mockQuerySortBlocksmithSpineSuccessWithBlocksmiths) ExecuteSelectRow(qStr mockBlock.GetTotalFee(), mockBlock.GetTotalCoinBase(), mockBlock.GetVersion(), + mockBlock.GetMerkleRoot(), + mockBlock.GetMerkleTree(), + mockBlock.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } @@ -206,6 +212,9 @@ func (*mockQueryGetBlocksmithsSpineSuccessNoBlocksmith) ExecuteSelectRow(qStr st mockBlock.GetTotalFee(), mockBlock.GetTotalCoinBase(), mockBlock.GetVersion(), + mockBlock.GetMerkleRoot(), + mockBlock.GetMerkleTree(), + mockBlock.GetReferenceBlockHeight(), )) return db.QueryRow(qStr), nil } diff --git a/main.go b/main.go index e8d6bfb7c..c34d87539 100644 --- a/main.go +++ b/main.go @@ -539,6 +539,7 @@ func initiateMainInstance() { spineBlockStateStorage, blockchainStatusService, spinePublicKeyService, + mainchainBlockService, ) /* @@ -1004,8 +1005,8 @@ func start() { mainchainSyncChannel := make(chan bool, 1) mainchainSyncChannel <- true - startSpinechain() startMainchain() + startSpinechain() startServices() startScheduler() go startBlockchainSynchronizers()