This repository was archived by the owner on Aug 18, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 631
/
Copy pathBHelpers.hs
171 lines (156 loc) · 6.21 KB
/
BHelpers.hs
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- | Definition of 'BlockchainHelpers' for the main blockchain.
--
-- FIXME rename this module to something to do with verification.
module Pos.Chain.Block.BHelpers
( verifyBlockHeader
, verifyBlock
, verifyGenesisBlock
, verifyMainBlock
, verifyMainBody
, verifyMainBlockHeader
, verifyMainConsensusData
, verifyMainExtraHeaderData
) where
import Universum
import Control.Monad.Except (MonadError (throwError))
import Pos.Binary.Class (Bi)
import Pos.Chain.Block.Blockchain (Blockchain (..), GenericBlock (..),
GenericBlockHeader (..), gbExtra)
import Pos.Chain.Block.Main (MainBody (..), MainExtraHeaderData (..),
MainProof)
import Pos.Chain.Block.Union (Block, BlockHeader (..),
BlockSignature (..), GenesisBlockchain, MainBlockchain,
MainConsensusData (..), MainToSign (..),
mainBlockEBDataProof)
import Pos.Chain.Ssc (verifySscPayload)
import Pos.Core.Configuration (HasProtocolConstants)
import Pos.Core.Delegation (LightDlgIndices (..), checkDlgPayload)
import Pos.Core.Slotting (SlotId (..))
import Pos.Core.Ssc (checkSscPayload)
import Pos.Core.Txp (checkTxPayload)
import Pos.Core.Update (checkSoftwareVersion, checkUpdatePayload)
import Pos.Crypto (ProtocolMagic, ProxySignature (..), SignTag (..),
checkSig, hash, isSelfSignedPsk, proxyVerify)
import Pos.Util.Some (Some (Some))
-- | Verify a BlockHeader in isolation. There is nothing to be done for
-- genesis headers.
verifyBlockHeader
:: MonadError Text m
=> ProtocolMagic
-> BlockHeader
-> m ()
verifyBlockHeader _ (BlockHeaderGenesis _) = pure ()
verifyBlockHeader pm (BlockHeaderMain bhm) = verifyMainBlockHeader pm bhm
-- | Verify a Block in isolation.
verifyBlock
:: ( MonadError Text m
, HasProtocolConstants
)
=> ProtocolMagic
-> Block
-> m ()
verifyBlock pm = either verifyGenesisBlock (verifyMainBlock pm)
-- | To verify a genesis block we only have to check the body proof.
verifyGenesisBlock
:: ( MonadError Text m )
=> GenericBlock GenesisBlockchain
-> m ()
verifyGenesisBlock UnsafeGenericBlock {..} =
checkBodyProof @GenesisBlockchain _gbBody (_gbhBodyProof _gbHeader)
verifyMainBlock
:: ( MonadError Text m
, Bi MainProof
, HasProtocolConstants
)
=> ProtocolMagic
-> GenericBlock MainBlockchain
-> m ()
verifyMainBlock pm block@UnsafeGenericBlock {..} = do
verifyMainBlockHeader pm _gbHeader
verifyMainBody pm _gbBody
-- No need to verify the main extra body data. It's an 'Attributes ()'
-- which is valid whenever it's well-formed.
--
-- Check internal consistency: the body proofs are all correct.
checkBodyProof @MainBlockchain _gbBody (_gbhBodyProof _gbHeader)
-- Check that the headers' extra body data hash is correct.
-- This isn't subsumed by the body proof check.
unless (hash (block ^. gbExtra) == (block ^. mainBlockEBDataProof)) $
throwError "Hash of extra body data is not equal to its representation in the header."
-- Ssc and Dlg consistency checks which require the header, and so can't
-- be done in 'verifyMainBody'.
either (throwError . pretty) pure $
verifySscPayload
pm
(Right (Some _gbHeader))
(_mbSscPayload _gbBody)
-- | Verify the body of a block. There are no internal consistency checks,
-- it's just a verification of its sub-components (payloads).
verifyMainBody
:: MonadError Text m
=> ProtocolMagic
-> MainBody
-> m ()
verifyMainBody pm MainBody {..} = do
checkTxPayload _mbTxPayload
checkSscPayload pm _mbSscPayload
checkDlgPayload pm _mbDlgPayload
checkUpdatePayload pm _mbUpdatePayload
-- | Verify a main block header in isolation.
verifyMainBlockHeader
:: MonadError Text m
=> ProtocolMagic
-> GenericBlockHeader MainBlockchain
-> m ()
verifyMainBlockHeader pm UnsafeGenericBlockHeader {..} = do
-- Previous header hash is always valid.
-- Body proof is just a bunch of hashes, which is always valid (although
-- must be checked against the actual body, in verifyMainBlock.
-- Consensus data and extra header data require validation.
verifyMainConsensusData _gbhConsensus
verifyMainExtraHeaderData _gbhExtra
-- Internal consistency: is the signature in the consensus data really for
-- this block?
unless (verifyBlockSignature _mcdSignature) $
throwError "can't verify signature"
where
verifyBlockSignature (BlockSignature sig) =
checkSig pm SignMainBlock leaderPk signature sig
verifyBlockSignature (BlockPSignatureLight proxySig) =
proxyVerify
pm
SignMainBlockLight
proxySig
(\(LightDlgIndices (epochLow, epochHigh)) ->
epochLow <= epochId && epochId <= epochHigh)
signature
verifyBlockSignature (BlockPSignatureHeavy proxySig) =
proxyVerify pm SignMainBlockHeavy proxySig (const True) signature
signature = MainToSign _gbhPrevBlock _gbhBodyProof slotId difficulty _gbhExtra
epochId = siEpoch slotId
MainConsensusData
{ _mcdLeaderKey = leaderPk
, _mcdSlot = slotId
, _mcdDifficulty = difficulty
, ..
} = _gbhConsensus
-- | Verify the consensus data in isolation.
verifyMainConsensusData
:: ( MonadError Text m )
=> MainConsensusData
-> m ()
verifyMainConsensusData MainConsensusData {..} = do
when (selfSignedProxy _mcdSignature) $
throwError "can't use self-signed psk to issue the block"
where
selfSignedProxy (BlockSignature _) = False
selfSignedProxy (BlockPSignatureLight (psigPsk -> psk)) = isSelfSignedPsk psk
selfSignedProxy (BlockPSignatureHeavy (psigPsk -> psk)) = isSelfSignedPsk psk
verifyMainExtraHeaderData
:: ( MonadError Text m )
=> ExtraHeaderData MainBlockchain
-> m ()
verifyMainExtraHeaderData MainExtraHeaderData {..} = do
checkSoftwareVersion _mehSoftwareVersion