From 56680d4d5fadb49b4bc3c800d5a819ef1c9c4a29 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 17:35:08 +0800 Subject: [PATCH 01/17] #55 add latest field to account balance --- common/model/accountBalance.pb.go | 105 ++++++++++++++++-------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/common/model/accountBalance.pb.go b/common/model/accountBalance.pb.go index 7b0706c06..bfbe17a3c 100644 --- a/common/model/accountBalance.pb.go +++ b/common/model/accountBalance.pb.go @@ -1,13 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: model/accountBalance.proto -package model +package model // import "github.com/zoobc/zoobc-core/common/model" -import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" -) +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -18,7 +16,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // AccountBalance represent the transaction data structure stored in the database type AccountBalance struct { @@ -27,6 +25,7 @@ type AccountBalance struct { SpendableBalance int64 `protobuf:"varint,3,opt,name=SpendableBalance,proto3" json:"SpendableBalance,omitempty"` Balance int64 `protobuf:"varint,4,opt,name=Balance,proto3" json:"Balance,omitempty"` PopRevenue int64 `protobuf:"varint,5,opt,name=PopRevenue,proto3" json:"PopRevenue,omitempty"` + Latest bool `protobuf:"varint,6,opt,name=Latest,proto3" json:"Latest,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -36,17 +35,16 @@ func (m *AccountBalance) Reset() { *m = AccountBalance{} } func (m *AccountBalance) String() string { return proto.CompactTextString(m) } func (*AccountBalance) ProtoMessage() {} func (*AccountBalance) Descriptor() ([]byte, []int) { - return fileDescriptor_44b9b1c521a5bcaa, []int{0} + return fileDescriptor_accountBalance_9be2208c33360bfc, []int{0} } - func (m *AccountBalance) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_AccountBalance.Unmarshal(m, b) } func (m *AccountBalance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_AccountBalance.Marshal(b, m, deterministic) } -func (m *AccountBalance) XXX_Merge(src proto.Message) { - xxx_messageInfo_AccountBalance.Merge(m, src) +func (dst *AccountBalance) XXX_Merge(src proto.Message) { + xxx_messageInfo_AccountBalance.Merge(dst, src) } func (m *AccountBalance) XXX_Size() int { return xxx_messageInfo_AccountBalance.Size(m) @@ -92,6 +90,13 @@ func (m *AccountBalance) GetPopRevenue() int64 { return 0 } +func (m *AccountBalance) GetLatest() bool { + if m != nil { + return m.Latest + } + return false +} + type GetAccountBalanceRequest struct { // Fetch AccountBalance by its ID AccountID uint32 `protobuf:"varint,1,opt,name=AccountID,proto3" json:"AccountID,omitempty"` @@ -106,17 +111,16 @@ func (m *GetAccountBalanceRequest) Reset() { *m = GetAccountBalanceReque func (m *GetAccountBalanceRequest) String() string { return proto.CompactTextString(m) } func (*GetAccountBalanceRequest) ProtoMessage() {} func (*GetAccountBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_44b9b1c521a5bcaa, []int{1} + return fileDescriptor_accountBalance_9be2208c33360bfc, []int{1} } - func (m *GetAccountBalanceRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetAccountBalanceRequest.Unmarshal(m, b) } func (m *GetAccountBalanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_GetAccountBalanceRequest.Marshal(b, m, deterministic) } -func (m *GetAccountBalanceRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetAccountBalanceRequest.Merge(m, src) +func (dst *GetAccountBalanceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetAccountBalanceRequest.Merge(dst, src) } func (m *GetAccountBalanceRequest) XXX_Size() int { return xxx_messageInfo_GetAccountBalanceRequest.Size(m) @@ -165,17 +169,16 @@ func (m *GetAccountBalancesRequest) Reset() { *m = GetAccountBalancesReq func (m *GetAccountBalancesRequest) String() string { return proto.CompactTextString(m) } func (*GetAccountBalancesRequest) ProtoMessage() {} func (*GetAccountBalancesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_44b9b1c521a5bcaa, []int{2} + return fileDescriptor_accountBalance_9be2208c33360bfc, []int{2} } - func (m *GetAccountBalancesRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetAccountBalancesRequest.Unmarshal(m, b) } func (m *GetAccountBalancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_GetAccountBalancesRequest.Marshal(b, m, deterministic) } -func (m *GetAccountBalancesRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetAccountBalancesRequest.Merge(m, src) +func (dst *GetAccountBalancesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetAccountBalancesRequest.Merge(dst, src) } func (m *GetAccountBalancesRequest) XXX_Size() int { return xxx_messageInfo_GetAccountBalancesRequest.Size(m) @@ -249,17 +252,16 @@ func (m *GetAccountBalancesResponse) Reset() { *m = GetAccountBalancesRe func (m *GetAccountBalancesResponse) String() string { return proto.CompactTextString(m) } func (*GetAccountBalancesResponse) ProtoMessage() {} func (*GetAccountBalancesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_44b9b1c521a5bcaa, []int{3} + return fileDescriptor_accountBalance_9be2208c33360bfc, []int{3} } - func (m *GetAccountBalancesResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_GetAccountBalancesResponse.Unmarshal(m, b) } func (m *GetAccountBalancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_GetAccountBalancesResponse.Marshal(b, m, deterministic) } -func (m *GetAccountBalancesResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetAccountBalancesResponse.Merge(m, src) +func (dst *GetAccountBalancesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetAccountBalancesResponse.Merge(dst, src) } func (m *GetAccountBalancesResponse) XXX_Size() int { return xxx_messageInfo_GetAccountBalancesResponse.Size(m) @@ -291,31 +293,34 @@ func init() { proto.RegisterType((*GetAccountBalancesResponse)(nil), "model.GetAccountBalancesResponse") } -func init() { proto.RegisterFile("model/accountBalance.proto", fileDescriptor_44b9b1c521a5bcaa) } - -var fileDescriptor_44b9b1c521a5bcaa = []byte{ - // 368 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xcd, 0x4a, 0xeb, 0x40, - 0x18, 0x25, 0x4d, 0x7f, 0xb8, 0x5f, 0x6f, 0x2f, 0xbd, 0x03, 0x17, 0xd2, 0x5e, 0x91, 0xd0, 0x55, - 0x28, 0x9a, 0x80, 0x6e, 0x55, 0xb4, 0x08, 0x56, 0x70, 0x21, 0xa9, 0xab, 0xee, 0x92, 0xe9, 0x47, - 0x13, 0x4c, 0xf2, 0xc5, 0x26, 0x51, 0xe8, 0x2b, 0xf8, 0x00, 0xbe, 0x89, 0xcf, 0x27, 0x4e, 0xa7, - 0x34, 0xcd, 0xb4, 0x05, 0x37, 0x81, 0x9c, 0x73, 0xbe, 0x73, 0x66, 0xe6, 0xcc, 0x40, 0x3f, 0xa6, - 0x19, 0x46, 0x8e, 0xc7, 0x39, 0x15, 0x49, 0x3e, 0xf2, 0x22, 0x2f, 0xe1, 0x68, 0xa7, 0x0b, 0xca, - 0x89, 0x35, 0x04, 0x37, 0xf8, 0xd4, 0xe0, 0xcf, 0xcd, 0x16, 0xcf, 0x8e, 0xe0, 0x97, 0x44, 0xee, - 0x6f, 0x0d, 0xcd, 0xd4, 0xac, 0xdf, 0xee, 0x06, 0x60, 0x26, 0xb4, 0x47, 0x11, 0xf1, 0xe7, 0x31, - 0x86, 0xf3, 0x20, 0x37, 0x6a, 0xa6, 0x66, 0x75, 0xdc, 0x32, 0xc4, 0x86, 0xd0, 0x9d, 0xa4, 0x98, - 0xcc, 0x3c, 0x3f, 0x42, 0xe9, 0x69, 0xe8, 0xa6, 0x66, 0xe9, 0xae, 0x82, 0x33, 0x03, 0x5a, 0x6b, - 0x49, 0x5d, 0x48, 0xd6, 0xbf, 0xec, 0x18, 0xe0, 0x91, 0x52, 0x17, 0x5f, 0x31, 0x29, 0xd0, 0x68, - 0x08, 0xb2, 0x84, 0x0c, 0xa6, 0x60, 0xdc, 0x61, 0xbe, 0xbd, 0x74, 0x17, 0x5f, 0x0a, 0xcc, 0x72, - 0x75, 0x07, 0x9d, 0x1f, 0xed, 0x60, 0xf0, 0xa1, 0x43, 0x4f, 0x31, 0xcf, 0xd6, 0xee, 0x43, 0xe8, - 0x4a, 0xe8, 0x81, 0xde, 0x70, 0xf1, 0x14, 0x78, 0x89, 0x0c, 0x51, 0x70, 0x76, 0x02, 0x7f, 0x25, - 0x36, 0x0e, 0xe7, 0x81, 0x14, 0xaf, 0x12, 0x55, 0x82, 0x5d, 0x40, 0xaf, 0x7a, 0x42, 0x9b, 0x08, - 0x5d, 0x4c, 0xed, 0x17, 0xb0, 0x2b, 0xe8, 0x57, 0xc9, 0x52, 0x68, 0x5d, 0x8c, 0x1f, 0x50, 0x7c, - 0xcf, 0x6f, 0xce, 0x57, 0x89, 0x6f, 0xac, 0xe6, 0xf7, 0x2b, 0xd8, 0x35, 0xfc, 0x57, 0xd8, 0xd2, - 0x02, 0x9a, 0xc2, 0xe0, 0x90, 0xa4, 0xda, 0x4c, 0x4b, 0x6d, 0xe6, 0x5d, 0x83, 0xfe, 0xae, 0x66, - 0xb2, 0x94, 0x92, 0x0c, 0x99, 0x0d, 0x6c, 0x9b, 0x9a, 0x84, 0x4b, 0x94, 0xe5, 0xec, 0x60, 0xd8, - 0x65, 0xf5, 0xf2, 0x1b, 0x35, 0x53, 0xb7, 0xda, 0x67, 0xff, 0x6c, 0xf1, 0x3a, 0xec, 0xca, 0xf5, - 0xaa, 0x88, 0x47, 0xc3, 0xa9, 0x35, 0x0f, 0xf3, 0xa0, 0xf0, 0x6d, 0x4e, 0xb1, 0xb3, 0x24, 0xf2, - 0xf9, 0xea, 0x7b, 0xca, 0x69, 0x81, 0x0e, 0xa7, 0x38, 0xa6, 0xc4, 0x11, 0x56, 0x7e, 0x53, 0x3c, - 0xbb, 0xf3, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x40, 0xbe, 0x99, 0x8b, 0x94, 0x03, 0x00, 0x00, +func init() { + proto.RegisterFile("model/accountBalance.proto", fileDescriptor_accountBalance_9be2208c33360bfc) +} + +var fileDescriptor_accountBalance_9be2208c33360bfc = []byte{ + // 384 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xc1, 0x6a, 0xdb, 0x40, + 0x10, 0x45, 0x96, 0x2d, 0xb7, 0xe3, 0xba, 0xb8, 0x0b, 0x2d, 0x6b, 0xb7, 0x14, 0xe1, 0x93, 0x30, + 0xad, 0x04, 0xed, 0xb5, 0x0d, 0x89, 0x09, 0xc4, 0x01, 0x1f, 0x82, 0x9c, 0x93, 0x6f, 0xd2, 0x7a, + 0xb0, 0x44, 0x24, 0xad, 0x62, 0xad, 0x12, 0xf0, 0x2f, 0xe4, 0x03, 0xf2, 0x57, 0xf9, 0xa6, 0x90, + 0xf5, 0x1a, 0xcb, 0x5a, 0xdb, 0x90, 0x8b, 0x60, 0xdf, 0x7b, 0xf3, 0x9e, 0x66, 0x67, 0x07, 0x06, + 0x29, 0x5f, 0x60, 0xe2, 0x05, 0x8c, 0xf1, 0x32, 0x13, 0xe3, 0x20, 0x09, 0x32, 0x86, 0x6e, 0xbe, + 0xe2, 0x82, 0x93, 0x96, 0xe4, 0x86, 0x2f, 0x06, 0x7c, 0xbe, 0xd8, 0xe3, 0xc9, 0x0f, 0xf8, 0xa8, + 0x90, 0xeb, 0x4b, 0x6a, 0xd8, 0x86, 0xf3, 0xc9, 0xdf, 0x01, 0xc4, 0x86, 0xce, 0x38, 0xe1, 0xec, + 0x6e, 0x82, 0xf1, 0x32, 0x12, 0xb4, 0x61, 0x1b, 0x4e, 0xd7, 0xaf, 0x42, 0x64, 0x04, 0xbd, 0x59, + 0x8e, 0xd9, 0x22, 0x08, 0x13, 0x54, 0x9e, 0xd4, 0xb4, 0x0d, 0xc7, 0xf4, 0x35, 0x9c, 0x50, 0x68, + 0x6f, 0x25, 0x4d, 0x29, 0xd9, 0x1e, 0xc9, 0x4f, 0x80, 0x1b, 0x9e, 0xfb, 0xf8, 0x80, 0x59, 0x89, + 0xb4, 0x25, 0xc9, 0x0a, 0x42, 0xbe, 0x81, 0x35, 0x0d, 0x04, 0x16, 0x82, 0x5a, 0xb6, 0xe1, 0x7c, + 0xf0, 0xd5, 0x69, 0x38, 0x07, 0x7a, 0x85, 0x62, 0xbf, 0x25, 0x1f, 0xef, 0x4b, 0x2c, 0x84, 0xde, + 0x59, 0xf7, 0x5d, 0x9d, 0x0d, 0x9f, 0x4d, 0xe8, 0x6b, 0xe6, 0xc5, 0xd6, 0x7d, 0x04, 0x3d, 0x05, + 0x4d, 0xf9, 0x23, 0xae, 0x6e, 0xa3, 0x20, 0x53, 0x21, 0x1a, 0x4e, 0x7e, 0xc1, 0x17, 0x85, 0x4d, + 0xe2, 0x65, 0xa4, 0xc4, 0x9b, 0x44, 0x9d, 0x20, 0xff, 0xa0, 0x5f, 0xbf, 0xb9, 0x5d, 0x84, 0x29, + 0xab, 0x8e, 0x0b, 0xc8, 0x19, 0x0c, 0xea, 0x64, 0x25, 0xb4, 0x29, 0xcb, 0x4f, 0x28, 0xde, 0xea, + 0x77, 0xf7, 0xae, 0xc5, 0xb7, 0x36, 0xf5, 0xc7, 0x15, 0xe4, 0x1c, 0xbe, 0x6b, 0x6c, 0xe5, 0x07, + 0x2c, 0x69, 0x70, 0x4a, 0x52, 0x9f, 0x4c, 0x5b, 0x9f, 0xcc, 0x93, 0x01, 0x83, 0x43, 0x93, 0x29, + 0x72, 0x9e, 0x15, 0x48, 0x5c, 0x20, 0xfb, 0xd4, 0x2c, 0x5e, 0xa3, 0x1a, 0xce, 0x01, 0x86, 0xfc, + 0xaf, 0x2f, 0x05, 0x6d, 0xd8, 0xa6, 0xd3, 0xf9, 0xf3, 0xd5, 0x95, 0x5b, 0xe3, 0xd6, 0x9e, 0x57, + 0x4d, 0x3c, 0x1e, 0xcd, 0x9d, 0x65, 0x2c, 0xa2, 0x32, 0x74, 0x19, 0x4f, 0xbd, 0x35, 0xe7, 0x21, + 0xdb, 0x7c, 0x7f, 0x33, 0xbe, 0x42, 0x8f, 0xf1, 0x34, 0xe5, 0x99, 0x27, 0xad, 0x42, 0x4b, 0xae, + 0xe3, 0xdf, 0xd7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xf8, 0x3b, 0x66, 0xac, 0x03, 0x00, 0x00, } From c22e0ca693add14c3fdcf4582bbae1f45a7cfaa9 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 17:36:41 +0800 Subject: [PATCH 02/17] #55 add genesis transactions --- core/service/blockCoreService.go | 13 ++++++- core/service/genesisCoreService.go | 55 ++++++++++++++++++++++++++++++ core/smith/blockchainProcessor.go | 11 ++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 core/service/genesisCoreService.go diff --git a/core/service/blockCoreService.go b/core/service/blockCoreService.go index 63d2e91cd..7e31a6409 100644 --- a/core/service/blockCoreService.go +++ b/core/service/blockCoreService.go @@ -5,6 +5,8 @@ import ( "fmt" "math/big" + "github.com/zoobc/zoobc-core/common/transaction" + "github.com/zoobc/zoobc-core/common/crypto" "github.com/zoobc/zoobc-core/common/contract" @@ -112,14 +114,23 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block) error { block.Height = previousBlock.GetHeight() + 1 block = core_util.CalculateSmithScale(previousBlock, block, bs.Chaintype.GetChainSmithingDelayTime()) } + // begin transaction blockInsertQuery, blockInsertValue := bs.BlockQuery.InsertBlock(block) result, err := bs.QueryExecutor.ExecuteStatement(blockInsertQuery, blockInsertValue...) if err != nil { return err } fmt.Printf("got new block, %v", result) - return nil // apply transactions + txs := block.GetTransactions() + for _, tx := range txs { // todo: this should be in a single `database transaction` as the block save function. + typedTx := transaction.GetTransactionType(tx, bs.QueryExecutor) + err = typedTx.ApplyConfirmed() + if err != nil { + return err + } + } + return nil // broadcast block } diff --git a/core/service/genesisCoreService.go b/core/service/genesisCoreService.go new file mode 100644 index 000000000..0b563781a --- /dev/null +++ b/core/service/genesisCoreService.go @@ -0,0 +1,55 @@ +package service + +import ( + "github.com/zoobc/zoobc-core/common/chaintype" + "github.com/zoobc/zoobc-core/common/contract" + "github.com/zoobc/zoobc-core/common/model" + "github.com/zoobc/zoobc-core/common/util" +) + +var genesisFundReceiver = map[string]int64{ // address : amount | public key hex + "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE": 10000000, // 04264418e6f758dc777c33957fd652e048ef388bff51e5b84d505027fead1ca9 + "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgtN": 10000000, // 04266749faa93f9b6a15094c4d89037815455a76f254aeef2ebe4e445a538e0b + "BCZKLvgUYZ1KKx-jtF9KoJskjVPvB9jpIjfzzI6zDW0J": 10000000, // 04264a2ef814619d4a2b1fa3b45f4aa09b248d53ef07d8e92237f3cc8eb30d6d +} + +const genesisSender = "BCZD_VxfO2S9aziIL3cn_cXW7uPDVPOrnXuP98GEAUC7" // 042643fd5c5f3b64bd6b38882f7727fdc5d6eee3c354f3ab9d7b8ff7c1840140 + +var genesisSignature = []byte{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} + +// GetGenesisTransactions return list of genesis transaction to be executed in the +// very beginning of running the blockchain +func GetGenesisTransactions(chainType contract.ChainType) []*model.Transaction { + genesisTxs := []*model.Transaction{} + switch chainType.(type) { + case *chaintype.MainChain: + for receiver, amount := range genesisFundReceiver { + genesisTxs = append(genesisTxs, &model.Transaction{ + Version: 1, + TransactionType: util.ConvertBytesToUint32([]byte{1, 0, 0, 0}), + Height: 0, + Timestamp: 1562806389280, + SenderAccountType: 0, + SenderAccountAddress: genesisSender, + RecipientAccountType: 0, + RecipientAccountAddress: receiver, + Fee: 0, + TransactionBodyLength: 8, + TransactionBody: &model.Transaction_SendMoneyTransactionBody{ + SendMoneyTransactionBody: &model.SendMoneyTransactionBody{ + Amount: amount, + }, + }, + TransactionBodyBytes: util.ConvertUint64ToBytes(uint64(amount)), + Signature: genesisSignature, + }) + } + return genesisTxs + default: + return nil + } + +} diff --git a/core/smith/blockchainProcessor.go b/core/smith/blockchainProcessor.go index ee7761c20..84143c931 100644 --- a/core/smith/blockchainProcessor.go +++ b/core/smith/blockchainProcessor.go @@ -7,6 +7,8 @@ import ( "math/big" "time" + "github.com/zoobc/zoobc-core/common/util" + "github.com/zoobc/zoobc-core/common/contract" "github.com/zoobc/zoobc-core/common/constant" @@ -169,6 +171,15 @@ func (bp *BlockchainProcessor) AddGenesis() error { var totalFee int64 var totalCoinBase int64 var blockTransactions []*model.Transaction + for _, tx := range service.GetGenesisTransactions(bp.Chaintype) { + txBytes, _ := coreUtil.GetTransactionBytes(tx, true) + _, _ = digest.Write(txBytes) + if tx.TransactionType == util.ConvertBytesToUint32([]byte{1, 0, 0, 0}) { // if type = send money + totalAmount += tx.GetSendMoneyTransactionBody().Amount + } + totalFee += tx.Fee + blockTransactions = append(blockTransactions, tx) + } payloadHash := digest.Sum([]byte{}) block := bp.BlockService.NewGenesisBlock(1, nil, make([]byte, 64), []byte{}, "", 0, constant.GenesisBlockTimestamp, totalAmount, totalFee, totalCoinBase, blockTransactions, payloadHash, constant.InitialSmithScale, From b9cb28db25eb58128b21fadb9951c777a6f27e99 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 17:37:04 +0800 Subject: [PATCH 03/17] #55 update smith time delay to 60 second --- common/chaintype/mainchain.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/chaintype/mainchain.go b/common/chaintype/mainchain.go index a57ea876e..99766948e 100644 --- a/common/chaintype/mainchain.go +++ b/common/chaintype/mainchain.go @@ -10,7 +10,7 @@ func (*MainChain) GetTablePrefix() string { // GetChainSmithingDelayTime return the value of chain smithing delay in second func (*MainChain) GetChainSmithingDelayTime() int64 { - return 6 + return 60 } // GetName return the name of the chain : used in parsing chaintype across node From 69c17018fc2295a51d9d456bae601e2838892f19 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 17:38:00 +0800 Subject: [PATCH 04/17] #55 update doc --- core/util/transactionUtil.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/util/transactionUtil.go b/core/util/transactionUtil.go index f51e9e781..f9d57a578 100644 --- a/core/util/transactionUtil.go +++ b/core/util/transactionUtil.go @@ -82,6 +82,8 @@ func ParseTransactionBytes(transactionBytes []byte, sign bool) (*model.Transacti }, nil } +// ReadAccountAddress support different way to read the sender or recipient address depending on +// their types. func ReadAccountAddress(accountType uint32, buf *bytes.Buffer) []byte { switch accountType { case 0: From 7400e6018a75bc72dc19e3db5ae1bfdd240ce7a5 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 17:40:26 +0800 Subject: [PATCH 05/17] #55 update send money applyConfirmed logic --- common/query/accountBalanceQuery.go | 27 ++++-- common/transaction/sendMoney.go | 111 ++++++++++++++----------- common/transaction/sendMoney_test.go | 4 +- common/transaction/transaction.go | 6 +- common/transaction/transaction_test.go | 15 +++- 5 files changed, 104 insertions(+), 59 deletions(-) diff --git a/common/query/accountBalanceQuery.go b/common/query/accountBalanceQuery.go index 08b13117c..c66ad2b90 100644 --- a/common/query/accountBalanceQuery.go +++ b/common/query/accountBalanceQuery.go @@ -19,6 +19,8 @@ type ( GetAccountBalanceByAccountID() string UpdateAccountBalance(fields, causedFields map[string]interface{}) (str string, args []interface{}) InsertAccountBalance(accountBalance *model.AccountBalance) (str string, args []interface{}) + AddAccountBalance(balance int64, causedFields map[string]interface{}) (str string, args []interface{}) + AddAccountUnconfirmedBalance(balance int64, causedFields map[string]interface{}) (str string, args []interface{}) } ) @@ -31,6 +33,7 @@ func NewAccountBalanceQuery() *AccountBalanceQuery { "spendable_balance", "balance", "pop_revenue", + "latest", }, TableName: "account_balance", } @@ -43,6 +46,17 @@ func (q *AccountBalanceQuery) GetAccountBalanceByAccountID() string { `, strings.Join(q.Fields, ","), q.TableName) } +func (q *AccountBalanceQuery) AddAccountBalance(balance int64, causedFields map[string]interface{}) (str string, args []interface{}) { + return fmt.Sprintf("UPDATE %s SET balance = balance + (%d), spendable_balance = spendable_balance + (%d) WHERE account_id = ?", + q.TableName, balance, balance), []interface{}{causedFields["account_id"]} +} + +func (q *AccountBalanceQuery) AddAccountUnconfirmedBalance(balance int64, causedFields map[string]interface{}) ( + str string, args []interface{}) { + return fmt.Sprintf("UPDATE %s SET spendable_balance = spendable_balance + (%d) WHERE account_id = ?", + q.TableName, balance), []interface{}{causedFields["account_id"]} +} + func (q *AccountBalanceQuery) UpdateAccountBalance(fields, causedFields map[string]interface{}) (str string, args []interface{}) { var ( @@ -55,18 +69,18 @@ func (q *AccountBalanceQuery) UpdateAccountBalance(fields, causedFields map[stri `, q.TableName)) for k, v := range fields { - buff.WriteString(fmt.Sprintf("%s = ?", k)) - if i < len(fields) { + buff.WriteString(fmt.Sprintf("%s = ? ", k)) + if i < len(fields) && len(fields) > 1 { buff.WriteString(",") } args = append(args, v) i++ } - buff.WriteString("WHERE") + buff.WriteString("WHERE ") for k, v := range causedFields { buff.WriteString(fmt.Sprintf("%s = ?", k)) - if j < len(causedFields) { + if j < len(causedFields) && len(causedFields) > 1 { buff.WriteString(" AND") } j++ @@ -88,9 +102,10 @@ func (q *AccountBalanceQuery) InsertAccountBalance(accountBalance *model.Account func (*AccountBalanceQuery) ExtractModel(account *model.AccountBalance) []interface{} { return []interface{}{ account.AccountID, - account.Balance, - account.SpendableBalance, account.BlockHeight, + account.SpendableBalance, + account.Balance, account.PopRevenue, + account.Latest, } } diff --git a/common/transaction/sendMoney.go b/common/transaction/sendMoney.go index 088959aab..e7a60d0c5 100644 --- a/common/transaction/sendMoney.go +++ b/common/transaction/sendMoney.go @@ -34,62 +34,91 @@ __If Not Genesis__: `sender.balance` = current - amount */ func (tx *SendMoney) ApplyConfirmed() error { - + // todo: undo apply unconfirmed for non-genesis transaction var ( - accountBalance model.AccountBalance - account model.Account - err error + recipientAccountBalance model.AccountBalance + recipientAccount model.Account + senderAccountBalance model.AccountBalance + senderAccount model.Account + err error ) if err := tx.Validate(); err != nil { return err } + recipientAccount = model.Account{ + ID: util.CreateAccountIDFromAddress(tx.RecipientAccountType, tx.RecipientAddress), + AccountType: tx.RecipientAccountType, + Address: tx.RecipientAddress, + } + senderAccount = model.Account{ + ID: util.CreateAccountIDFromAddress(tx.SenderAccountType, tx.SenderAddress), + AccountType: tx.SenderAccountType, + Address: tx.SenderAddress, + } + if tx.Height == 0 { - account = model.Account{ - ID: util.CreateAccountIDFromAddress(tx.RecipientAccountType, tx.RecipientAddress), - AccountType: tx.RecipientAccountType, - Address: tx.RecipientAddress, + senderAccountQ, senderAccountArgs := tx.AccountQuery.GetAccountByID(senderAccount.ID) + senderAccountRows, _ := tx.QueryExecutor.ExecuteSelect(senderAccountQ, senderAccountArgs...) + if !senderAccountRows.Next() { // genesis account not created yet + senderAccountBalance = model.AccountBalance{ + AccountID: senderAccount.ID, + BlockHeight: tx.Height, + SpendableBalance: 0, + Balance: 0, + PopRevenue: 0, + Latest: true, + } + senderAccountInsertQ, senderAccountInsertArgs := tx.AccountQuery.InsertAccount(&senderAccount) + senderAccountBalanceInsertQ, senderAccountBalanceInsertArgs := tx.AccountBalanceQuery.InsertAccountBalance(&senderAccountBalance) + _, err = tx.QueryExecutor.ExecuteTransactionStatements(map[*string][]interface{}{ + &senderAccountInsertQ: senderAccountInsertArgs, + &senderAccountBalanceInsertQ: senderAccountBalanceInsertArgs, + }) + if err != nil { + return err + } } - accountBalance = model.AccountBalance{ - AccountID: account.ID, + _ = senderAccountRows.Close() + recipientAccountBalance = model.AccountBalance{ + AccountID: recipientAccount.ID, BlockHeight: tx.Height, SpendableBalance: tx.Body.GetAmount(), Balance: tx.Body.GetAmount(), PopRevenue: 0, + Latest: true, } - accountQ, accountQArgs := tx.AccountQuery.InsertAccount(&account) - accountBalanceQ, accountBalanceArgs := tx.AccountBalanceQuery.InsertAccountBalance(&accountBalance) + accountQ, accountQArgs := tx.AccountQuery.InsertAccount(&recipientAccount) + accountBalanceQ, accountBalanceArgs := tx.AccountBalanceQuery.InsertAccountBalance(&recipientAccountBalance) + // update sender + accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.AddAccountBalance( + -tx.Body.GetAmount(), + map[string]interface{}{ + "account_id": senderAccount.ID, + }, + ) _, err = tx.QueryExecutor.ExecuteTransactionStatements(map[*string][]interface{}{ - &accountQ: accountQArgs, - &accountBalanceQ: accountBalanceArgs, + &accountQ: accountQArgs, + &accountBalanceQ: accountBalanceArgs, + &accountBalanceSenderQ: accountBalanceSenderQArgs, }) if err != nil { return err } } else { // update recipient - accountBalanceRecipientQ, accountBalanceRecipientQArgs := tx.AccountBalanceQuery.UpdateAccountBalance( - map[string]interface{}{ - "balance": fmt.Sprintf("balance + %d", tx.Body.GetAmount()), - }, + accountBalanceRecipientQ, accountBalanceRecipientQArgs := tx.AccountBalanceQuery.AddAccountBalance( + tx.Body.Amount, map[string]interface{}{ - "account_id": util.CreateAccountIDFromAddress( - tx.RecipientAccountType, - tx.RecipientAddress, - ), + "account_id": recipientAccount.ID, }, ) // update sender - accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.UpdateAccountBalance( + accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.AddAccountBalance( + -tx.Body.Amount, map[string]interface{}{ - "balance": fmt.Sprintf("balance - %d", tx.Body.GetAmount()), - }, - map[string]interface{}{ - "account_id": util.CreateAccountIDFromAddress( - tx.SenderAccountType, - tx.SenderAddress, - ), + "account_id": senderAccount.ID, }, ) _, err = tx.QueryExecutor.ExecuteTransactionStatements(map[*string][]interface{}{ @@ -117,23 +146,9 @@ func (tx *SendMoney) ApplyUnconfirmed() error { return err } - // update recipient - accountBalanceRecipientQ, accountBalanceRecipientQArgs := tx.AccountBalanceQuery.UpdateAccountBalance( - map[string]interface{}{ - "account_balance": fmt.Sprintf("account_balance + %d", tx.Body.GetAmount()), - }, - map[string]interface{}{ - "account_id": util.CreateAccountIDFromAddress( - tx.RecipientAccountType, - tx.RecipientAddress, - ), - }, - ) // update sender - accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.UpdateAccountBalance( - map[string]interface{}{ - "account_balance": fmt.Sprintf("account_balance - %d", tx.Body.GetAmount()), - }, + accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.AddAccountUnconfirmedBalance( + -tx.Body.Amount, map[string]interface{}{ "account_id": util.CreateAccountIDFromAddress( tx.SenderAccountType, @@ -142,8 +157,7 @@ func (tx *SendMoney) ApplyUnconfirmed() error { }, ) _, err = tx.QueryExecutor.ExecuteTransactionStatements(map[*string][]interface{}{ - &accountBalanceSenderQ: accountBalanceSenderQArgs, - &accountBalanceRecipientQ: accountBalanceRecipientQArgs, + &accountBalanceSenderQ: accountBalanceSenderQArgs, }) if err != nil { return err @@ -204,6 +218,7 @@ func (tx *SendMoney) Validate() error { &accountBalance.SpendableBalance, &accountBalance.Balance, &accountBalance.PopRevenue, + &accountBalance.Latest, ) } diff --git a/common/transaction/sendMoney_test.go b/common/transaction/sendMoney_test.go index 88d91c4ad..76b19204c 100644 --- a/common/transaction/sendMoney_test.go +++ b/common/transaction/sendMoney_test.go @@ -65,7 +65,7 @@ func (*executorValidateSuccess) ExecuteSelect(qStr string, args ...interface{}) mock.ExpectQuery(regexp.QuoteMeta(qStr)).WithArgs(1).WillReturnRows(sqlmock.NewRows( query.NewAccountBalanceQuery().Fields, - ).AddRow(1, 2, 50, 50, 0)) + ).AddRow(1, 2, 50, 50, 0, 1)) return db.Query(qStr, 1) } func (*executorValidateSuccess) ExecuteTransactionStatements(queries map[*string][]interface{}) ([]sql.Result, error) { @@ -149,7 +149,7 @@ func (*executorAccountCountSuccess) ExecuteSelect(qStr string, args ...interface mock.ExpectQuery(regexp.QuoteMeta(qStr)).WithArgs(1).WillReturnRows(sqlmock.NewRows( query.NewAccountBalanceQuery().Fields, - ).AddRow(1, 2, 3, 4, 5)) + ).AddRow(1, 2, 3, 4, 5, 6)) return db.Query(qStr, 1) } diff --git a/common/transaction/transaction.go b/common/transaction/transaction.go index efddc1a22..2049932f1 100644 --- a/common/transaction/transaction.go +++ b/common/transaction/transaction.go @@ -2,6 +2,7 @@ package transaction import ( "github.com/zoobc/zoobc-core/common/model" + "github.com/zoobc/zoobc-core/common/query" "github.com/zoobc/zoobc-core/common/util" ) @@ -13,7 +14,7 @@ type ( } ) -func GetTransactionType(tx *model.Transaction) TypeAction { +func GetTransactionType(tx *model.Transaction, executor query.ExecutorInterface) TypeAction { buf := util.ConvertUint32ToBytes(tx.GetTransactionType()) switch buf[0] { @@ -34,6 +35,9 @@ func GetTransactionType(tx *model.Transaction) TypeAction { RecipientAddress: tx.GetRecipientAccountAddress(), RecipientAccountType: tx.GetRecipientAccountType(), Height: tx.GetHeight(), + AccountQuery: query.NewAccountQuery(), + AccountBalanceQuery: query.NewAccountBalanceQuery(), + QueryExecutor: executor, } default: return nil diff --git a/common/transaction/transaction_test.go b/common/transaction/transaction_test.go index 59b65ad5b..98398790d 100644 --- a/common/transaction/transaction_test.go +++ b/common/transaction/transaction_test.go @@ -5,12 +5,15 @@ import ( "reflect" "testing" + "github.com/zoobc/zoobc-core/common/query" + "github.com/zoobc/zoobc-core/common/model" ) func TestGetTransactionType(t *testing.T) { type args struct { - tx *model.Transaction + tx *model.Transaction + executor query.ExecutorInterface } tests := []struct { name string @@ -33,6 +36,7 @@ func TestGetTransactionType(t *testing.T) { }, TransactionType: binary.LittleEndian.Uint32([]byte{1, 0, 0, 0}), }, + executor: nil, }, want: TypeAction(&SendMoney{ Height: 0, @@ -43,6 +47,9 @@ func TestGetTransactionType(t *testing.T) { Body: &model.SendMoneyTransactionBody{ Amount: 10, }, + QueryExecutor: nil, + AccountBalanceQuery: query.NewAccountBalanceQuery(), + AccountQuery: query.NewAccountQuery(), }), }, { @@ -61,6 +68,7 @@ func TestGetTransactionType(t *testing.T) { }, TransactionType: binary.LittleEndian.Uint32([]byte{0, 0, 0, 0}), }, + executor: nil, }, want: TypeAction(&TXEmpty{}), }, @@ -80,6 +88,7 @@ func TestGetTransactionType(t *testing.T) { }, TransactionType: binary.LittleEndian.Uint32([]byte{0, 1, 0, 0}), }, + executor: nil, }, }, { @@ -98,6 +107,7 @@ func TestGetTransactionType(t *testing.T) { }, TransactionType: binary.LittleEndian.Uint32([]byte{1, 1, 0, 0}), }, + executor: nil, }, }, { @@ -116,12 +126,13 @@ func TestGetTransactionType(t *testing.T) { }, TransactionType: binary.LittleEndian.Uint32([]byte{2, 1, 0, 0}), }, + executor: nil, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := GetTransactionType(tt.args.tx); !reflect.DeepEqual(got, tt.want) { + if got := GetTransactionType(tt.args.tx, tt.args.executor); !reflect.DeepEqual(got, tt.want) { t.Errorf("GetTransactionType() = %v, want %v", got, tt.want) } }) From d7024a22e4c12805dd9a1b77b01fc15af0e62d38 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 17:41:55 +0800 Subject: [PATCH 06/17] #55 update schema commit hash --- common/schema | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/schema b/common/schema index 89a8c9fa5..120cc6427 160000 --- a/common/schema +++ b/common/schema @@ -1 +1 @@ -Subproject commit 89a8c9fa5319476f17345e2bf92e62c011071814 +Subproject commit 120cc6427119bdb51349985fdc378d69a5063c7a From 9b5f0dc5662ba13ceecb632db6b6b1ba261bf314 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 19:18:43 +0800 Subject: [PATCH 07/17] #55 add getsize and get amount --- common/transaction/empty.go | 6 ++++++ common/transaction/sendMoney.go | 8 ++++++++ common/transaction/transaction.go | 2 ++ 3 files changed, 16 insertions(+) diff --git a/common/transaction/empty.go b/common/transaction/empty.go index 6371fbd0d..f5e0b803c 100644 --- a/common/transaction/empty.go +++ b/common/transaction/empty.go @@ -17,3 +17,9 @@ func (tx *TXEmpty) ApplyUnconfirmed() error { func (tx *TXEmpty) Validate() error { return nil } +func (*TXEmpty) GetAmount() int64 { + return 0 +} +func (tx *TXEmpty) GetSize() uint32 { + return 0 +} diff --git a/common/transaction/sendMoney.go b/common/transaction/sendMoney.go index e7a60d0c5..591eb6230 100644 --- a/common/transaction/sendMoney.go +++ b/common/transaction/sendMoney.go @@ -228,3 +228,11 @@ func (tx *SendMoney) Validate() error { } return nil } + +func (tx *SendMoney) GetAmount() int64 { + return tx.Body.Amount +} + +func (*SendMoney) GetSize() uint32 { + return 8 +} diff --git a/common/transaction/transaction.go b/common/transaction/transaction.go index 2049932f1..3ad29c406 100644 --- a/common/transaction/transaction.go +++ b/common/transaction/transaction.go @@ -11,6 +11,8 @@ type ( ApplyConfirmed() error ApplyUnconfirmed() error Validate() error + GetAmount() int64 + GetSize() uint32 } ) From e98be1e37f365b87c177ad5ba3c52206e25278cf Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Wed, 17 Jul 2019 20:10:33 +0800 Subject: [PATCH 08/17] #55 changes due to conflict --- core/service/blockCoreService_test.go | 7 +++++-- core/service/mempoolCoreService.go | 4 ++-- core/smith/blockchainProcessor_test.go | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/service/blockCoreService_test.go b/core/service/blockCoreService_test.go index 8dfc573fd..f217425b9 100644 --- a/core/service/blockCoreService_test.go +++ b/core/service/blockCoreService_test.go @@ -163,6 +163,7 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { totalCoinBase int64 transactions []*model.Transaction payloadHash []byte + payloadLength uint32 smithScale int64 cumulativeDifficulty *big.Int genesisSignature []byte @@ -192,6 +193,7 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { totalCoinBase: 0, transactions: []*model.Transaction{}, payloadHash: []byte{}, + payloadLength: 8, smithScale: 0, cumulativeDifficulty: big.NewInt(1), genesisSignature: []byte{}, @@ -207,6 +209,7 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { TotalCoinBase: 0, Transactions: []*model.Transaction{}, PayloadHash: []byte{}, + PayloadLength: 8, SmithScale: 0, CumulativeDifficulty: "1", BlockSignature: []byte{}, @@ -219,8 +222,8 @@ func TestBlockService_NewGenesisBlock(t *testing.T) { } if got := b.NewGenesisBlock(test.args.version, test.args.previousBlockHash, test.args.blockSeed, test.args.blocksmithID, test.args.hash, test.args.previousBlockHeight, test.args.timestamp, test.args.totalAmount, test.args.totalFee, - test.args.totalCoinBase, test.args.transactions, test.args.payloadHash, test.args.smithScale, test.args.cumulativeDifficulty, - test.args.genesisSignature); !reflect.DeepEqual(got, test.want) { + test.args.totalCoinBase, test.args.transactions, test.args.payloadHash, test.args.payloadLength, test.args.smithScale, + test.args.cumulativeDifficulty, test.args.genesisSignature); !reflect.DeepEqual(got, test.want) { t.Errorf("BlockService.NewGenesisBlock() = %v, want %v", got, test.want) } } diff --git a/core/service/mempoolCoreService.go b/core/service/mempoolCoreService.go index 187bdcc75..fac30af45 100644 --- a/core/service/mempoolCoreService.go +++ b/core/service/mempoolCoreService.go @@ -140,7 +140,7 @@ func (mps *MempoolService) ValidateMempoolTransaction(mpTx *model.MempoolTransac return errors.New("InvalidTransactionID") } - if err := transaction.GetTransactionType(tx).Validate(); err != nil { + if err := transaction.GetTransactionType(tx, mps.QueryExecutor).Validate(); err != nil { return err } @@ -182,7 +182,7 @@ func (mps *MempoolService) SelectTransactionsFromMempool(blockTimestamp int64) ( continue } - if err := transaction.GetTransactionType(tx).Validate(); err != nil { + if err := transaction.GetTransactionType(tx, mps.QueryExecutor).Validate(); err != nil { continue } diff --git a/core/smith/blockchainProcessor_test.go b/core/smith/blockchainProcessor_test.go index 225e28dd9..3071f869e 100644 --- a/core/smith/blockchainProcessor_test.go +++ b/core/smith/blockchainProcessor_test.go @@ -118,7 +118,7 @@ func (*mockBlockServiceSuccess) NewBlock(version uint32, previousBlockHash, bloc } func (*mockBlockServiceSuccess) NewGenesisBlock(version uint32, previousBlockHash, blockSeed, blocksmithID []byte, hash string, previousBlockHeight uint32, timestamp, totalAmount, totalFee, totalCoinBase int64, - transactions []*model.Transaction, payloadHash []byte, smithScale int64, cumulativeDifficulty *big.Int, + transactions []*model.Transaction, payloadHash []byte, payloadLength uint32, smithScale int64, cumulativeDifficulty *big.Int, genesisSignature []byte) *model.Block { return &model.Block{ Version: 1, @@ -131,7 +131,7 @@ func (*mockBlockServiceSuccess) NewGenesisBlock(version uint32, previousBlockHas TotalCoinBase: 0, Transactions: []*model.Transaction{}, PayloadHash: []byte{}, - PayloadLength: 0, + PayloadLength: payloadLength, SmithScale: 0, CumulativeDifficulty: "1", BlockSignature: []byte{}, From 406897e9f02f0344509aeb580c6337d919831bde Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 08:23:19 +0800 Subject: [PATCH 09/17] #55 update query tests --- common/query/transactionQuery_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/query/transactionQuery_test.go b/common/query/transactionQuery_test.go index eda1cc80a..43747ef7a 100644 --- a/common/query/transactionQuery_test.go +++ b/common/query/transactionQuery_test.go @@ -23,7 +23,7 @@ func TestGetTransaction(t *testing.T) { params: ¶msStruct{}, want: "SELECT id, block_id, block_height, sender_account_type, sender_account_address, " + "recipient_account_type, recipient_account_address, transaction_type, fee, timestamp, " + - "transaction_hash, transaction_body_length, transaction_body_bytes, signature from \"transaction\"", + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version from \"transaction\"", }, { name: "transaction query with ID param only", @@ -32,7 +32,7 @@ func TestGetTransaction(t *testing.T) { }, want: "SELECT id, block_id, block_height, sender_account_type, sender_account_address, " + "recipient_account_type, recipient_account_address, transaction_type, fee, timestamp, " + - "transaction_hash, transaction_body_length, transaction_body_bytes, signature from \"transaction\" " + + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version from \"transaction\" " + "WHERE id = 1", }, } @@ -65,7 +65,7 @@ func TestGetTransactions(t *testing.T) { params: ¶msStruct{}, want: "SELECT id, block_id, block_height, sender_account_type, sender_account_address, " + "recipient_account_type, recipient_account_address, transaction_type, fee, timestamp, " + - "transaction_hash, transaction_body_length, transaction_body_bytes, signature from " + + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version from " + "\"transaction\" ORDER BY block_height, timestamp LIMIT 0,10", }, { @@ -75,7 +75,7 @@ func TestGetTransactions(t *testing.T) { }, want: "SELECT id, block_id, block_height, sender_account_type, sender_account_address, " + "recipient_account_type, recipient_account_address, transaction_type, fee, timestamp, " + - "transaction_hash, transaction_body_length, transaction_body_bytes, signature from " + + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version from " + "\"transaction\" ORDER BY block_height, timestamp LIMIT 0,10", }, { @@ -85,7 +85,7 @@ func TestGetTransactions(t *testing.T) { }, want: "SELECT id, block_id, block_height, sender_account_type, sender_account_address, " + "recipient_account_type, recipient_account_address, transaction_type, fee, timestamp, " + - "transaction_hash, transaction_body_length, transaction_body_bytes, signature from " + + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version from " + "\"transaction\" ORDER BY block_height, timestamp LIMIT 20,10", }, { @@ -96,7 +96,7 @@ func TestGetTransactions(t *testing.T) { }, want: "SELECT id, block_id, block_height, sender_account_type, sender_account_address, " + "recipient_account_type, recipient_account_address, transaction_type, fee, timestamp, " + - "transaction_hash, transaction_body_length, transaction_body_bytes, signature from " + + "transaction_hash, transaction_body_length, transaction_body_bytes, signature, version from " + "\"transaction\" ORDER BY block_height, timestamp LIMIT 20,10", }, } From cd5298496e634aac3ef44f9fbf7423779c887389 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 09:55:30 +0800 Subject: [PATCH 10/17] #55 update signature to accept accounttype+address instead of account ID --- common/crypto/signature.go | 44 +++------ common/crypto/signature_test.go | 159 ++++++++++---------------------- 2 files changed, 64 insertions(+), 139 deletions(-) diff --git a/common/crypto/signature.go b/common/crypto/signature.go index 8b5469f5b..759eae23c 100644 --- a/common/crypto/signature.go +++ b/common/crypto/signature.go @@ -1,44 +1,31 @@ package crypto import ( - "github.com/zoobc/zoobc-core/common/model" - "github.com/zoobc/zoobc-core/common/query" + "github.com/zoobc/zoobc-core/common/util" "golang.org/x/crypto/ed25519" ) type ( SignatureInterface interface { - Sign(payload, accountID []byte, seed string) []byte + Sign(payload []byte, accountType uint32, accountAddress, seed string) []byte SignBlock(payload []byte, nodeSeed string) []byte - VerifySignature(payload, signature, accountID []byte) bool + VerifySignature(payload, signature []byte, accountType uint32, accountAddress string) bool } // Signature object handle signing and verifying different signature Signature struct { - Executor query.ExecutorInterface } ) // NewSignature create new instance of signature object -func NewSignature(executor query.ExecutorInterface) *Signature { - return &Signature{ - Executor: executor, - } +func NewSignature() *Signature { + return &Signature{} } // Sign accept account ID and payload to be signed then return the signature byte based on the // signature method associated with account.Type -func (sig *Signature) Sign(payload, accountID []byte, seed string) []byte { - - accountQuery := query.NewAccountQuery() - getQuery, condition := accountQuery.GetAccountByID(accountID) - accountRows, _ := sig.Executor.ExecuteSelect(getQuery, condition...) - var accounts []*model.Account - account := accountQuery.BuildModel(accounts, accountRows) - if len(account) == 0 { - return nil - } - switch account[0].AccountType { +func (sig *Signature) Sign(payload []byte, accountType uint32, accountAddress, seed string) []byte { + switch accountType { case 0: // zoobc accountPrivateKey := ed25519GetPrivateKeyFromSeed(seed) signature := ed25519.Sign(accountPrivateKey, payload) @@ -58,21 +45,16 @@ func (*Signature) SignBlock(payload []byte, nodeSeed string) []byte { // VerifySignature accept payload (before without signature), signature and the account id // then verify the signature + public key against the payload based on the -func (*Signature) VerifySignature(payload, signature, accountID []byte) bool { - // todo: Fetch account from accountID - account := &model.Account{ - ID: []byte{4, 38, 68, 24, 230, 247, 88, 220, 119, 124, 51, 149, 127, 214, 82, 224, 72, 239, 56, 139, - 255, 81, 229, 184, 77, 80, 80, 39, 254, 173, 28, 169}, - AccountType: 0, - Address: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", - } +func (*Signature) VerifySignature(payload, signature []byte, accountType uint32, accountAddress string) bool { - switch account.AccountType { + switch accountType { case 0: // zoobc - result := ed25519.Verify(accountID, payload, signature) + accountPublicKey, _ := util.GetPublicKeyFromAddress(accountAddress) + result := ed25519.Verify(accountPublicKey, payload, signature) return result default: - result := ed25519.Verify(accountID, payload, signature) + accountPublicKey, _ := util.GetPublicKeyFromAddress(accountAddress) + result := ed25519.Verify(accountPublicKey, payload, signature) return result } } diff --git a/common/crypto/signature_test.go b/common/crypto/signature_test.go index de3399edd..eec3a961c 100644 --- a/common/crypto/signature_test.go +++ b/common/crypto/signature_test.go @@ -1,122 +1,70 @@ package crypto import ( - "database/sql" "reflect" - "regexp" "testing" - - "github.com/DATA-DOG/go-sqlmock" - - "github.com/zoobc/zoobc-core/common/query" ) func TestNewSignature(t *testing.T) { - type args struct { - executor query.ExecutorInterface - } tests := []struct { name string - args args want *Signature }{ { name: "NewSignature:success", - args: args{ - executor: nil, - }, - want: &Signature{ - Executor: nil, - }, + want: &Signature{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := NewSignature(tt.args.executor); !reflect.DeepEqual(got, tt.want) { + if got := NewSignature(); !reflect.DeepEqual(got, tt.want) { t.Errorf("NewSignature() = %v, want %v", got, tt.want) } }) } } -type mockSignatureSignExecutorSuccess struct { - query.Executor -} - -func (*mockSignatureSignExecutorSuccess) ExecuteSelect(qe string, args ...interface{}) (*sql.Rows, error) { - db, mock, _ := sqlmock.New() - mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, account_type, address FROM account`)).WillReturnRows(sqlmock.NewRows([]string{ - "ID", "AccountType", "Address"}). - AddRow([]byte{7, 205, 139, 247, 101, 123, 250, 42, 95, 96, 199, 181, 108, 85, 197, 164, 168, 36, 49, 12, 251, 252, - 209, 82, 181, 112, 94, 41, 107, 240, 83, 180}, 0, "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgs=")) - defer db.Close() - rows, _ := db.Query(qe) - return rows, nil -} - -type mockSignatureSignExecutorFail struct { - query.Executor -} - -func (*mockSignatureSignExecutorFail) ExecuteSelect(qe string, args ...interface{}) (*sql.Rows, error) { - db, mock, _ := sqlmock.New() - mock.ExpectQuery(regexp.QuoteMeta(`SELECT id, account_type, address FROM account`)).WillReturnRows(sqlmock.NewRows([]string{ - "ID", "AccountType", "Address"})) - defer db.Close() - rows, _ := db.Query(qe) - return rows, nil -} - func TestSignature_Sign(t *testing.T) { - type fields struct { - Executor query.ExecutorInterface - } type args struct { - payload []byte - accountID []byte - seed string + payload []byte + accountType uint32 + accountAddress string + seed string } tests := []struct { - name string - fields fields - args args - want []byte + name string + args args + want []byte }{ { name: "Sign:valid", - fields: fields{ - Executor: &mockSignatureSignExecutorSuccess{}, - }, args: args{ - payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, - accountID: []byte{4, 38, 68, 24, 230, 247, 88, 220, 119, 124, 51, 149, 127, 214, 82, 224, 72, 239, 56, 139, - 255, 81, 229, 184, 77, 80, 80, 39, 254, 173, 28, 169}, - seed: "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved", + payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, + accountType: 0, + accountAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + seed: "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved", }, want: []byte{42, 62, 47, 200, 180, 101, 85, 204, 179, 147, 143, 68, 30, 111, 6, 94, 81, 248, 219, 43, 90, 6, 167, 45, 132, 96, 130, 0, 153, 244, 159, 137, 159, 113, 78, 9, 164, 154, 213, 255, 17, 206, 153, 156, 176, 206, 33, 103, 72, 182, 228, 148, 234, 15, 176, 243, 50, 221, 106, 152, 53, 54, 173, 15}, }, { - name: "Sign:fail-{no account in account table}", - fields: fields{ - Executor: &mockSignatureSignExecutorFail{}, - }, + name: "Sign:valid-{default type}", args: args{ - payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, - accountID: []byte{4, 38, 68, 24, 230, 247, 88, 220, 119, 124, 51, 149, 127, 214, 82, 224, 72, 239, 56, 139, - 255, 81, 229, 184, 77, 80, 80, 39, 254, 173, 28, 169}, - seed: "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved", + payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, + accountType: 1000, + accountAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + seed: "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved", }, - want: nil, + want: []byte{42, 62, 47, 200, 180, 101, 85, 204, 179, 147, 143, 68, 30, 111, 6, 94, 81, 248, 219, 43, 90, 6, 167, + 45, 132, 96, 130, 0, 153, 244, 159, 137, 159, 113, 78, 9, 164, 154, 213, 255, 17, 206, 153, 156, 176, 206, 33, + 103, 72, 182, 228, 148, 234, 15, 176, 243, 50, 221, 106, 152, 53, 54, 173, 15}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &Signature{ - Executor: tt.fields.Executor, - } - got := s.Sign(tt.args.payload, tt.args.accountID, tt.args.seed) + s := &Signature{} + got := s.Sign(tt.args.payload, tt.args.accountType, tt.args.accountAddress, tt.args.seed) if !reflect.DeepEqual(got, tt.want) { t.Errorf("Signature.Sign() = %v, want %v", got, tt.want) } @@ -125,24 +73,17 @@ func TestSignature_Sign(t *testing.T) { } func TestSignature_SignBlock(t *testing.T) { - type fields struct { - Executor *query.Executor - } type args struct { payload []byte nodeSeed string } tests := []struct { - name string - fields fields - args args - want []byte + name string + args args + want []byte }{ { name: "SignBlock:success", - fields: fields{ - Executor: nil, // todo: update when node-registration integrated - }, args: args{ payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, nodeSeed: "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved", @@ -154,9 +95,7 @@ func TestSignature_SignBlock(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &Signature{ - Executor: tt.fields.Executor, - } + s := &Signature{} if got := s.SignBlock(tt.args.payload, tt.args.nodeSeed); !reflect.DeepEqual(got, tt.want) { t.Errorf("Signature.SignBlock() = %v, want %v", got, tt.want) } @@ -165,42 +104,46 @@ func TestSignature_SignBlock(t *testing.T) { } func TestSignature_VerifySignature(t *testing.T) { - type fields struct { - Executor *query.Executor - } type args struct { - payload []byte - signature []byte - accountID []byte + payload []byte + signature []byte + accountType uint32 + accountAddress string } tests := []struct { - name string - fields fields - args args - want bool + name string + args args + want bool }{ { - name: "VerifySignature:success", // todo: add fail:test after account integrated. - fields: fields{ - Executor: nil, // todo: update this after account integrated + name: "VerifySignature:success", + args: args{ + payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, + accountType: 0, + accountAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + signature: []byte{42, 62, 47, 200, 180, 101, 85, 204, 179, 147, 143, 68, 30, 111, 6, 94, 81, 248, 219, 43, 90, 6, 167, + 45, 132, 96, 130, 0, 153, 244, 159, 137, 159, 113, 78, 9, 164, 154, 213, 255, 17, 206, 153, 156, 176, 206, 33, + 103, 72, 182, 228, 148, 234, 15, 176, 243, 50, 221, 106, 152, 53, 54, 173, 15}, }, + want: true, + }, + { + name: "VerifySignature:success-{default}", args: args{ - payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, + payload: []byte{12, 43, 65, 65, 12, 123, 43, 12, 1, 24, 5, 5, 12, 54}, + accountType: 10000, + accountAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", signature: []byte{42, 62, 47, 200, 180, 101, 85, 204, 179, 147, 143, 68, 30, 111, 6, 94, 81, 248, 219, 43, 90, 6, 167, 45, 132, 96, 130, 0, 153, 244, 159, 137, 159, 113, 78, 9, 164, 154, 213, 255, 17, 206, 153, 156, 176, 206, 33, 103, 72, 182, 228, 148, 234, 15, 176, 243, 50, 221, 106, 152, 53, 54, 173, 15}, - accountID: []byte{4, 38, 68, 24, 230, 247, 88, 220, 119, 124, 51, 149, 127, 214, 82, 224, 72, 239, 56, 139, - 255, 81, 229, 184, 77, 80, 80, 39, 254, 173, 28, 169}, }, want: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := &Signature{ - Executor: tt.fields.Executor, - } - if got := s.VerifySignature(tt.args.payload, tt.args.signature, tt.args.accountID); got != tt.want { + s := &Signature{} + if got := s.VerifySignature(tt.args.payload, tt.args.signature, tt.args.accountType, tt.args.accountAddress); got != tt.want { t.Errorf("Signature.VerifySignature() = %v, want %v", got, tt.want) } }) From a0d45b833bc9ac9c8038f3b1f701db2b057f9e49 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 09:55:49 +0800 Subject: [PATCH 11/17] #55 update send money test --- common/transaction/sendMoney_test.go | 123 +++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/common/transaction/sendMoney_test.go b/common/transaction/sendMoney_test.go index 76b19204c..f50e5eb65 100644 --- a/common/transaction/sendMoney_test.go +++ b/common/transaction/sendMoney_test.go @@ -2,6 +2,7 @@ package transaction import ( "database/sql" + "errors" "regexp" "testing" @@ -28,6 +29,22 @@ type ( executorApplySuccess struct { executorValidateSuccess } + + executorGenesisSuccess struct { + query.Executor + } + + executorGenesisSuccessCreateAccount struct { + executorGenesisSuccess + } + + executorGenesisFail struct { + executorGenesisSuccessCreateAccount + } + + executorGenesisFailAddBalance struct { + executorGenesisSuccess + } ) func (*executorApplySuccess) ExecuteTransactionStatements(queries map[*string][]interface{}) ([]sql.Result, error) { @@ -153,6 +170,44 @@ func (*executorAccountCountSuccess) ExecuteSelect(qStr string, args ...interface return db.Query(qStr, 1) } +func (*executorGenesisSuccess) ExecuteSelect(qStr string, args ...interface{}) (*sql.Rows, error) { + db, mock, err := sqlmock.New() + if err != nil { + return nil, err + } + defer db.Close() + + mock.ExpectQuery(regexp.QuoteMeta(qStr)).WithArgs(args[0]).WillReturnRows(sqlmock.NewRows([]string{ + "AccountID", "AccountType", "AccountAddress"}, + ).AddRow([]byte{}, 0, "")) + return db.Query(qStr, args[0]) +} + +func (*executorGenesisSuccess) ExecuteTransactionStatements(queries map[*string][]interface{}) ([]sql.Result, error) { + return nil, nil +} + +func (*executorGenesisSuccessCreateAccount) ExecuteSelect(qStr string, args ...interface{}) (*sql.Rows, error) { + db, mock, err := sqlmock.New() + if err != nil { + return nil, err + } + defer db.Close() + + mock.ExpectQuery(regexp.QuoteMeta(qStr)).WithArgs(args[0]).WillReturnRows(sqlmock.NewRows([]string{ + "AccountID", "AccountType", "AccountAddress"}, + )) + return db.Query(qStr, args[0]) +} + +func (*executorGenesisFail) ExecuteTransactionStatements(queries map[*string][]interface{}) ([]sql.Result, error) { + return nil, errors.New("mockedError") +} + +func (*executorGenesisFailAddBalance) ExecuteTransactionStatements(queries map[*string][]interface{}) ([]sql.Result, error) { + return nil, errors.New("mockedError") +} + func TestSendMoney_Validate(t *testing.T) { type fields struct { Body *model.SendMoneyTransactionBody @@ -456,6 +511,74 @@ func TestSendMoney_ApplyConfirmed(t *testing.T) { }, wantErr: true, }, + { + name: "wantSuccess:genesis-{genesis-sender-exist}", + fields: fields{ + Body: &model.SendMoneyTransactionBody{ + Amount: 10, + }, + Height: 0, + SenderAccountType: 0, + SenderAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + RecipientAccountType: 0, + RecipientAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + AccountQuery: query.NewAccountQuery(), + AccountBalanceQuery: query.NewAccountBalanceQuery(), + QueryExecutor: &executorGenesisSuccess{}, + }, + wantErr: false, + }, + { + name: "wantSuccess:genesis-{genesis-sender-not-exist, create genesis}", + fields: fields{ + Body: &model.SendMoneyTransactionBody{ + Amount: 10, + }, + Height: 0, + SenderAccountType: 0, + SenderAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + RecipientAccountType: 0, + RecipientAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + AccountQuery: query.NewAccountQuery(), + AccountBalanceQuery: query.NewAccountBalanceQuery(), + QueryExecutor: &executorGenesisSuccessCreateAccount{}, + }, + wantErr: false, + }, + { + name: "wantFail:genesis-{genesis-sender-not-exist, create genesis fail}", + fields: fields{ + Body: &model.SendMoneyTransactionBody{ + Amount: 10, + }, + Height: 0, + SenderAccountType: 0, + SenderAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + RecipientAccountType: 0, + RecipientAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + AccountQuery: query.NewAccountQuery(), + AccountBalanceQuery: query.NewAccountBalanceQuery(), + QueryExecutor: &executorGenesisFail{}, + }, + wantErr: true, + }, + { + name: "wantFail:genesis-{genesis add balance fail}", + fields: fields{ + Body: &model.SendMoneyTransactionBody{ + Amount: 10, + }, + Height: 0, + SenderAccountType: 0, + SenderAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + RecipientAccountType: 0, + RecipientAddress: "BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE", + AccountQuery: query.NewAccountQuery(), + AccountBalanceQuery: query.NewAccountBalanceQuery(), + QueryExecutor: &executorGenesisFailAddBalance{}, + }, + wantErr: true, + }, { name: "wantSuccess:Create", fields: fields{ From cad84e99ebcbb7d3c51bf747bc2291c5163745af Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 09:56:34 +0800 Subject: [PATCH 12/17] #55 add new method to account util --- common/util/account.go | 15 +++++++ common/util/account_test.go | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/common/util/account.go b/common/util/account.go index 5d18174a9..fa75fd8d8 100644 --- a/common/util/account.go +++ b/common/util/account.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/binary" "errors" + "fmt" "golang.org/x/crypto/ed25519" @@ -71,6 +72,20 @@ func GetAddressFromPublicKey(publicKey []byte) (string, error) { return address, nil } +// GetPublicKeyFromAddress Get the raw public key from a formatted address +func GetPublicKeyFromAddress(address string) ([]byte, error) { + // decode base64 back to byte + publicKey, err := base64.URLEncoding.DecodeString(address) + if err != nil { + return nil, err + } + // Needs to check the checksum bit at the end, and if valid, + if publicKey[32] != GetChecksumByte(publicKey[:32]) { + return nil, fmt.Errorf("address checksum failed") + } + return publicKey[:32], nil +} + // GetChecksumByte Calculate a checksum byte from a collection of bytes // checksum 255 = 255, 256 = 0, 257 = 1 and so on. func GetChecksumByte(bytes []byte) byte { diff --git a/common/util/account_test.go b/common/util/account_test.go index 878753224..318e2755e 100644 --- a/common/util/account_test.go +++ b/common/util/account_test.go @@ -152,3 +152,82 @@ func TestGetAddressFromPublicKey(t *testing.T) { }) } } + +func TestGetPublicKeyFromAddress(t *testing.T) { + type args struct { + address string + } + tests := []struct { + name string + args args + want []byte + wantErr bool + }{ + { + name: "GetPublicKeyFromAddress:success", + args: args{ + address: "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgtN", + }, + want: []byte{4, 38, 103, 73, 250, 169, 63, 155, 106, 21, 9, 76, 77, 137, 3, 120, 21, 69, 90, 118, 242, + 84, 174, 239, 46, 190, 78, 68, 90, 83, 142, 11}, + wantErr: false, + }, + { + name: "GetPublicKeyFromAddress:fail-{decode error, wrong address format/length}", + args: args{ + address: "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgt", + }, + want: nil, + wantErr: true, + }, + { + name: "GetPublicKeyFromAddress:fail-{checksum error, wrong address format}", + args: args{ + address: "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgtM", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetPublicKeyFromAddress(tt.args.address) + if (err != nil) != tt.wantErr { + t.Errorf("GetPublicKeyFromAddress() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetPublicKeyFromAddress() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCreateAccountIDFromAddress(t *testing.T) { + type args struct { + accountType uint32 + address string + } + tests := []struct { + name string + args args + want []byte + }{ + { + name: "CreateAccountIDFromAddress:success", + args: args{ + accountType: 0, + address: "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgtN", + }, + want: []byte{136, 106, 141, 253, 44, 34, 145, 81, 166, 229, 33, 209, 150, 188, 204, 28, 239, 33, 152, 158, 4, 187, + 13, 109, 173, 223, 169, 232, 50, 200, 169, 25}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := CreateAccountIDFromAddress(tt.args.accountType, tt.args.address); !reflect.DeepEqual(got, tt.want) { + t.Errorf("CreateAccountIDFromAddress() = %v, want %v", got, tt.want) + } + }) + } +} From 9c2d9aea762a9985df694979b105daf7dfeaee41 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 09:57:00 +0800 Subject: [PATCH 13/17] #55 add missing small test --- common/util/convert_test.go | 27 +++++++++++++++++++++++++++ common/util/loadConfig_test.go | 9 +++++++++ 2 files changed, 36 insertions(+) diff --git a/common/util/convert_test.go b/common/util/convert_test.go index 579dc3d2d..3ef5a2fb1 100644 --- a/common/util/convert_test.go +++ b/common/util/convert_test.go @@ -243,3 +243,30 @@ func TestConvertIntToBytes(t *testing.T) { }) } } + +func TestConvertStringToBytes(t *testing.T) { + type args struct { + str string + } + tests := []struct { + name string + args args + want []byte + }{ + { + name: "ConvertStringToBytes:success", + args: args{ + str: "dummy random string here", + }, + want: []byte{24, 0, 0, 0, 100, 117, 109, 109, 121, 32, 114, 97, 110, 100, 111, 109, 32, 115, 116, 114, 105, 110, 103, 32, + 104, 101, 114, 101}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ConvertStringToBytes(tt.args.str); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ConvertStringToBytes() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/common/util/loadConfig_test.go b/common/util/loadConfig_test.go index db474ece5..265ca74bc 100644 --- a/common/util/loadConfig_test.go +++ b/common/util/loadConfig_test.go @@ -32,6 +32,15 @@ func TestLoadConfig(t *testing.T) { }, wantErr: true, }, + { + name: "MustError:{len path, name, or extension < 1}", + args: args{ + path: "", + name: "", + extension: "", + }, + wantErr: true, + }, } for _, tt := range tests { From 063528a2f5eaa990ecb88fdf9a062aacb7b52e77 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 09:57:36 +0800 Subject: [PATCH 14/17] #55 update signature instantiation --- core/service/blockCoreService.go | 2 +- main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/service/blockCoreService.go b/core/service/blockCoreService.go index f88705ee4..e8cc80601 100644 --- a/core/service/blockCoreService.go +++ b/core/service/blockCoreService.go @@ -135,7 +135,7 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block) error { transactions := block.GetTransactions() if len(transactions) > 0 { for _, tx := range block.GetTransactions() { - err := transaction.GetTransactionType(tx, bs.QueryExecutor).ApplyConfirmed() + err := transaction.GetTransactionType(tx, bs.QueryExecutor).ApplyConfirmed() // todo: make this mockable if err == nil { tx.BlockID = block.ID tx.Height = block.Height diff --git a/main.go b/main.go index 0c048ef78..7283ed48b 100644 --- a/main.go +++ b/main.go @@ -81,7 +81,7 @@ func main() { blockchainProcessor := smith.NewBlockchainProcessor(mainchain, smith.NewBlocksmith(nodeSecretPhrase), service.NewBlockService(mainchain, query.NewQueryExecutor(db), query.NewBlockQuery(mainchain), - query.NewMempoolQuery(mainchain), query.NewTransactionQuery(mainchain), crypto.NewSignature(queryExecutor)), + query.NewMempoolQuery(mainchain), query.NewTransactionQuery(mainchain), crypto.NewSignature()), service.NewMempoolService(mainchain, query.NewQueryExecutor(db), query.NewMempoolQuery(mainchain))) if !blockchainProcessor.CheckGenesis() { // Add genesis if not exist _ = blockchainProcessor.AddGenesis() From 538304456d64b2e25dae165a73980d671fc9c4b4 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 11:09:47 +0800 Subject: [PATCH 15/17] #55 fix mempool query wrong field name --- common/query/mempoolQuery.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/query/mempoolQuery.go b/common/query/mempoolQuery.go index 0f682869b..0b0349743 100644 --- a/common/query/mempoolQuery.go +++ b/common/query/mempoolQuery.go @@ -30,7 +30,7 @@ type ( func NewMempoolQuery(chaintype contract.ChainType) *MempoolQuery { return &MempoolQuery{ Fields: []string{ - "ID", "FeePerByte", "ArrivalTimestamp", "TransactionBytes", + "id", "fee_per_byte", "arrival_timestamp", "transaction_bytes", }, TableName: "mempool", ChainType: chaintype, From 3de1d597ae9bbae98d6ba0bdd478dd58cbd0938b Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 11:19:58 +0800 Subject: [PATCH 16/17] #55 fix mempool query wrong field name --- core/service/mempoolCoreService_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/service/mempoolCoreService_test.go b/core/service/mempoolCoreService_test.go index 88677783c..853d5cceb 100644 --- a/core/service/mempoolCoreService_test.go +++ b/core/service/mempoolCoreService_test.go @@ -21,14 +21,14 @@ type mockMempoolQueryExecutorSuccess struct { query.Executor } -var getTxByIDQuery = "SELECT ID, FeePerByte, ArrivalTimestamp, TransactionBytes FROM mempool WHERE id = :id" +var getTxByIDQuery = "SELECT id, fee_per_byte, arrival_timestamp, transaction_bytes FROM mempool WHERE id = :id" func (*mockMempoolQueryExecutorSuccess) ExecuteSelect(qe string, args ...interface{}) (*sql.Rows, error) { db, mock, _ := sqlmock.New() defer db.Close() switch qe { - case "SELECT ID, FeePerByte, ArrivalTimestamp, TransactionBytes FROM mempool": - mockedRows := sqlmock.NewRows([]string{"ID", "FeePerByte", "ArrivalTimestamp", "TransactionBytes"}) + case "SELECT id, fee_per_byte, arrival_timestamp, transaction_bytes FROM mempool": + mockedRows := sqlmock.NewRows([]string{"id", "fee_per_byte", "arrival_timestamp", "transaction_bytes"}) mockedRows.AddRow(1, 1, 1562893305, getTestSignedMempoolTransaction(1, 1562893305).TransactionBytes) mockedRows.AddRow(2, 10, 1562893304, getTestSignedMempoolTransaction(2, 1562893304).TransactionBytes) mockedRows.AddRow(3, 1, 1562893302, getTestSignedMempoolTransaction(3, 1562893302).TransactionBytes) @@ -58,7 +58,7 @@ func (*mockMempoolQueryExecutorFail) ExecuteSelect(qe string, args ...interface{ // before adding mempool transactions to db we check for duplicate transactions case getTxByIDQuery: mock.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(sqlmock.NewRows([]string{ - "ID", "FeePerByte", "ArrivalTimestamp", "TransactionBytes"}, + "id", "fee_per_byte", "arrival_timestamp", "transaction_bytes"}, ).AddRow(3, 1, 1562893302, []byte{})) default: return nil, errors.New("MockedError") From 355ef7035e0d05a2e1010c29481d78f2c5d9a707 Mon Sep 17 00:00:00 2001 From: andy-shi88 Date: Thu, 18 Jul 2019 13:24:39 +0800 Subject: [PATCH 17/17] #55 update unconfirmed to spendable --- common/query/accountBalanceQuery.go | 4 ++-- common/transaction/sendMoney.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/query/accountBalanceQuery.go b/common/query/accountBalanceQuery.go index c66ad2b90..d4f45c03a 100644 --- a/common/query/accountBalanceQuery.go +++ b/common/query/accountBalanceQuery.go @@ -20,7 +20,7 @@ type ( UpdateAccountBalance(fields, causedFields map[string]interface{}) (str string, args []interface{}) InsertAccountBalance(accountBalance *model.AccountBalance) (str string, args []interface{}) AddAccountBalance(balance int64, causedFields map[string]interface{}) (str string, args []interface{}) - AddAccountUnconfirmedBalance(balance int64, causedFields map[string]interface{}) (str string, args []interface{}) + AddAccountSpendableBalance(balance int64, causedFields map[string]interface{}) (str string, args []interface{}) } ) @@ -51,7 +51,7 @@ func (q *AccountBalanceQuery) AddAccountBalance(balance int64, causedFields map[ q.TableName, balance, balance), []interface{}{causedFields["account_id"]} } -func (q *AccountBalanceQuery) AddAccountUnconfirmedBalance(balance int64, causedFields map[string]interface{}) ( +func (q *AccountBalanceQuery) AddAccountSpendableBalance(balance int64, causedFields map[string]interface{}) ( str string, args []interface{}) { return fmt.Sprintf("UPDATE %s SET spendable_balance = spendable_balance + (%d) WHERE account_id = ?", q.TableName, balance), []interface{}{causedFields["account_id"]} diff --git a/common/transaction/sendMoney.go b/common/transaction/sendMoney.go index 1a8d9ce44..84d7f81cf 100644 --- a/common/transaction/sendMoney.go +++ b/common/transaction/sendMoney.go @@ -147,7 +147,7 @@ func (tx *SendMoney) ApplyUnconfirmed() error { } // update sender - accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.AddAccountUnconfirmedBalance( + accountBalanceSenderQ, accountBalanceSenderQArgs := tx.AccountBalanceQuery.AddAccountSpendableBalance( -tx.Body.Amount, map[string]interface{}{ "account_id": util.CreateAccountIDFromAddress(