Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,131 @@ where
}
}
}

#[cfg(test)]
mod tests {
use crate::execution::types::block_execution_context::v0::BlockExecutionContextV0;
use crate::execution::types::block_execution_context::BlockExecutionContext;
use crate::execution::types::block_state_info::v0::BlockStateInfoV0;
use crate::execution::types::block_state_info::BlockStateInfo;
use crate::platform_types::epoch_info::v0::EpochInfoV0;
use crate::platform_types::epoch_info::EpochInfo;
use crate::platform_types::withdrawal::unsigned_withdrawal_txs::v0::UnsignedWithdrawalTxs;
use crate::test::helpers::setup::TestPlatformBuilder;
use dpp::version::PlatformVersion;
use std::collections::BTreeMap;

fn make_block_execution_context(height: u64, block_time_ms: u64) -> BlockExecutionContext {
let platform_version = PlatformVersion::latest();
let platform_state =
crate::platform_types::platform_state::PlatformState::default_with_protocol_versions(
platform_version.protocol_version,
platform_version.protocol_version,
&crate::config::PlatformConfig::default_for_network(
dpp::dashcore::Network::Testnet,
),
)
.expect("expected platform state");

BlockExecutionContext::V0(BlockExecutionContextV0 {
block_state_info: BlockStateInfo::V0(BlockStateInfoV0 {
height,
round: 0,
block_time_ms,
previous_block_time_ms: None,
proposer_pro_tx_hash: [0u8; 32],
core_chain_locked_height: 1,
block_hash: None,
app_hash: None,
}),
epoch_info: EpochInfo::V0(EpochInfoV0 {
current_epoch_index: 0,
previous_epoch_index: None,
is_epoch_change: false,
}),
unsigned_withdrawal_transactions: UnsignedWithdrawalTxs::default(),
block_address_balance_changes: BTreeMap::new(),
block_platform_state: platform_state,
proposer_results: None,
})
}

#[test]
fn test_first_block_should_always_checkpoint() {
let platform_version = PlatformVersion::latest();
let platform_config = crate::config::PlatformConfig {
testing_configs: crate::config::PlatformTestConfig {
disable_checkpoints: false,
..Default::default()
},
..Default::default()
};
let platform = TestPlatformBuilder::new()
.with_config(platform_config)
.build_with_mock_rpc()
.set_genesis_state();

// With no existing checkpoints and checkpoint feature enabled (v7+),
// the first block should trigger a checkpoint
if platform_version
.drive_abci
.methods
.block_end
.should_checkpoint
.is_none()
{
// If checkpoints are disabled in this version, skip
return;
}

let block_execution_context = make_block_execution_context(1, 1_000_000);
let result = platform
.should_checkpoint_v0(&block_execution_context, platform_version)
.expect("expected Ok");

// When there are no checkpoints, it should return Some (checkpoint needed)
assert!(result.is_some(), "first block should trigger checkpoint");
}

#[test]
fn test_checkpoint_interval_zero_returns_none() {
let platform_version = PlatformVersion::latest();
let platform = TestPlatformBuilder::new()
.build_with_mock_rpc()
.set_genesis_state();

let mut modified_version = platform_version.clone();
modified_version.drive_abci.checkpoints.frequency_seconds = 0;

let block_execution_context = make_block_execution_context(1, 1_000_000);
let result = platform
.should_checkpoint_v0(&block_execution_context, &modified_version)
.expect("expected Ok");

assert!(
result.is_none(),
"should return None when frequency is zero"
);
}

#[test]
fn test_num_checkpoints_zero_returns_none() {
let platform_version = PlatformVersion::latest();
let platform = TestPlatformBuilder::new()
.build_with_mock_rpc()
.set_genesis_state();

let mut modified_version = platform_version.clone();
modified_version.drive_abci.checkpoints.num_checkpoints = 0;

let block_execution_context = make_block_execution_context(1, 1_000_000);
let result = platform
.should_checkpoint_v0(&block_execution_context, &modified_version)
.expect("expected Ok");

assert!(
result.is_none(),
"should return None when num_checkpoints is zero"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,120 @@ mod tests {
use rand::SeedableRng;
use std::collections::BTreeMap;

#[test]
fn test_choose_quorum_v0_empty_quorums_returns_none() {
let quorums = BTreeMap::new();
let request_id = [0u8; 32];

let result = Platform::<MockCoreRPCLike>::choose_quorum_v0(
QuorumType::Llmq50_60,
&quorums,
&request_id,
);

assert!(result.is_none());
}

#[test]
fn test_choose_quorum_thread_safe_v0_empty_quorums_returns_none() {
let quorums: BTreeMap<QuorumHash, [u8; 48]> = BTreeMap::new();
let request_id = [0u8; 32];

let result = Platform::<MockCoreRPCLike>::choose_quorum_thread_safe_v0(
QuorumType::Llmq50_60,
&quorums,
&request_id,
);

assert!(result.is_none());
}

#[test]
fn test_choose_quorum_thread_safe_v0_single_quorum() {
let quorum_hash = QuorumHash::from_slice(
hex::decode("000000dc07d722238a994116c3395c334211d9864ff5b37c3be51d5fdda66223")
.expect("valid hex")
.as_slice(),
)
.expect("valid quorum hash");

let key = [42u8; 48];
let quorums = BTreeMap::from([(quorum_hash, key)]);
let request_id = [1u8; 32];

let result = Platform::<MockCoreRPCLike>::choose_quorum_thread_safe_v0(
QuorumType::Llmq50_60,
&quorums,
&request_id,
);

let (_, returned_key) = result.expect("expected quorum selection for single quorum");
assert_eq!(*returned_key, key);
}

#[test]
fn test_choose_quorum_thread_safe_v0_deterministic() {
let quorum_hash1 = QuorumHash::from_slice(
hex::decode("000000dc07d722238a994116c3395c334211d9864ff5b37c3be51d5fdda66223")
.expect("valid hex")
.as_slice(),
)
.expect("valid quorum hash");
let quorum_hash2 = QuorumHash::from_slice(
hex::decode("000000bd5639c21dd8abf60253c3fe0343d87a9762b5b8f57e2b4ea1523fd071")
.expect("valid hex")
.as_slice(),
)
.expect("valid quorum hash");

let key1 = [1u8; 48];
let key2 = [2u8; 48];
let quorums = BTreeMap::from([(quorum_hash1, key1), (quorum_hash2, key2)]);
let request_id = [42u8; 32];

// Call twice with same inputs - should be deterministic
let result1 = Platform::<MockCoreRPCLike>::choose_quorum_thread_safe_v0(
QuorumType::Llmq50_60,
&quorums,
&request_id,
)
.expect("expected quorum selection on first call");
let result2 = Platform::<MockCoreRPCLike>::choose_quorum_thread_safe_v0(
QuorumType::Llmq50_60,
&quorums,
&request_id,
)
.expect("expected quorum selection on second call");

assert_eq!(result1.0, result2.0);
}

#[test]
fn test_choose_quorum_v0_single_quorum() {
let quorum_hash = QuorumHash::from_slice(
hex::decode("000000dc07d722238a994116c3395c334211d9864ff5b37c3be51d5fdda66223")
.expect("valid hex")
.as_slice(),
)
.expect("valid quorum hash");

let mut rng = StdRng::seed_from_u64(42);
let key = SecretKey::random(&mut rng).public_key();
let quorums = BTreeMap::from([(quorum_hash, key)]);
let request_id = [1u8; 32];

let result = Platform::<MockCoreRPCLike>::choose_quorum_v0(
QuorumType::Llmq50_60,
&quorums,
&request_id,
);

assert!(
result.is_some(),
"expected quorum selection for single quorum"
);
}

#[test]
fn test_choose_quorum() {
// Active quorums:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,8 @@ where
})
}
}

// Tests removed: the production method `make_sure_core_is_synced_to_chain_lock_v0` requires
// a Platform<C> whose `core_rpc` has mock expectations configured before construction.
// The previous tests created mocks but never called the production method, only testing
// inline if/else arithmetic. Real integration coverage belongs in higher-level tests.
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,9 @@ where
}
}
}

// Tests removed: all 4 tests only exercised mock wiring by calling methods directly on
// MockCoreRPCLike, never invoking the production method `verify_chain_lock_through_core_v0`.
// The production method requires a Platform<C> whose `core_rpc` has mock expectations
// configured before construction, which is impractical for isolated unit tests.
// Real integration coverage belongs in higher-level tests.
Loading
Loading