@@ -783,10 +783,12 @@ impl BlockTransactionPayload {
783783 }
784784
785785 /// Returns the proofs of the transaction payload
786- pub fn payload_proofs_v2 ( & self ) -> Vec < ProofOfStore < BatchInfoExt > > {
786+ pub fn payload_proofs_v2 ( & self ) -> Result < Vec < ProofOfStore < BatchInfoExt > > , Error > {
787787 match self {
788- BlockTransactionPayload :: OptQuorumStoreV2 ( payload, _) => payload. proofs ( ) ,
789- _ => unreachable ! ( ) ,
788+ BlockTransactionPayload :: OptQuorumStoreV2 ( payload, _) => Ok ( payload. proofs ( ) ) ,
789+ _ => Err ( Error :: InvalidMessageError (
790+ "Transaction payload is not an OptQuorumStoreV2 variant!" . into ( ) ,
791+ ) ) ,
790792 }
791793 }
792794
@@ -857,7 +859,7 @@ impl BlockTransactionPayload {
857859 // Get the batches in the block transaction payload
858860 let payload_proofs = self
859861 . payload_proofs ( )
860- . expect ( "non-OptQSV2 batch is expected" ) ;
862+ . map_err ( |e| Error :: InvalidMessageError ( e . to_string ( ) ) ) ? ;
861863 let payload_batches: Vec < & BatchInfo > =
862864 payload_proofs. iter ( ) . map ( |proof| proof. info ( ) ) . collect ( ) ;
863865
@@ -946,7 +948,7 @@ impl BlockTransactionPayload {
946948 expected_proofs : & [ ProofOfStore < BatchInfoExt > ] ,
947949 ) -> Result < ( ) , Error > {
948950 // Get the batches in the block transaction payload
949- let payload_proofs = self . payload_proofs_v2 ( ) ;
951+ let payload_proofs = self . payload_proofs_v2 ( ) ? ;
950952 let payload_batches: Vec < & BatchInfoExt > =
951953 payload_proofs. iter ( ) . map ( |proof| proof. info ( ) ) . collect ( ) ;
952954
@@ -1207,7 +1209,7 @@ impl BlockPayload {
12071209 ) )
12081210 } ) ?;
12091211 } else {
1210- let payload_proofs = self . transaction_payload . payload_proofs_v2 ( ) ;
1212+ let payload_proofs = self . transaction_payload . payload_proofs_v2 ( ) ? ;
12111213 let validator_verifier = & epoch_state. verifier ;
12121214 payload_proofs
12131215 . par_iter ( )
@@ -1513,6 +1515,90 @@ mod test {
15131515 . unwrap ( ) ;
15141516 }
15151517
1518+ #[ test]
1519+ fn test_verify_against_ordered_payload_optqs_v2_variant_mismatch ( ) {
1520+ // Build an empty V2 ordered block payload (as produced by validators when
1521+ // enable_opt_qs_v2_payload_tx is enabled).
1522+ let v2_ordered_payload = Payload :: OptQuorumStore ( OptQuorumStorePayload :: new_v2 (
1523+ Vec :: < ( BatchInfoExt , Vec < SignedTransaction > ) > :: new ( ) . into ( ) ,
1524+ Vec :: < BatchInfoExt > :: new ( ) . into ( ) ,
1525+ Vec :: < ProofOfStore < BatchInfoExt > > :: new ( ) . into ( ) ,
1526+ PayloadExecutionLimit :: MaxTransactionsToExecute ( 100 ) ,
1527+ ) ) ;
1528+
1529+ // Verify that non-V2 stored variants fail verification
1530+ let hybrid_payload = BlockTransactionPayload :: new_quorum_store_inline_hybrid (
1531+ vec ! [ ] ,
1532+ vec ! [ ] ,
1533+ None ,
1534+ None ,
1535+ vec ! [ ] ,
1536+ false , // Produces the legacy QuorumStoreInlineHybrid variant
1537+ ) ;
1538+ let error = hybrid_payload
1539+ . verify_against_ordered_payload ( & v2_ordered_payload)
1540+ . unwrap_err ( ) ;
1541+ assert_matches ! ( error, Error :: InvalidMessageError ( _) ) ;
1542+
1543+ // Verify that the QuorumStoreInlineHybridV2 variant also fails verification
1544+ let hybrid_v2_payload = BlockTransactionPayload :: new_quorum_store_inline_hybrid (
1545+ vec ! [ ] ,
1546+ vec ! [ ] ,
1547+ None ,
1548+ None ,
1549+ vec ! [ ] ,
1550+ true , // Produces QuorumStoreInlineHybridV2
1551+ ) ;
1552+ let error = hybrid_v2_payload
1553+ . verify_against_ordered_payload ( & v2_ordered_payload)
1554+ . unwrap_err ( ) ;
1555+ assert_matches ! ( error, Error :: InvalidMessageError ( _) ) ;
1556+
1557+ // Verify that the OptQuorumStoreV1 variant fails verification
1558+ let optqs_v1_payload =
1559+ BlockTransactionPayload :: new_opt_quorum_store ( vec ! [ ] , vec ! [ ] , None , None , vec ! [ ] ) ;
1560+ let error = optqs_v1_payload
1561+ . verify_against_ordered_payload ( & v2_ordered_payload)
1562+ . unwrap_err ( ) ;
1563+ assert_matches ! ( error, Error :: InvalidMessageError ( _) ) ;
1564+
1565+ // Verify that the OptQuorumStoreV2 variant with matching batches and limit passes verification
1566+ let optqs_v2_payload = BlockTransactionPayload :: new_opt_quorum_store_v2 (
1567+ vec ! [ ] ,
1568+ vec ! [ ] ,
1569+ Some ( 100 ) ,
1570+ None ,
1571+ vec ! [ ] ,
1572+ ) ;
1573+ optqs_v2_payload
1574+ . verify_against_ordered_payload ( & v2_ordered_payload)
1575+ . unwrap ( ) ;
1576+ }
1577+
1578+ #[ test]
1579+ fn test_verify_against_ordered_payload_optqs_v1_variant_mismatch ( ) {
1580+ // Build an empty V1 ordered block payload.
1581+ let v1_ordered_payload = Payload :: OptQuorumStore ( OptQuorumStorePayload :: new (
1582+ Vec :: < InlineBatch < BatchInfo > > :: new ( ) . into ( ) ,
1583+ Vec :: new ( ) . into ( ) ,
1584+ Vec :: < ProofOfStore < BatchInfo > > :: new ( ) . into ( ) ,
1585+ PayloadExecutionLimit :: MaxTransactionsToExecute ( 100 ) ,
1586+ ) ) ;
1587+
1588+ // Verify that an OptQuorumStoreV2 transaction payload returns InvalidMessageError
1589+ let optqs_v2_payload = BlockTransactionPayload :: new_opt_quorum_store_v2 (
1590+ vec ! [ ] ,
1591+ vec ! [ ] ,
1592+ Some ( 100 ) ,
1593+ None ,
1594+ vec ! [ ] ,
1595+ ) ;
1596+ let error = optqs_v2_payload
1597+ . verify_against_ordered_payload ( & v1_ordered_payload)
1598+ . unwrap_err ( ) ;
1599+ assert_matches ! ( error, Error :: InvalidMessageError ( _) ) ;
1600+ }
1601+
15161602 #[ test]
15171603 fn test_verify_commit_proof ( ) {
15181604 // Create a ledger info with an empty signature set
0 commit comments