8
"gitverse.ru/IvanTimofeev/cranberry/internal/db"
9
"gitverse.ru/IvanTimofeev/cranberry/internal/errors"
10
"gitverse.ru/IvanTimofeev/cranberry/internal/log"
11
"gitverse.ru/IvanTimofeev/cranberry/internal/merkle"
12
pbapi "gitverse.ru/IvanTimofeev/cranberry/pkg/grpc"
13
utility "gitverse.ru/IvanTimofeev/cranberry/pkg/utility"
16
const LAST_BLOCK_HEIGHT_PARAM_NAME = "last_block_height"
17
const BLOCK_TX_COUNT = 1000
19
type BlockService struct {
20
poolService *PoolService
23
logger *zap.SugaredLogger
24
validatorService *ValidatorService
27
func NewBlockService(poolService *PoolService, db *db.Db,
28
txService *TxService, validatorService *ValidatorService) *BlockService {
30
poolService: poolService,
32
validatorService: validatorService,
34
logger: log.GetLogger(),
38
func (s *BlockService) MakeGenesisBlock(addr string, balance uint64) error {
39
_, ok, err := s.db.GetUint64Param(LAST_BLOCK_HEIGHT_PARAM_NAME)
44
txs := make([]*pbapi.TxContainer, 0, BLOCK_TX_COUNT)
45
genesisBlockHeader := &pbapi.BlockHeader{
46
MerkleRoot: merkle.MerkleRoot(txs),
50
genesisBlockContainer := &pbapi.BlockContainer{
51
Hash: utility.BlockHeaderToHash(genesisBlockHeader),
52
Header: genesisBlockHeader,
54
ValidatorSignatures: []*pbapi.SignatureItem{},
56
err := s.db.RunTransaction(func(dbtx *sql.Tx) error {
57
pubKeyBytes := utility.PubKeyToBytes(&s.validatorService.GetPrivKey().PublicKey)
58
validator := &pbapi.Validator{
59
Addr: s.validatorService.GetValidatorAddr(),
62
return s.db.SaveValidator(validator, dbtx)
67
err = s.db.RunTransaction(func(dbtx *sql.Tx) error {
68
err := s.db.SaveBlock(genesisBlockContainer, dbtx)
72
err = s.db.SaveUint64Param(LAST_BLOCK_HEIGHT_PARAM_NAME, 0, dbtx)
76
err = s.db.SaveAccount(&pbapi.Account{
92
func (s *BlockService) MakeBlock() error {
93
lastBlockHeight, ok, err := s.db.GetUint64Param(LAST_BLOCK_HEIGHT_PARAM_NAME)
98
//собираем транзакции для формирования блока
99
txcs := make([]*pbapi.TxContainer, 0, BLOCK_TX_COUNT)
100
for i := uint64(0); i < BLOCK_TX_COUNT; i++ {
101
if txc, ok := s.poolService.memorypool.ExtractTx(); ok {
102
txc.OrderInBlock = &i
103
txcs = append(txcs, txc)
106
s.logger.Infof("Count of txs = %d", len(txcs))
107
//запрашиваем последний блок
108
lastBlockContainer, _, err := s.db.GetBlockByHeight(lastBlockHeight)
112
newBlockHeader := &pbapi.BlockHeader{
113
MerkleRoot: merkle.MerkleRoot(txcs),
114
PrevHash: lastBlockContainer.Hash,
115
Height: lastBlockHeight + 1,
117
newBlockContainer := &pbapi.BlockContainer{
118
Hash: utility.BlockHeaderToHash(newBlockHeader),
119
Header: newBlockHeader,
121
ValidatorSignatures: []*pbapi.SignatureItem{},
123
signature, err := utility.SignBlock(s.validatorService.GetPrivKey(), newBlockHeader)
127
newBlockContainer.ValidatorSignatures = append(newBlockContainer.ValidatorSignatures,
128
&pbapi.SignatureItem{
129
Addr: s.validatorService.GetValidatorAddr(),
130
Signature: signature,
133
verified, err := s.validatorService.ValidateBlock(newBlockContainer)
138
return errors.BlockInvaliderror(newBlockContainer.Hash)
140
//сохраняем блок, высоту и публичный ключ подписанта
141
err = s.db.RunTransaction(func(dbtx *sql.Tx) error {
142
err := s.db.SaveBlock(newBlockContainer, dbtx)
146
err = s.db.SaveUint64Param(LAST_BLOCK_HEIGHT_PARAM_NAME, newBlockHeader.Height, dbtx)
150
for _, txc := range txcs {
151
// исполняем транзакцию
152
err := s.txService.ExecuteTx(txc, newBlockContainer, dbtx)
166
func (s *BlockService) GetBlockByHeight(height uint64) (*pbapi.BlockContainer, error) {
167
blockConatiner, ok, err := s.db.GetBlockByHeight(height)
174
return blockConatiner, nil
177
func (s *BlockService) GetBlockWithTxsByHeight(height uint64) (*pbapi.BlockContainer, error) {
178
blockConatiner, err := s.GetBlockByHeight(height)
182
txcs, err := s.db.GetAllTxsByBlockHeight(height)
186
blockConatiner.Txs = txcs
187
return blockConatiner, nil
190
func (s BlockService) GetLastBlock() (*pbapi.BlockContainer, error) {