From 51892ef76eb689e8bc3d176713424654042c56f7 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:57:58 +0100 Subject: [PATCH] fix(drive-abci): verify apphash in finalize_block --- .../engine/finalize_block_proposal/v0/mod.rs | 5 ++++- .../src/execution/types/block_state_info/mod.rs | 2 ++ .../src/execution/types/block_state_info/v0/mod.rs | 13 ++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs index c8d71074316..c4b5aac7f71 100644 --- a/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs @@ -104,17 +104,20 @@ where block_header.core_chain_locked_height, block_header.proposer_pro_tx_hash, hash, + block_header.app_hash, )? { // we are on the wrong height or round validation_result.add_error(AbciError::WrongFinalizeBlockReceived(format!( - "received a block for h: {} r: {}, block hash: {}, core height: {}, expected h: {} r: {}, block hash: {}, core height: {}", + "received a block for h: {} r: {}, block hash: {}, app_hash: {}, core height: {}, expected h: {} r: {}, block hash: {}, app_hash: {}, core height: {}", height, round, hex::encode(hash), + hex::encode(block_header.app_hash), block_header.core_chain_locked_height, block_state_info.height(), block_state_info.round(), block_state_info.block_hash().map(hex::encode).unwrap_or("None".to_string()), + hex::encode(block_state_info.app_hash().unwrap_or_default()), block_state_info.core_chain_locked_height() ))); return Ok(validation_result.into()); diff --git a/packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs b/packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs index 684bcaaa569..8eb714a5979 100644 --- a/packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs @@ -168,6 +168,7 @@ impl BlockStateInfoV0Methods for BlockStateInfo { core_block_height: u32, proposer_pro_tx_hash: [u8; 32], commit_hash: I, + app_hash: I, ) -> Result { match self { BlockStateInfo::V0(v0) => v0.matches_expected_block_info( @@ -176,6 +177,7 @@ impl BlockStateInfoV0Methods for BlockStateInfo { core_block_height, proposer_pro_tx_hash, commit_hash, + app_hash, ), } } diff --git a/packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs b/packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs index 8e3b405e651..dbdaf366c00 100644 --- a/packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs @@ -100,6 +100,7 @@ pub trait BlockStateInfoV0Methods { core_block_height: u32, proposer_pro_tx_hash: [u8; 32], commit_hash: I, + app_hash: I, ) -> Result; } @@ -151,12 +152,18 @@ impl BlockStateInfoV0Methods for BlockStateInfoV0 { core_block_height: u32, proposer_pro_tx_hash: [u8; 32], commit_hash: I, + app_hash: I, ) -> Result { let received_hash = commit_hash.try_into().map_err(|_| { Error::Abci(AbciError::BadRequestDataSize( "can't convert hash as vec to [u8;32]".to_string(), )) })?; + let received_app_hash = app_hash.try_into().map_err(|_| { + Error::Abci(AbciError::BadRequestDataSize( + "can't convert app hash as vec to [u8;32]".to_string(), + )) + })?; // the order is important here, don't verify commit hash before height and round tracing::trace!( self=?self, @@ -165,14 +172,18 @@ impl BlockStateInfoV0Methods for BlockStateInfoV0 { ?core_block_height, proposer_pro_tx_hash = hex::encode(proposer_pro_tx_hash), commit_hash = hex::encode(received_hash), + app_hash = hex::encode(received_app_hash), "check if block info matches request" ); + Ok(self.height == height && self.round == round && self.core_chain_locked_height == core_block_height && self.proposer_pro_tx_hash == proposer_pro_tx_hash && self.block_hash.is_some() - && self.block_hash.unwrap() == received_hash) + && self.block_hash.unwrap() == received_hash + && self.app_hash.is_some() + && self.app_hash.unwrap_or_default() == received_app_hash) } }