Source file consensus_helpers.ml
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
172
173
174
175
176
177
178
179
180
181
182
open Protocol
open Alpha_context
type mode = Application | Construction | Mempool
let show_mode = function
| Application -> "Application"
| Construction -> "Construction"
| Mempool -> "Mempool"
type kind = Preattestation | Attestation
(** Craft an attestation or preattestation, and bake a block
containing it (in application or construction modes) or inject it
into a mempool. When [error] is [None], check that it succeeds,
otherwise check that it fails as specified by [error].
By default, the (pre)attestation is for the first slot and is
signed by the delegate that owns this slot. Moreover, the operation
points to the given [attested_block]: in other words, it has that
block's level, round, payload hash, and its branch is the
predecessor of that block. Optional arguments allow to override
these default parameters.
The [predecessor] is used as the predecessor of the baked block or
the head of the mempool. When it is not provided, we use the
[attested_block] for this. *)
let test_consensus_operation ?delegate ?slot ?level ?round ?block_payload_hash
?branch ~attested_block ?(predecessor = attested_block) ?error ~loc kind
mode =
let open Lwt_result_syntax in
let* operation =
match kind with
| Preattestation ->
Op.preattestation
?delegate
?slot
?level
?round
?block_payload_hash
?branch
attested_block
| Attestation ->
Op.attestation
?delegate
?slot
?level
?round
?block_payload_hash
?branch
attested_block
in
let check_error res =
match error with
| Some error -> Assert.proto_error ~loc res error
| None ->
let*? _ = res in
return_unit
in
match mode with
| Application ->
Block.bake ~baking_mode:Application ~operation predecessor >>= check_error
| Construction ->
Block.bake ~baking_mode:Baking ~operation predecessor >>= check_error
| Mempool ->
let*! res =
let* inc =
Incremental.begin_construction ~mempool_mode:true predecessor
in
let* inc = Incremental.add_operation inc operation in
Incremental.finalize_block inc
in
check_error res
let test_consensus_operation_all_modes_different_outcomes ?delegate ?slot ?level
?round ?block_payload_hash ?branch ~attested_block ?predecessor ~loc
?application_error ?construction_error ?mempool_error kind =
List.iter_es
(fun (mode, error) ->
test_consensus_operation
?delegate
?slot
?level
?round
?block_payload_hash
?branch
~attested_block
?predecessor
?error
~loc:(Format.sprintf "%s (%s mode)" loc (show_mode mode))
kind
mode)
[
(Application, application_error);
(Construction, construction_error);
(Mempool, mempool_error);
]
let test_consensus_operation_all_modes ?delegate ?slot ?level ?round
?block_payload_hash ?branch ~attested_block ?predecessor ?error ~loc kind =
test_consensus_operation_all_modes_different_outcomes
?delegate
?slot
?level
?round
?block_payload_hash
?branch
~attested_block
?predecessor
~loc
?application_error:error
?construction_error:error
?mempool_error:error
kind
let delegate_of_first_slot b =
let module V = Plugin.RPC.Validators in
Context.get_attesters b >|=? function
| {V.consensus_key; slots = s :: _; _} :: _ -> (consensus_key, s)
| _ -> assert false
let delegate_of_slot ?(different_slot = false) slot b =
let module V = Plugin.RPC.Validators in
Context.get_attesters b >|=? fun attesters ->
List.find_map
(function
| {V.consensus_key; slots = s :: _; _}
when if different_slot then not (Slot.equal s slot)
else Slot.equal s slot ->
Some consensus_key
| _ -> None)
attesters
|> function
| None -> assert false
| Some d -> d
let test_consensus_op_for_next ~genesis ~kind ~next =
let dorsement ~attested_block ~delegate =
match kind with
| `Preattestation -> Op.preattestation ~delegate attested_block
| `Attestation -> Op.attestation ~delegate attested_block
in
Block.bake genesis >>=? fun b1 ->
(match next with
| `Level -> Block.bake b1
| `Round -> Block.bake ~policy:(By_round 1) genesis)
>>=? fun b2 ->
Incremental.begin_construction ~mempool_mode:true b1 >>=? fun inc ->
delegate_of_first_slot (B b1) >>=? fun (delegate, slot) ->
dorsement ~attested_block:b1 ~delegate >>=? fun operation ->
Incremental.add_operation inc operation >>=? fun inc ->
delegate_of_slot ~different_slot:true slot (B b2) >>=? fun delegate ->
dorsement ~attested_block:b2 ~delegate >>=? fun operation ->
Incremental.add_operation inc operation >>=? fun (_ : Incremental.t) ->
return_unit