forked from aergoio/aergo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
blockvalidator.go
129 lines (105 loc) · 3.34 KB
/
blockvalidator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @file
* @copyright defined in aergo/LICENSE.txt
*/
package chain
import (
"bytes"
"errors"
"github.com/aergoio/aergo/internal/enc"
"github.com/aergoio/aergo/state"
"github.com/aergoio/aergo/types"
)
type BlockValidator struct {
signVerifier *SignVerifier
sdb *state.ChainStateDB
}
var (
ErrorBlockVerifySign = errors.New("Block verify failed, because Tx sign is invalid")
ErrorBlockVerifyTxRoot = errors.New("Block verify failed, because Tx root hash is invaild")
ErrorBlockVerifyStateRoot = errors.New("Block verify failed, because state root hash is not equal")
)
func NewBlockValidator(sdb *state.ChainStateDB) *BlockValidator {
bv := BlockValidator{
signVerifier: NewSignVerifier(DefaultVerifierCnt),
sdb: sdb,
}
logger.Debug().Msg("started signverifier")
return &bv
}
func (bv *BlockValidator) Stop() {
bv.signVerifier.Stop()
}
func (bv *BlockValidator) ValidateBlock(block *types.Block) error {
if err := bv.ValidateHeader(block.GetHeader()); err != nil {
return err
}
if err := bv.ValidateBody(block); err != nil {
return err
}
return nil
}
func (bv *BlockValidator) ValidateHeader(header *types.BlockHeader) error {
// TODO : more field?
// Block, State not exsit
// MaxBlockSize
// MaxHeaderSize
// ChainVersion
// StateRootHash
if bv.sdb.IsExistState(header.GetBlocksRootHash()) {
return ErrorBlockVerifyStateRoot
}
return nil
}
func (bv *BlockValidator) ValidateBody(block *types.Block) error {
txs := block.GetBody().GetTxs()
// TxRootHash
logger.Debug().Int("Txlen", len(txs)).Str("TxRoot", enc.ToString(block.GetHeader().GetTxsRootHash())).
Msg("tx root verify")
computeTxRootHash := types.CalculateTxsRootHash(txs)
if bytes.Equal(block.GetHeader().GetTxsRootHash(), computeTxRootHash) == false {
logger.Error().Str("block", block.ID()).
Str("txroot", enc.ToString(block.GetHeader().GetTxsRootHash())).
Str("compute txroot", enc.ToString(computeTxRootHash)).
Msg("tx root validation failed")
return ErrorBlockVerifyTxRoot
}
// check Tx sign
if len(txs) == 0 {
return nil
}
failed, _ := bv.signVerifier.VerifyTxs(&types.TxList{Txs: txs})
if failed {
logger.Error().Str("block", block.ID()).Msg("sign of txs validation failed")
return ErrorBlockVerifySign
}
return nil
}
func (bv *BlockValidator) ValidatePost(sdbRoot []byte, receipts types.Receipts, block *types.Block) error {
hdrRoot := block.GetHeader().GetBlocksRootHash()
if !bytes.Equal(hdrRoot, sdbRoot) {
logger.Error().Str("block", block.ID()).
Str("hdrroot", enc.ToString(hdrRoot)).
Str("sdbroot", enc.ToString(sdbRoot)).
Msg("block root hash validation failed")
return ErrorBlockVerifySign
}
logger.Debug().Str("block", block.ID()).
Str("hdrroot", enc.ToString(hdrRoot)).
Str("sdbroot", enc.ToString(sdbRoot)).
Msg("block root hash validation succeed")
hdrRoot = block.GetHeader().ReceiptsRootHash
receiptsRoot := receipts.MerkleRoot()
if !bytes.Equal(hdrRoot, receiptsRoot) {
logger.Error().Str("block", block.ID()).
Str("hdrroot", enc.ToString(hdrRoot)).
Str("receipts_root", enc.ToString(receiptsRoot)).
Msg("receipts root hash validation failed")
return ErrorBlockVerifySign
}
logger.Debug().Str("block", block.ID()).
Str("hdrroot", enc.ToString(hdrRoot)).
Str("receipts_root", enc.ToString(receiptsRoot)).
Msg("receipt root hash validation succeed")
return nil
}