11// Copyright 2023-, Semiotic AI, Inc.
22// SPDX-License-Identifier: Apache-2.0
33
4- use std:: collections:: { hash_set , HashSet } ;
4+ use std:: collections:: HashSet ;
55
66use anyhow:: { bail, Ok , Result } ;
77use rayon:: prelude:: * ;
8- use tap_core:: signed_message :: { Eip712SignedMessage , SignatureBytes , SignatureBytesExt } ;
8+ use tap_core:: { receipt :: WithUniqueId , signed_message :: Eip712SignedMessage } ;
99use tap_graph:: { Receipt , ReceiptAggregateVoucher } ;
1010use thegraph_core:: alloy:: {
1111 dyn_abi:: Eip712Domain , primitives:: Address , signers:: local:: PrivateKeySigner ,
@@ -19,7 +19,7 @@ pub fn check_and_aggregate_receipts(
1919 wallet : & PrivateKeySigner ,
2020 accepted_addresses : & HashSet < Address > ,
2121) -> Result < Eip712SignedMessage < ReceiptAggregateVoucher > > {
22- check_signatures_unique ( receipts) ?;
22+ check_signatures_unique ( domain_separator , receipts) ?;
2323
2424 // Check that the receipts are signed by an accepted signer address
2525 receipts. par_iter ( ) . try_for_each ( |receipt| {
@@ -93,14 +93,17 @@ fn check_allocation_id(
9393 Ok ( ( ) )
9494}
9595
96- fn check_signatures_unique ( receipts : & [ Eip712SignedMessage < Receipt > ] ) -> Result < ( ) > {
97- let mut receipt_signatures: hash_set:: HashSet < SignatureBytes > = hash_set:: HashSet :: new ( ) ;
96+ fn check_signatures_unique (
97+ domain_separator : & Eip712Domain ,
98+ receipts : & [ Eip712SignedMessage < Receipt > ] ,
99+ ) -> Result < ( ) > {
100+ let mut receipt_signatures = HashSet :: new ( ) ;
98101 for receipt in receipts. iter ( ) {
99- let signature = receipt. signature . get_signature_bytes ( ) ;
102+ let signature = receipt. unique_id ( domain_separator ) ? ;
100103 if !receipt_signatures. insert ( signature) {
101104 return Err ( tap_core:: Error :: DuplicateReceiptSignature ( format ! (
102105 "{:?}" ,
103- receipt. signature
106+ receipt. unique_id ( domain_separator ) ?
104107 ) )
105108 . into ( ) ) ;
106109 }
@@ -167,7 +170,6 @@ mod tests {
167170
168171 #[ rstest]
169172 #[ test]
170- #[ should_panic]
171173 fn test_signature_malleability_vulnerability (
172174 keys : ( PrivateKeySigner , Address ) ,
173175 allocation_ids : Vec < Address > ,
@@ -219,7 +221,7 @@ mod tests {
219221
220222 // This should return an error because the signatures are different
221223 // but the messages are the same, which if allowed would present a security vulnerability
222- let result = check_signatures_unique ( & receipts) ;
224+ let result = check_signatures_unique ( & domain_separator , & receipts) ;
223225
224226 // The result should be an error because the malleated signature is not treated as unique
225227 // and is detected as a duplicate
@@ -244,7 +246,7 @@ mod tests {
244246 receipts. push ( receipt. clone ( ) ) ;
245247 receipts. push ( receipt) ;
246248
247- let res = check_signatures_unique ( & receipts) ;
249+ let res = check_signatures_unique ( & domain_separator , & receipts) ;
248250 assert ! ( res. is_err( ) ) ;
249251 }
250252
@@ -271,7 +273,7 @@ mod tests {
271273 . unwrap( ) ,
272274 ] ;
273275
274- let res = check_signatures_unique ( & receipts) ;
276+ let res = check_signatures_unique ( & domain_separator , & receipts) ;
275277 assert ! ( res. is_ok( ) ) ;
276278 }
277279
0 commit comments