Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable payload continue #8

Merged
112 changes: 112 additions & 0 deletions testing/integration/src/consensus_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ use std::{
io::{BufRead, BufReader},
str::{from_utf8, FromStr},
};
use kaspa_consensus_core::errors::tx::TxRuleError;

#[derive(Serialize, Deserialize, Debug)]
struct JsonBlock {
Expand Down Expand Up @@ -1903,3 +1904,114 @@ async fn payload_test() {

consensus.shutdown(wait_handles);
}

#[tokio::test]
async fn run_payload_activation_test() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need for run_ in test names

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit 2df7765

use kaspa_consensus_core::subnets::SUBNETWORK_ID_NATIVE;

// Set payload activation at DAA score 3 for this test
const PAYLOAD_ACTIVATION_DAA_SCORE: u64 = 3;

init_allocator_with_default_settings();

// Create initial UTXO to fund our test transactions
let initial_utxo_collection = [(
TransactionOutpoint::new(1.into(), 0),
UtxoEntry {
amount: SOMPI_PER_KASPA,
script_public_key: ScriptPublicKey::from_vec(0, vec![OpTrue]),
block_daa_score: 0,
is_coinbase: false
},
)];

// Initialize consensus with payload activation point
let config = ConfigBuilder::new(DEVNET_PARAMS)
.skip_proof_of_work()
.apply_args(|cfg| {
let mut genesis_multiset = MuHash::new();
initial_utxo_collection.iter().for_each(|(outpoint, utxo)| {
genesis_multiset.add_utxo(outpoint, utxo);
});
cfg.params.genesis.utxo_commitment = genesis_multiset.finalize();
let genesis_header: Header = (&cfg.params.genesis).into();
cfg.params.genesis.hash = genesis_header.hash;
})
.edit_consensus_params(|p| {
p.payload_activation = ForkActivation::new(PAYLOAD_ACTIVATION_DAA_SCORE);
})
.build();

let consensus = TestConsensus::new(&config);
let mut genesis_multiset = MuHash::new();
consensus.append_imported_pruning_point_utxos(&initial_utxo_collection, &mut genesis_multiset);
consensus.import_pruning_point_utxo_set(config.genesis.hash, genesis_multiset).unwrap();
consensus.init();

// Build blockchain up to one block before activation
let mut index = 0;
for _ in 0..PAYLOAD_ACTIVATION_DAA_SCORE - 1 {
let parent = if index == 0 { config.genesis.hash } else { index.into() };
consensus.add_utxo_valid_block_with_parents((index + 1).into(), vec![parent], vec![]).await.unwrap();
index += 1;
}
assert_eq!(consensus.get_virtual_daa_score(), index);

// Create transaction with large payload
let large_payload = vec![0u8; (config.params.max_block_mass / 2) as usize];
let mut tx_with_payload = Transaction::new(
0,
vec![TransactionInput::new(
initial_utxo_collection[0].0,
vec![], // Empty signature script since we're using OpTrue
0,
0,
)],
vec![TransactionOutput::new(
initial_utxo_collection[0].1.amount - 5000,
ScriptPublicKey::from_vec(0, vec![OpTrue])
)],
0,
SUBNETWORK_ID_NATIVE,
0,
large_payload,
);
tx_with_payload.finalize();
let tx_id = tx_with_payload.id();

// Test 1: Build empty block, then manually insert invalid tx and verify consensus rejects it
{
let miner_data = MinerData::new(ScriptPublicKey::from_vec(0, vec![]), vec![]);

// First build block without transactions
let mut block = consensus.build_utxo_valid_block_with_parents(
(index + 1).into(),
vec![index.into()],
miner_data.clone(),
vec![],
);

// Insert our test transaction and recalculate block hashes
block.transactions.push(tx_with_payload.clone());

block.header.hash_merkle_root = calc_hash_merkle_root(block.transactions.iter(), false);
let block_status = consensus.validate_and_insert_block(block.to_immutable()).virtual_state_task.await;
assert!(matches!(block_status, Err(RuleError::TxInContextFailed(tx, TxRuleError::NonCoinbaseTxHasPayload)) if tx == tx_id));
assert_eq!(consensus.lkg_virtual_state.load().daa_score, PAYLOAD_ACTIVATION_DAA_SCORE - 1);
index += 1;
}

// Add one more block to reach activation score
consensus.add_utxo_valid_block_with_parents((index + 1).into(), vec![(index - 1).into()], vec![]).await.unwrap();
index += 1;

// Test 2: Verify the same transaction is accepted after activation
let status = consensus.add_utxo_valid_block_with_parents(
(index + 1).into(),
vec![index.into()],
vec![tx_with_payload.clone()]
).await;

assert!(matches!(status, Ok(BlockStatus::StatusUTXOValid)));
assert!(consensus.lkg_virtual_state.load().accepted_tx_ids.contains(&tx_id));
}