@@ -1102,6 +1102,17 @@ impl<T: Read + Write> ElectrumApi for RawClient<T> {
1102
1102
Ok ( serde_json:: from_value ( result) ?)
1103
1103
}
1104
1104
1105
+ fn batch_transaction_get_merkle < ' s , I > (
1106
+ & self ,
1107
+ txids_and_hashes : I ,
1108
+ ) -> Result < Vec < GetMerkleRes > , Error >
1109
+ where
1110
+ I : IntoIterator + Clone ,
1111
+ I :: Item : Borrow < & ' s ( Txid , usize ) > ,
1112
+ {
1113
+ impl_batch_call ! ( self , txids_and_hashes, transaction_get_merkle)
1114
+ }
1115
+
1105
1116
fn txid_from_pos ( & self , height : usize , tx_pos : usize ) -> Result < Txid , Error > {
1106
1117
let params = vec ! [ Param :: Usize ( height) , Param :: Usize ( tx_pos) ] ;
1107
1118
let req = Request :: new_id (
@@ -1448,6 +1459,98 @@ mod test {
1448
1459
) ) ;
1449
1460
}
1450
1461
1462
+ #[ test]
1463
+ fn test_batch_transaction_get_merkle ( ) {
1464
+ use bitcoin:: Txid ;
1465
+
1466
+ struct TestCase {
1467
+ txid : Txid ,
1468
+ block_height : usize ,
1469
+ exp_pos : usize ,
1470
+ exp_bytes : [ u8 ; 32 ] ,
1471
+ }
1472
+
1473
+ let client = RawClient :: new ( get_test_server ( ) , None ) . unwrap ( ) ;
1474
+
1475
+ let test_cases: Vec < TestCase > = vec ! [
1476
+ TestCase {
1477
+ txid: Txid :: from_str(
1478
+ "1f7ff3c407f33eabc8bec7d2cc230948f2249ec8e591bcf6f971ca9366c8788d" ,
1479
+ )
1480
+ . unwrap( ) ,
1481
+ block_height: 630000 ,
1482
+ exp_pos: 68 ,
1483
+ exp_bytes: [
1484
+ 34 , 65 , 51 , 64 , 49 , 139 , 115 , 189 , 185 , 246 , 70 , 225 , 168 , 193 , 217 , 195 , 47 ,
1485
+ 66 , 179 , 240 , 153 , 24 , 114 , 215 , 144 , 196 , 212 , 41 , 39 , 155 , 246 , 25 ,
1486
+ ] ,
1487
+ } ,
1488
+ TestCase {
1489
+ txid: Txid :: from_str(
1490
+ "70a8639bc9b743c0610d1231103a2f8e99f4a25670946b91f16c55a5373b37d1" ,
1491
+ )
1492
+ . unwrap( ) ,
1493
+ block_height: 630001 ,
1494
+ exp_pos: 25 ,
1495
+ exp_bytes: [
1496
+ 169 , 100 , 34 , 99 , 168 , 101 , 25 , 168 , 184 , 90 , 77 , 50 , 151 , 245 , 130 , 101 , 193 ,
1497
+ 229 , 136 , 128 , 63 , 110 , 241 , 19 , 242 , 59 , 184 , 137 , 245 , 249 , 188 , 110 ,
1498
+ ] ,
1499
+ } ,
1500
+ TestCase {
1501
+ txid: Txid :: from_str(
1502
+ "a0db149ace545beabbd87a8d6b20ffd6aa3b5a50e58add49a3d435f898c272cf" ,
1503
+ )
1504
+ . unwrap( ) ,
1505
+ block_height: 840000 ,
1506
+ exp_pos: 0 ,
1507
+ exp_bytes: [
1508
+ 43 , 184 , 95 , 75 , 0 , 75 , 230 , 218 , 84 , 247 , 102 , 193 , 124 , 30 , 133 , 81 , 135 , 50 ,
1509
+ 113 , 18 , 194 , 49 , 239 , 47 , 243 , 94 , 186 , 208 , 234 , 103 , 198 , 158 ,
1510
+ ] ,
1511
+ } ,
1512
+ ] ;
1513
+
1514
+ let txids_and_heights: Vec < ( Txid , usize ) > = test_cases
1515
+ . iter ( )
1516
+ . map ( |case| ( case. txid , case. block_height ) )
1517
+ . collect ( ) ;
1518
+
1519
+ let resp = client
1520
+ . batch_transaction_get_merkle ( & txids_and_heights)
1521
+ . unwrap ( ) ;
1522
+
1523
+ for ( i, ( res, test_case) ) in resp. iter ( ) . zip ( test_cases) . enumerate ( ) {
1524
+ assert_eq ! ( res. block_height, test_case. block_height) ;
1525
+ assert_eq ! ( res. pos, test_case. exp_pos) ;
1526
+ assert_eq ! ( res. merkle. len( ) , 12 ) ;
1527
+ assert_eq ! ( res. merkle[ 0 ] , test_case. exp_bytes) ;
1528
+
1529
+ // Check we can verify the merkle proof validity, but fail if we supply wrong data.
1530
+ let block_header = client. block_header ( res. block_height ) . unwrap ( ) ;
1531
+ assert ! ( utils:: validate_merkle_proof(
1532
+ & txids_and_heights[ i] . 0 ,
1533
+ & block_header. merkle_root,
1534
+ res
1535
+ ) ) ;
1536
+
1537
+ let mut fail_res = res. clone ( ) ;
1538
+ fail_res. pos = 13 ;
1539
+ assert ! ( !utils:: validate_merkle_proof(
1540
+ & txids_and_heights[ i] . 0 ,
1541
+ & block_header. merkle_root,
1542
+ & fail_res
1543
+ ) ) ;
1544
+
1545
+ let fail_block_header = client. block_header ( res. block_height + 1 ) . unwrap ( ) ;
1546
+ assert ! ( !utils:: validate_merkle_proof(
1547
+ & txids_and_heights[ i] . 0 ,
1548
+ & fail_block_header. merkle_root,
1549
+ res
1550
+ ) ) ;
1551
+ }
1552
+ }
1553
+
1451
1554
#[ test]
1452
1555
fn test_txid_from_pos ( ) {
1453
1556
use bitcoin:: Txid ;
0 commit comments