@@ -4801,6 +4801,158 @@ mod tests {
48014801 assert ! ( transactions_pool. output_pointer_map. is_empty( ) ) ;
48024802 }
48034803
4804+ #[ test]
4805+ fn transactions_pool_malleability_vt ( ) {
4806+ let input = Input :: default ( ) ;
4807+ let mut vt_1 = VTTransaction :: new (
4808+ VTTransactionBody :: new ( vec ! [ input] , vec ! [ ] ) ,
4809+ vec ! [ KeyedSignature :: default ( ) ] ,
4810+ ) ;
4811+ // Add dummy signature, but pretend it is valid
4812+ match & mut vt_1. signatures [ 0 ] . signature {
4813+ Signature :: Secp256k1 ( sig) => sig. der = vec ! [ 0 ; 32 ] ,
4814+ }
4815+
4816+ let mut vt_2 = vt_1. clone ( ) ;
4817+ // Flip one bit in the signature, but pretend that the signature is still valid (malleability).
4818+ match & mut vt_2. signatures [ 0 ] . signature {
4819+ Signature :: Secp256k1 ( secp_sig) => {
4820+ // Flip 1 bit
4821+ secp_sig. der [ 10 ] ^= 0x01 ;
4822+ }
4823+ }
4824+
4825+ let vt1 = Transaction :: ValueTransfer ( vt_1. clone ( ) ) ;
4826+ let vt2 = Transaction :: ValueTransfer ( vt_2. clone ( ) ) ;
4827+ assert_eq ! ( vt1. hash( ) , vt2. hash( ) ) ;
4828+ assert_ne ! ( vt1, vt2) ;
4829+
4830+ let mut transactions_pool = TransactionsPool :: default ( ) ;
4831+ transactions_pool. insert ( vt1. clone ( ) , 1 ) ;
4832+ transactions_pool. insert ( vt2. clone ( ) , 1 ) ;
4833+ // Removing vt_1 actually returns vt_2, because they have the same hash, but this is fine
4834+ // because they both have a valid signature
4835+ let t = transactions_pool. vt_remove ( & vt_1) . unwrap ( ) ;
4836+ assert_eq ! ( Transaction :: ValueTransfer ( t) , vt2) ;
4837+ assert ! ( !transactions_pool. contains( & vt1) . unwrap( ) ) ;
4838+ assert ! ( !transactions_pool. contains( & vt2) . unwrap( ) ) ;
4839+ }
4840+
4841+ #[ test]
4842+ fn transactions_pool_malleability_dr ( ) {
4843+ let input = Input :: default ( ) ;
4844+ let mut dr_1 = DRTransaction :: new (
4845+ DRTransactionBody :: new ( vec ! [ input] , vec ! [ ] , DataRequestOutput :: default ( ) ) ,
4846+ vec ! [ KeyedSignature :: default ( ) ] ,
4847+ ) ;
4848+ // Add dummy signature, but pretend it is valid
4849+ match & mut dr_1. signatures [ 0 ] . signature {
4850+ Signature :: Secp256k1 ( sig) => sig. der = vec ! [ 0 ; 32 ] ,
4851+ }
4852+
4853+ let mut dr_2 = dr_1. clone ( ) ;
4854+ // Flip one bit in the signature, but pretend that the signature is still valid (malleability).
4855+ match & mut dr_2. signatures [ 0 ] . signature {
4856+ Signature :: Secp256k1 ( secp_sig) => {
4857+ // Flip 1 bit
4858+ secp_sig. der [ 10 ] ^= 0x01 ;
4859+ }
4860+ }
4861+
4862+ let dr1 = Transaction :: DataRequest ( dr_1. clone ( ) ) ;
4863+ let dr2 = Transaction :: DataRequest ( dr_2. clone ( ) ) ;
4864+ assert_eq ! ( dr1. hash( ) , dr2. hash( ) ) ;
4865+ assert_ne ! ( dr1, dr2) ;
4866+
4867+ let mut transactions_pool = TransactionsPool :: default ( ) ;
4868+ transactions_pool. insert ( dr1. clone ( ) , 1 ) ;
4869+ transactions_pool. insert ( dr2. clone ( ) , 1 ) ;
4870+ // Removing dr_1 actually returns dr_2, because they have the same hash, but this is fine
4871+ // because they both have a valid signature
4872+ let t = transactions_pool. dr_remove ( & dr_1) . unwrap ( ) ;
4873+ assert_eq ! ( Transaction :: DataRequest ( t) , dr2) ;
4874+ assert ! ( !transactions_pool. contains( & dr1) . unwrap( ) ) ;
4875+ assert ! ( !transactions_pool. contains( & dr2) . unwrap( ) ) ;
4876+ }
4877+
4878+ #[ test]
4879+ fn transactions_pool_malleability_co ( ) {
4880+ let c1 = Hash :: SHA256 ( [ 1 ; 32 ] ) ;
4881+ let mut t1 = Transaction :: Commit ( CommitTransaction {
4882+ body : CommitTransactionBody :: without_collateral (
4883+ Default :: default ( ) ,
4884+ c1,
4885+ Default :: default ( ) ,
4886+ ) ,
4887+ signatures : vec ! [ KeyedSignature :: default ( ) ] ,
4888+ } ) ;
4889+ // Add dummy signature, but pretend it is valid
4890+ match & mut t1 {
4891+ Transaction :: Commit ( co1) => match & mut co1. signatures [ 0 ] . signature {
4892+ Signature :: Secp256k1 ( sig) => sig. der = vec ! [ 0 ; 32 ] ,
4893+ } ,
4894+ _ => unreachable ! ( ) ,
4895+ }
4896+
4897+ let mut t2 = t1. clone ( ) ;
4898+ // Flip one bit in the signature, but pretend that the signature is still valid (malleability).
4899+ match & mut t2 {
4900+ Transaction :: Commit ( co2) => {
4901+ match & mut co2. signatures [ 0 ] . signature {
4902+ Signature :: Secp256k1 ( secp_sig) => {
4903+ // Flip 1 bit
4904+ secp_sig. der [ 10 ] ^= 0x01 ;
4905+ }
4906+ }
4907+ }
4908+ _ => unreachable ! ( ) ,
4909+ }
4910+
4911+ let mut transactions_pool = TransactionsPool :: default ( ) ;
4912+ transactions_pool. insert ( t1, 0 ) ;
4913+ transactions_pool. insert ( t2. clone ( ) , 0 ) ;
4914+ let mut expected = TransactionsPool :: default ( ) ;
4915+ expected. insert ( t2, 0 ) ;
4916+ assert_eq ! ( transactions_pool. co_transactions, expected. co_transactions) ;
4917+ }
4918+
4919+ #[ test]
4920+ fn transactions_pool_malleability_re ( ) {
4921+ let r1 = vec ! [ 1 ] ;
4922+ let mut t1 = Transaction :: Reveal ( RevealTransaction {
4923+ body : RevealTransactionBody :: new ( Default :: default ( ) , r1, Default :: default ( ) ) ,
4924+ signatures : vec ! [ KeyedSignature :: default ( ) ] ,
4925+ } ) ;
4926+ // Add dummy signature, but pretend it is valid
4927+ match & mut t1 {
4928+ Transaction :: Reveal ( re1) => match & mut re1. signatures [ 0 ] . signature {
4929+ Signature :: Secp256k1 ( sig) => sig. der = vec ! [ 0 ; 32 ] ,
4930+ } ,
4931+ _ => unreachable ! ( ) ,
4932+ }
4933+
4934+ let mut t2 = t1. clone ( ) ;
4935+ // Flip one bit in the signature, but pretend that the signature is still valid (malleability).
4936+ match & mut t2 {
4937+ Transaction :: Reveal ( re2) => {
4938+ match & mut re2. signatures [ 0 ] . signature {
4939+ Signature :: Secp256k1 ( secp_sig) => {
4940+ // Flip 1 bit
4941+ secp_sig. der [ 10 ] ^= 0x01 ;
4942+ }
4943+ }
4944+ }
4945+ _ => unreachable ! ( ) ,
4946+ }
4947+
4948+ let mut transactions_pool = TransactionsPool :: default ( ) ;
4949+ transactions_pool. insert ( t1, 0 ) ;
4950+ transactions_pool. insert ( t2. clone ( ) , 0 ) ;
4951+ let mut expected = TransactionsPool :: default ( ) ;
4952+ expected. insert ( t2, 0 ) ;
4953+ assert_eq ! ( transactions_pool. re_transactions, expected. re_transactions) ;
4954+ }
4955+
48044956 #[ test]
48054957 fn transactions_pool_size_limit ( ) {
48064958 let input = Input :: default ( ) ;
0 commit comments