@@ -745,6 +745,55 @@ async fn decision_reached_sends_correct_values() {
745745 . assert_eq ( & metrics, VersionedConstants :: latest_constants ( ) . min_gas_price . 0 ) ;
746746}
747747
748+ // The blob's `parent_proposal_commitment` must bind the parent block's `fee_proposal_fri`, which
749+ // is read from `fee_proposals_window`. Build/decide at HEIGHT_1 so the parent (HEIGHT_0) exists,
750+ // seed the window with a parent fee distinct from the current block's, and assert the blob carries
751+ // the V0_14_3 commitment `Poseidon(partial_block_hash, parent_fee_proposal)`.
752+ #[ tokio:: test]
753+ async fn blob_parent_proposal_commitment_binds_parent_fee_proposal ( ) {
754+ const PARENT_FEE_PROPOSAL : GasPrice = GasPrice ( 5_000_000_000 ) ;
755+
756+ let ( mut deps, _network) = create_test_and_network_deps ( ) ;
757+
758+ deps. setup_deps_for_build ( SetupDepsArgs { start_block_number : HEIGHT_1 , ..Default :: default ( ) } ) ;
759+
760+ deps. batcher . expect_decision_reached ( ) . times ( 1 ) . return_once ( move |_| {
761+ Ok ( DecisionReachedResponse {
762+ central_objects : CentralObjects {
763+ parent_proposal_commitment : Some ( BatcherProposalCommitment {
764+ partial_block_hash : PARTIAL_BLOCK_HASH ,
765+ } ) ,
766+ ..Default :: default ( )
767+ } ,
768+ ..Default :: default ( )
769+ } )
770+ } ) ;
771+
772+ deps. state_sync_client . expect_add_new_block ( ) . times ( 1 ) . return_once ( |_| Ok ( ( ) ) ) ;
773+
774+ let expected_parent_commitment =
775+ proposal_commitment_from ( PARTIAL_BLOCK_HASH , Some ( PARENT_FEE_PROPOSAL ) ) ;
776+ deps. cende_ambassador . expect_prepare_blob_for_next_height ( ) . times ( 1 ) . return_once (
777+ move |params| {
778+ assert_eq ! ( params. proposal_commitment, * TEST_PROPOSAL_COMMITMENT ) ;
779+ assert_eq ! ( params. parent_proposal_commitment, Some ( expected_parent_commitment) ) ;
780+ Ok ( ( ) )
781+ } ,
782+ ) ;
783+
784+ let mut context = deps. build_context ( ) ;
785+
786+ let _fin = context
787+ . build_proposal ( BuildParam { height : HEIGHT_1 , ..Default :: default ( ) } , TIMEOUT )
788+ . await
789+ . unwrap ( )
790+ . await ;
791+ // Seed the parent fee after building, so the current block still uses the default fee_proposal.
792+ context. fee_proposals_window . insert ( HEIGHT_0 , Some ( PARENT_FEE_PROPOSAL ) ) ;
793+
794+ context. decision_reached ( HEIGHT_1 , ROUND_0 , * TEST_PROPOSAL_COMMITMENT , false ) . await . unwrap ( ) ;
795+ }
796+
748797/// Verify that when `stop_at_height` is set and decision is reached at that height:
749798/// 1. `wait_for_block_hash` retries until the batcher has computed the hash.
750799/// 2. The blob contains the block hash of that height.
0 commit comments