@@ -6,6 +6,7 @@ import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator
6
6
import io .iohk .ethereum .consensus .difficulty .DifficultyCalculator
7
7
import io .iohk .ethereum .consensus .validators .BlockHeaderError ._
8
8
import io .iohk .ethereum .crypto .ECDSASignature
9
+ import io .iohk .ethereum .crypto .ECDSASignatureImplicits .ECDSASignatureOrdering
9
10
import io .iohk .ethereum .domain .BlockHeader .HeaderExtraFields .HefPostEcip1097
10
11
import io .iohk .ethereum .domain ._
11
12
import io .iohk .ethereum .ledger .BloomFilter
@@ -155,6 +156,18 @@ class BlockWithCheckpointHeaderValidatorSpec
155
156
)
156
157
}
157
158
159
+ it should " return failure when checkpoint signatures aren't sorted lexicographically" in new TestSetup {
160
+ val invalidBlockHeaderExtraFields = HefPostEcip1097 (
161
+ false ,
162
+ Some (Checkpoint (validCheckpoint.signatures.reverse))
163
+ )
164
+ val invalidBlockHeader =
165
+ validBlockHeaderWithCheckpoint.copy(extraFields = invalidBlockHeaderExtraFields)
166
+ blockHeaderValidator.validate(invalidBlockHeader, validBlockParentHeader) shouldBe Left (
167
+ HeaderInvalidOrderOfCheckpointSignatures
168
+ )
169
+ }
170
+
158
171
it should " return failure when checkpoint has not enough valid signatures" in new TestSetup {
159
172
val invalidBlockHeaderExtraFields = HefPostEcip1097 (
160
173
false ,
@@ -170,10 +183,11 @@ class BlockWithCheckpointHeaderValidatorSpec
170
183
it should " return failure when checkpoint has enough valid signatures, but also an invalid one" in new TestSetup {
171
184
val invalidKeys = crypto.generateKeyPair(secureRandom)
172
185
val invalidSignatures =
173
- CheckpointingTestHelpers .createCheckpointSignatures(Seq (invalidKeys), validBlockParentHeader.hash)
186
+ CheckpointingTestHelpers .createCheckpointSignatures(Seq (invalidKeys), validBlockParent.hash)
187
+ val signatures = invalidSignatures ++ validCheckpoint.signatures
174
188
val invalidBlockHeaderExtraFields = HefPostEcip1097 (
175
189
false ,
176
- Some (Checkpoint (invalidSignatures ++ validCheckpoint. signatures))
190
+ Some (Checkpoint (signatures.sorted ))
177
191
)
178
192
val invalidBlockHeader = validBlockHeaderWithCheckpoint.copy(extraFields = invalidBlockHeaderExtraFields)
179
193
blockHeaderValidator.validate(invalidBlockHeader, validBlockParentHeader) shouldBe Left (
@@ -203,11 +217,15 @@ class BlockWithCheckpointHeaderValidatorSpec
203
217
" 7e1573bc593f289793304c50fa8068d35f8611e5c558337c72b6bcfef1dbfc884226ad305a97659fc172d347b70ea7bfca011859118efcee33f3b5e02d31c3cd1b"
204
218
val sameSignerSig = ECDSASignature .fromBytes(ByteStringUtils .string2hash(sameSignerSigHex)).get
205
219
206
- val invalidCheckpoint = Checkpoint (sameSignerSig +: validCheckpoint.signatures)
220
+ val invalidCheckpoint = Checkpoint (( sameSignerSig +: validCheckpoint.signatures).sorted )
207
221
208
222
// verify that we have 2 signatures from the same signer
209
- val actualSigners = invalidCheckpoint.signatures.flatMap(_.publicKey(validBlockParentHeader.hash))
210
- val expectedSigners = (keys.head +: keys).map(kp => ByteString (crypto.pubKeyFromKeyPair(kp)))
223
+ import Ordering .Implicits ._
224
+ val actualSigners = invalidCheckpoint.signatures.flatMap(_.publicKey(validBlockParent.hash)).sortBy(_.toSeq)
225
+ val duplicatedSigner = ByteString (crypto.pubKeyFromKeyPair(keys.head))
226
+ val expectedSigners =
227
+ (keys.map(kp => ByteString (crypto.pubKeyFromKeyPair(kp))) :+ duplicatedSigner)
228
+ .sortBy(_.toSeq)
211
229
actualSigners shouldEqual expectedSigners
212
230
213
231
val headerWithInvalidCheckpoint = checkpointBlockGenerator
@@ -219,15 +237,17 @@ class BlockWithCheckpointHeaderValidatorSpec
219
237
220
238
val expectedError = {
221
239
val invalidSigs =
222
- invalidCheckpoint.signatures.take(2 ).map(_ -> Some (ByteStringUtils .hash2string(expectedSigners.head)))
240
+ invalidCheckpoint.signatures
241
+ .filter(_.publicKey(validBlockParent.hash).contains(duplicatedSigner))
242
+ .map(_ -> Some (ByteStringUtils .hash2string(duplicatedSigner)))
223
243
Left (HeaderInvalidCheckpointSignatures (invalidSigs))
224
244
}
225
245
226
246
blockHeaderValidator.validate(headerWithInvalidCheckpoint, validBlockParentHeader) shouldBe expectedError
227
247
}
228
248
229
249
it should " return when failure when checkpoint has too many signatures" in new TestSetup {
230
- val invalidCheckpoint = validCheckpoint.copy(signatures = validCheckpoint.signatures ++ validCheckpoint.signatures)
250
+ val invalidCheckpoint = validCheckpoint.copy(signatures = ( validCheckpoint.signatures ++ validCheckpoint.signatures).sorted )
231
251
val invalidBlockHeaderExtraFields = HefPostEcip1097 (false , Some (invalidCheckpoint))
232
252
val invalidBlockHeader = validBlockHeaderWithCheckpoint.copy(extraFields = invalidBlockHeaderExtraFields)
233
253
@@ -255,7 +275,6 @@ class BlockWithCheckpointHeaderValidatorSpec
255
275
" 6848a3ab71918f57d3b9116b8e93c6fbc53e8a28dcd63e99c514dceee30fdd9741050fa7646bd196c9512e52f0d03097678c707996fff55587cd467801a1eee1"
256
276
)
257
277
)
258
-
259
278
val config : BlockchainConfig = blockchainConfig.copy(
260
279
ecip1097BlockNumber = validBlockParentHeader.number,
261
280
ecip1098BlockNumber = validBlockParentHeader.number,
0 commit comments