@@ -6,6 +6,7 @@ import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator
66import io .iohk .ethereum .consensus .difficulty .DifficultyCalculator
77import io .iohk .ethereum .consensus .validators .BlockHeaderError ._
88import io .iohk .ethereum .crypto .ECDSASignature
9+ import io .iohk .ethereum .crypto .ECDSASignatureImplicits .ECDSASignatureOrdering
910import io .iohk .ethereum .domain .BlockHeader .HeaderExtraFields .HefPostEcip1097
1011import io .iohk .ethereum .domain ._
1112import io .iohk .ethereum .ledger .BloomFilter
@@ -155,6 +156,18 @@ class BlockWithCheckpointHeaderValidatorSpec
155156 )
156157 }
157158
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+
158171 it should " return failure when checkpoint has not enough valid signatures" in new TestSetup {
159172 val invalidBlockHeaderExtraFields = HefPostEcip1097 (
160173 false ,
@@ -170,10 +183,11 @@ class BlockWithCheckpointHeaderValidatorSpec
170183 it should " return failure when checkpoint has enough valid signatures, but also an invalid one" in new TestSetup {
171184 val invalidKeys = crypto.generateKeyPair(secureRandom)
172185 val invalidSignatures =
173- CheckpointingTestHelpers .createCheckpointSignatures(Seq (invalidKeys), validBlockParentHeader.hash)
186+ CheckpointingTestHelpers .createCheckpointSignatures(Seq (invalidKeys), validBlockParent.hash)
187+ val signatures = invalidSignatures ++ validCheckpoint.signatures
174188 val invalidBlockHeaderExtraFields = HefPostEcip1097 (
175189 false ,
176- Some (Checkpoint (invalidSignatures ++ validCheckpoint. signatures))
190+ Some (Checkpoint (signatures.sorted ))
177191 )
178192 val invalidBlockHeader = validBlockHeaderWithCheckpoint.copy(extraFields = invalidBlockHeaderExtraFields)
179193 blockHeaderValidator.validate(invalidBlockHeader, validBlockParentHeader) shouldBe Left (
@@ -203,11 +217,15 @@ class BlockWithCheckpointHeaderValidatorSpec
203217 " 7e1573bc593f289793304c50fa8068d35f8611e5c558337c72b6bcfef1dbfc884226ad305a97659fc172d347b70ea7bfca011859118efcee33f3b5e02d31c3cd1b"
204218 val sameSignerSig = ECDSASignature .fromBytes(ByteStringUtils .string2hash(sameSignerSigHex)).get
205219
206- val invalidCheckpoint = Checkpoint (sameSignerSig +: validCheckpoint.signatures)
220+ val invalidCheckpoint = Checkpoint (( sameSignerSig +: validCheckpoint.signatures).sorted )
207221
208222 // 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)
211229 actualSigners shouldEqual expectedSigners
212230
213231 val headerWithInvalidCheckpoint = checkpointBlockGenerator
@@ -219,15 +237,17 @@ class BlockWithCheckpointHeaderValidatorSpec
219237
220238 val expectedError = {
221239 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)))
223243 Left (HeaderInvalidCheckpointSignatures (invalidSigs))
224244 }
225245
226246 blockHeaderValidator.validate(headerWithInvalidCheckpoint, validBlockParentHeader) shouldBe expectedError
227247 }
228248
229249 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 )
231251 val invalidBlockHeaderExtraFields = HefPostEcip1097 (false , Some (invalidCheckpoint))
232252 val invalidBlockHeader = validBlockHeaderWithCheckpoint.copy(extraFields = invalidBlockHeaderExtraFields)
233253
@@ -255,7 +275,6 @@ class BlockWithCheckpointHeaderValidatorSpec
255275 " 6848a3ab71918f57d3b9116b8e93c6fbc53e8a28dcd63e99c514dceee30fdd9741050fa7646bd196c9512e52f0d03097678c707996fff55587cd467801a1eee1"
256276 )
257277 )
258-
259278 val config : BlockchainConfig = blockchainConfig.copy(
260279 ecip1097BlockNumber = validBlockParentHeader.number,
261280 ecip1098BlockNumber = validBlockParentHeader.number,
0 commit comments