forked from pokt-network/pocket
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblock.go
103 lines (84 loc) · 3.24 KB
/
block.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
package consensus
import (
"log"
"unsafe"
typesCons "github.com/pokt-network/pocket/consensus/types"
"github.com/pokt-network/pocket/shared/codec"
)
func (m *consensusModule) commitBlock(block *typesCons.Block) error {
m.nodeLog(typesCons.CommittingBlock(m.Height, len(block.Transactions)))
// Store the block in the KV store
codec := codec.GetCodec()
blockProtoBytes, err := codec.Marshal(block)
if err != nil {
return err
}
// IMPROVE(olshansky): temporary solution. `ApplyBlock` above applies the
// transactions to the postgres database, and this stores it in the KV store upon commitment.
// Instead of calling this directly, an alternative solution is to store the block metadata in
// the persistence context and have `CommitPersistenceContext` do this under the hood. However,
// additional `Block` metadata will need to be passed through and may change when we merkle the
// state hash.
if err := m.storeBlock(block, blockProtoBytes); err != nil {
return err
}
// Commit and release the context
if err := m.utilityContext.CommitPersistenceContext(); err != nil {
return err
}
m.utilityContext.ReleaseContext()
m.utilityContext = nil
m.lastAppHash = block.BlockHeader.Hash
return nil
}
func (m *consensusModule) storeBlock(block *typesCons.Block, blockProtoBytes []byte) error {
store := m.utilityContext.GetPersistenceContext()
// Store in KV Store
if err := store.StoreBlock(blockProtoBytes); err != nil {
return err
}
// Store in SQL Store
header := block.BlockHeader
if err := store.InsertBlock(uint64(header.Height), header.Hash, header.ProposerAddress, header.QuorumCertificate); err != nil {
return err
}
return nil
}
// TODO: Add unit tests specific to block validation
func (m *consensusModule) validateBlockBasic(block *typesCons.Block) error {
if block == nil && m.Step != NewRound {
return typesCons.ErrNilBlock
}
if block != nil && m.Step == NewRound {
return typesCons.ErrBlockExists
}
if block != nil && unsafe.Sizeof(*block) > uintptr(m.consGenesis.MaxBlockBytes) {
return typesCons.ErrInvalidBlockSize(uint64(unsafe.Sizeof(*block)), m.consGenesis.MaxBlockBytes)
}
// If the current block being processed (i.e. voted on) by consensus is non nil, we need to make
// sure that the data (height, round, step, txs, etc) is the same before we start validating the signatures
if m.Block != nil {
// DISCUSS: The only difference between blocks from one step to another is the QC, so we need
// to determine where/how to validate this
if protoHash(m.Block) != protoHash(block) {
log.Println("[TECHDEBT][ERROR] The block being processed is not the same as that received by the consensus module ")
}
}
return nil
}
// Creates a new Utility context and clears/nullifies any previous contexts if they exist
func (m *consensusModule) refreshUtilityContext() error {
// Catch-all structure to release the previous utility context if it wasn't properly cleaned up.
// Ideally, this should not be called.
if m.utilityContext != nil {
m.nodeLog(typesCons.NilUtilityContextWarning)
m.utilityContext.ReleaseContext()
m.utilityContext = nil
}
utilityContext, err := m.GetBus().GetUtilityModule().NewContext(int64(m.Height))
if err != nil {
return err
}
m.utilityContext = utilityContext
return nil
}