5
5
from typing import Optional
6
6
7
7
import pytest
8
- from chia_rs import G1Element , ProofOfSpace
8
+ from chia_rs import G1Element , PlotSize , ProofOfSpace
9
9
from chia_rs .sized_bytes import bytes32 , bytes48
10
10
from chia_rs .sized_ints import uint8 , uint32
11
11
12
12
from chia ._tests .util .misc import Marks , datacases
13
13
from chia .consensus .default_constants import DEFAULT_CONSTANTS
14
- from chia .types .blockchain_format .proof_of_space import passes_plot_filter , verify_and_get_quality_string
14
+ from chia .types .blockchain_format .proof_of_space import (
15
+ calculate_plot_difficulty ,
16
+ calculate_prefix_bits ,
17
+ passes_plot_filter ,
18
+ verify_and_get_quality_string ,
19
+ )
15
20
16
21
17
22
@dataclass
@@ -27,6 +32,15 @@ class ProofOfSpaceCase:
27
32
marks : Marks = ()
28
33
29
34
35
+ def g1 (key : str ) -> G1Element :
36
+ return G1Element .from_bytes_unchecked (bytes48 .from_hexstr (key ))
37
+
38
+
39
+ def b32 (key : str ) -> bytes32 :
40
+ return bytes32 .from_hexstr (key )
41
+
42
+
43
+ # TODO: todo_v2_plots more test cases
30
44
@datacases (
31
45
ProofOfSpaceCase (
32
46
id = "Neither pool public key nor pool contract puzzle hash" ,
@@ -70,37 +84,57 @@ class ProofOfSpaceCase:
70
84
),
71
85
ProofOfSpaceCase (
72
86
id = "Not passing the plot filter with size 9" ,
73
- pos_challenge = bytes32 . from_hexstr ("08b23cc2844dfb92d2eedaa705a1ce665d571ee753bd81cbb67b92caa6d34722" ),
87
+ pos_challenge = b32 ("08b23cc2844dfb92d2eedaa705a1ce665d571ee753bd81cbb67b92caa6d34722" ),
74
88
plot_size = uint8 (42 ),
75
- pool_public_key = G1Element .from_bytes_unchecked (
76
- bytes48 .from_hexstr (
77
- "b6449c2c68df97c19e884427e42ee7350982d4020571ead08732615ff39bd216bfd630b6460784982bec98b49fea79d0"
78
- )
89
+ pool_public_key = g1 (
90
+ "b6449c2c68df97c19e884427e42ee7350982d4020571ead08732615ff39bd216bfd630b6460784982bec98b49fea79d0"
79
91
),
80
- plot_public_key = G1Element .from_bytes_unchecked (
81
- bytes48 .from_hexstr (
82
- "b17d368f5400230b2b01464807825bf4163c5c159bd7d4465f935912e538ac9fb996dd9a9c479bd8aa6256bdca1fed96"
83
- )
92
+ plot_public_key = g1 (
93
+ "b17d368f5400230b2b01464807825bf4163c5c159bd7d4465f935912e538ac9fb996dd9a9c479bd8aa6256bdca1fed96"
84
94
),
85
95
height = uint32 (5495999 ),
86
96
expected_error = "Did not pass the plot filter" ,
87
97
),
88
98
ProofOfSpaceCase (
89
99
id = "Passing the plot filter with size 8" ,
90
- pos_challenge = bytes32 . from_hexstr ("08b23cc2844dfb92d2eedaa705a1ce665d571ee753bd81cbb67b92caa6d34722" ),
100
+ pos_challenge = b32 ("08b23cc2844dfb92d2eedaa705a1ce665d571ee753bd81cbb67b92caa6d34722" ),
91
101
plot_size = uint8 (42 ),
92
- pool_public_key = G1Element .from_bytes_unchecked (
93
- bytes48 .from_hexstr (
94
- "b6449c2c68df97c19e884427e42ee7350982d4020571ead08732615ff39bd216bfd630b6460784982bec98b49fea79d0"
95
- )
102
+ pool_public_key = g1 (
103
+ "b6449c2c68df97c19e884427e42ee7350982d4020571ead08732615ff39bd216bfd630b6460784982bec98b49fea79d0"
96
104
),
97
- plot_public_key = G1Element .from_bytes_unchecked (
98
- bytes48 .from_hexstr (
99
- "b17d368f5400230b2b01464807825bf4163c5c159bd7d4465f935912e538ac9fb996dd9a9c479bd8aa6256bdca1fed96"
100
- )
105
+ plot_public_key = g1 (
106
+ "b17d368f5400230b2b01464807825bf4163c5c159bd7d4465f935912e538ac9fb996dd9a9c479bd8aa6256bdca1fed96"
101
107
),
102
108
height = uint32 (5496000 ),
103
109
),
110
+ ProofOfSpaceCase (
111
+ id = "v2 plot size 0" ,
112
+ pos_challenge = bytes32 (b"1" * 32 ),
113
+ plot_size = uint8 (0x80 ),
114
+ plot_public_key = G1Element (),
115
+ pool_public_key = G1Element (),
116
+ expected_error = "Plot size is lower than the minimum" ,
117
+ ),
118
+ ProofOfSpaceCase (
119
+ id = "v2 plot size 34" ,
120
+ pos_challenge = bytes32 (b"1" * 32 ),
121
+ plot_size = uint8 (0x80 | 34 ),
122
+ plot_public_key = G1Element (),
123
+ pool_public_key = G1Element (),
124
+ expected_error = "Plot size is higher than the maximum" ,
125
+ ),
126
+ ProofOfSpaceCase (
127
+ id = "Not passing the plot filter v2" ,
128
+ pos_challenge = b32 ("3d29ea79d19b3f7e99ebf764ae53697cbe143603909873946af6ab1ece606861" ),
129
+ plot_size = uint8 (0x80 | 32 ),
130
+ pool_public_key = g1 (
131
+ "b6449c2c68df97c19e884427e42ee7350982d4020571ead08732615ff39bd216bfd630b6460784982bec98b49fea79d0"
132
+ ),
133
+ plot_public_key = g1 (
134
+ "879526b4e7b616cfd64984d8ad140d0798b048392a6f11e2faf09054ef467ea44dc0dab5e5edb2afdfa850c5c8b629cc"
135
+ ),
136
+ expected_error = "Did not pass the plot filter" ,
137
+ ),
104
138
)
105
139
def test_verify_and_get_quality_string (caplog : pytest .LogCaptureFixture , case : ProofOfSpaceCase ) -> None :
106
140
pos = ProofOfSpace (
@@ -114,41 +148,25 @@ def test_verify_and_get_quality_string(caplog: pytest.LogCaptureFixture, case: P
114
148
quality_string = verify_and_get_quality_string (
115
149
pos = pos ,
116
150
constants = DEFAULT_CONSTANTS ,
117
- original_challenge_hash = bytes32 .from_hexstr (
118
- "0x73490e166d0b88347c37d921660b216c27316aae9a3450933d3ff3b854e5831a"
119
- ),
120
- signage_point = bytes32 .from_hexstr ("0x7b3e23dbd438f9aceefa9827e2c5538898189987f49b06eceb7a43067e77b531" ),
151
+ original_challenge_hash = b32 ("0x73490e166d0b88347c37d921660b216c27316aae9a3450933d3ff3b854e5831a" ),
152
+ signage_point = b32 ("0x7b3e23dbd438f9aceefa9827e2c5538898189987f49b06eceb7a43067e77b531" ),
121
153
height = case .height ,
122
154
)
123
155
assert quality_string is None
124
156
assert len (caplog .text ) == 0 if case .expected_error is None else case .expected_error in caplog .text
125
157
126
158
127
- # TODO: todo_v2_plots more test cases
128
159
@datacases (
129
- ProofOfSpaceCase (
130
- id = "v2 plot size 0" ,
131
- pos_challenge = bytes32 (b"1" * 32 ),
132
- plot_size = uint8 (0x80 ),
133
- plot_public_key = G1Element (),
134
- pool_public_key = G1Element (),
135
- pool_contract_puzzle_hash = bytes32 (b"1" * 32 ),
136
- expected_error = "Plot size is lower than the minimum" ,
137
- ),
138
- ProofOfSpaceCase (
139
- id = "v2 plot size 34" ,
140
- pos_challenge = bytes32 (b"1" * 32 ),
141
- plot_size = uint8 (0x80 | 34 ),
142
- plot_public_key = G1Element (),
143
- pool_public_key = G1Element (),
144
- expected_error = "Plot size is higher than the maximum" ,
145
- ),
146
160
ProofOfSpaceCase (
147
161
id = "v2 plot are not implemented" ,
148
- pos_challenge = bytes32 (b"1" * 32 ),
149
162
plot_size = uint8 (0x80 | 30 ),
150
- plot_public_key = G1Element (),
151
- pool_public_key = G1Element (),
163
+ pos_challenge = b32 ("47deb938e145d25d7b3b3c85ca9e3972b76c01aeeb78a02fe5d3b040d282317e" ),
164
+ plot_public_key = g1 (
165
+ "afa3aaf09c03885154be49216ee7fb2e4581b9c4a4d7e9cc402e27280bf0cfdbdf1b9ba674e301fd1d1450234b3b1868"
166
+ ),
167
+ pool_public_key = g1 (
168
+ "b6449c2c68df97c19e884427e42ee7350982d4020571ead08732615ff39bd216bfd630b6460784982bec98b49fea79d0"
169
+ ),
152
170
expected_error = "NotImplementedError" ,
153
171
),
154
172
)
@@ -168,20 +186,41 @@ def test_verify_and_get_quality_string_v2(caplog: pytest.LogCaptureFixture, case
168
186
quality_string = verify_and_get_quality_string (
169
187
pos = pos ,
170
188
constants = DEFAULT_CONSTANTS ,
171
- original_challenge_hash = bytes32 .from_hexstr (
172
- "0x73490e166d0b88347c37d921660b216c27316aae9a3450933d3ff3b854e5831a"
173
- ),
174
- signage_point = bytes32 .from_hexstr ("0x7b3e23dbd438f9aceefa9827e2c5538898189987f49b06eceb7a43067e77b531" ),
189
+ original_challenge_hash = b32 ("0x73490e166d0b88347c37d921660b216c27316aae9a3450933d3ff3b854e5831a" ),
190
+ signage_point = b32 ("0x7b3e23dbd438f9aceefa9827e2c5538898189987f49b06eceb7a43067e77b531" ),
175
191
height = case .height ,
176
192
)
177
- except Exception as e :
193
+ except NotImplementedError as e :
178
194
assert case .expected_error is not None
179
195
assert case .expected_error in repr (e )
180
196
else :
181
197
assert quality_string is None
182
198
assert len (caplog .text ) == 0 if case .expected_error is None else case .expected_error in caplog .text
183
199
184
200
201
+ @pytest .mark .parametrize (
202
+ "height, difficulty" ,
203
+ [
204
+ (0 , 2 ),
205
+ (DEFAULT_CONSTANTS .HARD_FORK_HEIGHT , 2 ),
206
+ (DEFAULT_CONSTANTS .HARD_FORK2_HEIGHT , 2 ),
207
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_4_HEIGHT - 1 , 2 ),
208
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_4_HEIGHT , 4 ),
209
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_5_HEIGHT - 1 , 4 ),
210
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_5_HEIGHT , 5 ),
211
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_6_HEIGHT - 1 , 5 ),
212
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_6_HEIGHT , 6 ),
213
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_7_HEIGHT - 1 , 6 ),
214
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_7_HEIGHT , 7 ),
215
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_8_HEIGHT - 1 , 7 ),
216
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_8_HEIGHT , 8 ),
217
+ (DEFAULT_CONSTANTS .PLOT_DIFFICULTY_8_HEIGHT + 1000000 , 8 ),
218
+ ],
219
+ )
220
+ def test_calculate_plot_difficulty (height : uint32 , difficulty : uint8 ) -> None :
221
+ assert calculate_plot_difficulty (DEFAULT_CONSTANTS , height ) == difficulty
222
+
223
+
185
224
class TestProofOfSpace :
186
225
@pytest .mark .parametrize ("prefix_bits" , [DEFAULT_CONSTANTS .NUMBER_ZERO_BITS_PLOT_FILTER_V1 , 8 , 7 , 6 , 5 , 1 , 0 ])
187
226
def test_can_create_proof (self , prefix_bits : int , seeded_random : random .Random ) -> None :
@@ -200,3 +239,34 @@ def test_can_create_proof(self, prefix_bits: int, seeded_random: random.Random)
200
239
success_count += 1
201
240
202
241
assert abs ((success_count * target_filter / num_trials ) - 1 ) < 0.35
242
+
243
+
244
+ @pytest .mark .parametrize ("height,expected" , [(0 , 3 ), (5496000 , 2 ), (10542000 , 1 ), (15592000 , 0 ), (20643000 , 0 )])
245
+ @pytest .mark .parametrize ("plot_size" , [PlotSize .make_v1 (32 ), PlotSize .make_v2 (28 )])
246
+ def test_calculate_prefix_bits_clamp_zero (height : uint32 , expected : int , plot_size : PlotSize ) -> None :
247
+ constants = DEFAULT_CONSTANTS .replace (NUMBER_ZERO_BITS_PLOT_FILTER_V1 = uint8 (3 ))
248
+ if plot_size .size_v2 is not None :
249
+ expected = constants .NUMBER_ZERO_BITS_PLOT_FILTER_V2
250
+ assert calculate_prefix_bits (constants , height , plot_size ) == expected
251
+
252
+
253
+ @pytest .mark .parametrize (
254
+ argnames = ["height" , "expected" ],
255
+ argvalues = [
256
+ (0 , 9 ),
257
+ (5495999 , 9 ),
258
+ (5496000 , 8 ),
259
+ (10541999 , 8 ),
260
+ (10542000 , 7 ),
261
+ (15591999 , 7 ),
262
+ (15592000 , 6 ),
263
+ (20642999 , 6 ),
264
+ (20643000 , 5 ),
265
+ ],
266
+ )
267
+ @pytest .mark .parametrize ("plot_size" , [PlotSize .make_v1 (32 ), PlotSize .make_v2 (28 )])
268
+ def test_calculate_prefix_bits_default (height : uint32 , expected : int , plot_size : PlotSize ) -> None :
269
+ constants = DEFAULT_CONSTANTS
270
+ if plot_size .size_v2 is not None :
271
+ expected = DEFAULT_CONSTANTS .NUMBER_ZERO_BITS_PLOT_FILTER_V2
272
+ assert calculate_prefix_bits (constants , height , plot_size ) == expected
0 commit comments