cranberry

Форк
0
/
validator_service.go 
128 строк · 3.7 Кб
1
package services
2

3
import (
4
	"crypto/ecdsa"
5
	"strings"
6

7
	"gitverse.ru/IvanTimofeev/cranberry/internal/db"
8
	"gitverse.ru/IvanTimofeev/cranberry/internal/log"
9
	"gitverse.ru/IvanTimofeev/cranberry/internal/merkle"
10
	pbapi "gitverse.ru/IvanTimofeev/cranberry/pkg/grpc"
11
	utility "gitverse.ru/IvanTimofeev/cranberry/pkg/utility"
12
	"go.uber.org/zap"
13
)
14

15
type ValidatorService struct {
16
	db            *db.Db
17
	logger        *zap.SugaredLogger
18
	privKey       *ecdsa.PrivateKey
19
	validatorAddr string
20
}
21

22
func NewValidatorService(db *db.Db, seed string) *ValidatorService {
23
	logger := log.GetLogger()
24
	privKey, err := utility.GeneratePrivKeyBySeed(seed)
25
	if err != nil {
26
		logger.Fatal("Error generate private key", zap.Error(err))
27
	}
28
	validatorAddr := utility.GetAddrFromPubKey(utility.PubKeyToBytes(&privKey.PublicKey))
29
	logger.Infof("validator id = %s", validatorAddr)
30
	return &ValidatorService{
31
		db:            db,
32
		logger:        logger,
33
		privKey:       privKey,
34
		validatorAddr: validatorAddr,
35
	}
36
}
37

38
func (vs *ValidatorService) ValidateBlock(bc *pbapi.BlockContainer) (bool, error) {
39
	hash := utility.BlockHeaderToHash(bc.Header)
40
	if !strings.EqualFold(hash, bc.Hash) {
41
		log.GetLogger().Warnf("invalid block hash: expected %v, actual %v", hash, bc.Hash)
42
		return false, nil
43
	}
44
	height, ok, err := vs.db.GetUint64Param(LAST_BLOCK_HEIGHT_PARAM_NAME)
45
	if err != nil {
46
		return false, err
47
	}
48
	if !ok {
49
		return false, nil
50
	}
51
	if height+1 != bc.Header.Height {
52
		log.GetLogger().Warnf("invalid block height: expected %v, actual %v", height, bc.Header.Height)
53
		return false, nil
54
	}
55
	merkleRoot := merkle.MerkleRoot(bc.Txs)
56
	if !strings.EqualFold(merkleRoot, bc.Header.MerkleRoot) {
57
		log.GetLogger().Warnf("invalid block merkle: expected %v, actual %v", merkleRoot, bc.Header.MerkleRoot)
58
		return false, nil
59
	}
60
	for order, txc := range bc.Txs {
61
		verified, err := vs.ValidateTx(txc)
62
		if err != nil {
63
			return false, err
64
		}
65
		if !verified {
66
			return false, nil
67
		}
68
		if txc.OrderInBlock == nil || uint64(order) != *txc.OrderInBlock {
69
			log.GetLogger().Warnf("invalid order in block for tx with hash = %v: expected %v, actual %v",
70
				txc.Hash, order, txc.OrderInBlock)
71
			return false, nil
72
		}
73
		return true, nil
74
	}
75
	for _, s := range bc.ValidatorSignatures {
76
		validator, ok, err := vs.db.GetValidator(s.Addr)
77
		if err != nil {
78
			return false, err
79
		}
80
		if !ok {
81
			log.GetLogger().Warnf("validator id = %v is not found in database", s.Addr)
82
			return false, nil
83
		}
84
		verified := utility.VerifyBlock(utility.BytesToPubKey(validator.PubKey), s.Signature, bc.Header)
85
		if !verified {
86
			log.GetLogger().Warnf("invalid block signature with hash = %s", hash)
87
			return false, nil
88
		}
89
	}
90
	return true, nil
91
}
92

93
func (vs *ValidatorService) ValidateTx(txc *pbapi.TxContainer) (bool, error) {
94
	hash := utility.TxToHash(txc.Tx)
95
	if !strings.EqualFold(hash, txc.Hash) {
96
		log.GetLogger().Warnf("invalid tx hash: expected %v, actual %v", hash, txc.Hash)
97
		return false, nil
98
	}
99

100
	verified := utility.VerifyTx(utility.BytesToPubKey(txc.PubKey), txc)
101
	if !verified {
102
		log.GetLogger().Warnf("invalid tx signature with hash = %s", string(hash))
103
		return false, nil
104
	}
105
	from := utility.GetAddrFromPubKey(txc.PubKey)
106
	fromAcc, ok, err := vs.db.GetAccount(from)
107
	if err != nil {
108
		return false, nil
109
	}
110
	if !ok {
111
		log.GetLogger().Warnf("account with address = %s is not found in database", from)
112
		return false, nil
113
	}
114
	if fromAcc.Balance-txc.Tx.Amount < 0 {
115
		log.GetLogger().Warnf("insufficient funds for account with id = %s. Current balance = %d, tx amount = %d",
116
			from, fromAcc.Balance, txc.Tx.Amount)
117
		return false, nil
118
	}
119
	return true, nil
120
}
121

122
func (vs *ValidatorService) GetValidatorAddr() string {
123
	return vs.validatorAddr
124
}
125

126
func (vs *ValidatorService) GetPrivKey() *ecdsa.PrivateKey {
127
	return vs.privKey
128
}
129

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.