@@ -509,64 +509,83 @@ fn try_parse_stacks_operation(
509
509
let mut pox_sats_burnt = 0 ;
510
510
let mut pox_sats_transferred = vec ! [ ] ;
511
511
512
- // We need to determine wether the transaction was a PoB or a Pox commitment
513
- let mining_output_index = if pox_config
514
- . is_consensus_rewarding_participants_at_block_height ( block_height)
512
+ let output_1 = outputs
513
+ . get ( 1 )
514
+ . ok_or ( format ! ( "expected output 1 not found" ) )
515
+ . ok ( ) ?;
516
+ let script_1 = output_1
517
+ . script_pub_key
518
+ . script ( )
519
+ . map_err ( |_e| format ! ( "expected output 1 corrupted" ) )
520
+ . ok ( ) ?;
521
+ let address_1 = Address :: from_script ( & script_1, bitcoin:: Network :: Bitcoin )
522
+ . map_err ( |_e| format ! ( "expected output 1 corrupted" ) )
523
+ . ok ( ) ?;
524
+
525
+ let output_2 = outputs
526
+ . get ( 2 )
527
+ . ok_or ( format ! ( "expected output 2 not found" ) )
528
+ . ok ( ) ?;
529
+ let script_2 = output_2
530
+ . script_pub_key
531
+ . script ( )
532
+ . map_err ( |_e| format ! ( "expected output 2 corrupted" ) )
533
+ . ok ( ) ?;
534
+ let address_2 = Address :: from_script ( & script_2, bitcoin:: Network :: Bitcoin )
535
+ . map_err ( |_e| format ! ( "expected output 2 corrupted" ) )
536
+ . ok ( ) ?;
537
+
538
+ let output_1_is_burn = address_1. to_string ( ) . eq ( pox_config. get_burn_address ( ) ) ;
539
+ let output_2_is_burn = address_2. to_string ( ) . eq ( pox_config. get_burn_address ( ) ) ;
540
+
541
+ // PoX commitments have the following outputs:
542
+ // - 0: OP_RETURN
543
+ // - 1: rewarding address (could be a reward address, could be burn address in some rare cases)
544
+ // - 2: rewarding address (could be a reward address, could be burn address in some rare cases; always burn address if 1 was burn address)
545
+ // - [3-n]: change outputs
546
+ //
547
+ // PoB commitments have:
548
+ // - 0: OP_RETURN
549
+ // - 1: Burn address
550
+ // - [3-n]: change outputs
551
+ //
552
+ // So, to determine if PoX vs PoB, we check if output 1 is the burn address
553
+ // - If not, we definitely have a PoX block commitment
554
+ // - If it is, we need to check if output 2 is the burn address
555
+ // - If it is, we have a PoX block commitment
556
+ // - If not, we have a PoB block commitment
557
+ //
558
+ // The only assumption we're making in this logic is that the first change output doesn't
559
+ // get sent to the burn address, in which case we'd incorrectly label a PoB block commitment as Pox.
560
+ let mining_output_index = if !output_1_is_burn || ( output_1_is_burn && output_2_is_burn)
515
561
{
562
+ // We have a PoX Block Commitment
516
563
// Output 0 is OP_RETURN
517
564
// Output 1 is rewarding Address 1
518
- let pox_output_1 = outputs
519
- . get ( 1 )
520
- . ok_or ( format ! ( "expected pox output 1 not found" ) )
521
- . ok ( ) ?;
522
- let pox_script_1 = pox_output_1
523
- . script_pub_key
524
- . script ( )
525
- . map_err ( |_e| format ! ( "expected pox output 1 corrupted" ) )
526
- . ok ( ) ?;
527
- let pox_address_1 = Address :: from_script ( & pox_script_1, bitcoin:: Network :: Bitcoin )
528
- . map_err ( |_e| format ! ( "expected pox output 1 corrupted" ) )
529
- . ok ( ) ?;
530
- if pox_address_1. to_string ( ) . eq ( & pox_config. get_burn_address ( ) ) {
531
- pox_sats_burnt += pox_output_1. value . to_sat ( ) ;
565
+ if output_1_is_burn {
566
+ pox_sats_burnt += output_1. value . to_sat ( ) ;
532
567
} else {
533
568
pox_sats_transferred. push ( PoxReward {
534
- recipient_address : pox_address_1 . to_string ( ) ,
535
- amount : pox_output_1 . value . to_sat ( ) ,
569
+ recipient_address : address_1 . to_string ( ) ,
570
+ amount : output_1 . value . to_sat ( ) ,
536
571
} ) ;
537
572
}
538
573
// Output 2 is rewarding Address 2
539
- let pox_output_2 = outputs
540
- . get ( 2 )
541
- . ok_or ( format ! ( "expected pox output 2 not found" ) )
542
- . ok ( ) ?;
543
- let pox_script_2 = pox_output_2
544
- . script_pub_key
545
- . script ( )
546
- . map_err ( |_e| format ! ( "expected pox output 2 corrupted" ) )
547
- . ok ( ) ?;
548
- let pox_address_2 = Address :: from_script ( & pox_script_2, bitcoin:: Network :: Bitcoin )
549
- . map_err ( |_e| format ! ( "expected pox output 2 corrupted" ) )
550
- . ok ( ) ?;
551
- if pox_address_2. to_string ( ) . eq ( & pox_config. get_burn_address ( ) ) {
552
- pox_sats_burnt += pox_output_2. value . to_sat ( ) ;
574
+ if output_2_is_burn {
575
+ pox_sats_burnt += output_2. value . to_sat ( ) ;
553
576
} else {
554
577
pox_sats_transferred. push ( PoxReward {
555
- recipient_address : pox_address_2 . to_string ( ) ,
556
- amount : pox_output_2 . value . to_sat ( ) ,
578
+ recipient_address : address_2 . to_string ( ) ,
579
+ amount : output_2 . value . to_sat ( ) ,
557
580
} ) ;
558
581
}
559
582
// Output 3 is used for miner chained commitments
560
583
3
561
584
} else {
585
+ // We have a PoB Block Commitment
562
586
// Output 0 is OP_RETURN
563
- // Output 1 should be a Burn Address
564
- let burn_output = outputs
565
- . get ( 1 )
566
- . ok_or ( format ! ( "expected burn address not found" ) )
567
- . ok ( ) ?;
568
- // Todo: Ensure that we're looking at a burn address
569
- pox_sats_burnt += burn_output. value . to_sat ( ) ;
587
+ // Output 1 is be a Burn Address
588
+ pox_sats_burnt += output_1. value . to_sat ( ) ;
570
589
// Output 2 is used for miner chained commitments
571
590
2
572
591
} ;
0 commit comments