Skip to content

Commit

Permalink
Include fixed integ tests in CI
Browse files Browse the repository at this point in the history
  • Loading branch information
Marzi committed Feb 26, 2024
1 parent b49e33f commit 525ba04
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/workflows/bitcoin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ jobs:
- tests::neon_integrations::size_overflow_unconfirmed_stream_microblocks_integration_test
- tests::neon_integrations::stx_delegate_btc_integration_test
- tests::neon_integrations::stx_transfer_btc_integration_test
- tests::neon_integrations::stack_stx_burn_op_test
- tests::neon_integrations::test_chainwork_first_intervals
- tests::neon_integrations::test_chainwork_partial_interval
- tests::neon_integrations::test_flash_block_skip_tenure
Expand All @@ -81,6 +82,7 @@ jobs:
- tests::signer::stackerdb_block_proposal
- tests::signer::stackerdb_filter_bad_transactions
- tests::signer::stackerdb_mine_2_nakamoto_reward_cycles
- tests::nakamoto_integrations::stack_stx_burn_op_integration_test
steps:
## Setup test environment
- name: Setup Test Environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,7 @@ impl BitcoinRegtestController {
) -> Option<Transaction> {
unimplemented!()
}

#[cfg(test)]
fn build_stack_stx_tx(
&mut self,
Expand Down Expand Up @@ -1211,6 +1212,8 @@ impl BitcoinRegtestController {
};

tx.output = vec![consensus_output];
tx.output
.push(payload.reward_addr.to_bitcoin_tx_out(DUST_UTXO_LIMIT));

self.finalize_tx(
epoch_id,
Expand Down
313 changes: 312 additions & 1 deletion testnet/stacks-node/src/tests/neon_integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ use stacks::burnchains::db::BurnchainDB;
use stacks::burnchains::{Address, Burnchain, PoxConstants, Txid};
use stacks::chainstate::burn::db::sortdb::SortitionDB;
use stacks::chainstate::burn::operations::{
BlockstackOperationType, DelegateStxOp, PreStxOp, TransferStxOp,
BlockstackOperationType, DelegateStxOp, PreStxOp, StackStxOp, TransferStxOp,
};
use stacks::chainstate::burn::ConsensusHash;
use stacks::chainstate::coordinator::comm::CoordinatorChannels;
use stacks::chainstate::stacks::address::PoxAddress;
use stacks::chainstate::stacks::db::StacksChainState;
use stacks::chainstate::stacks::miner::{
signal_mining_blocked, signal_mining_ready, TransactionErrorEvent, TransactionEvent,
Expand All @@ -40,6 +41,7 @@ use stacks::core::{
StacksEpoch, StacksEpochId, BLOCK_LIMIT_MAINNET_20, BLOCK_LIMIT_MAINNET_205,
BLOCK_LIMIT_MAINNET_21, CHAIN_ID_TESTNET, HELIUM_BLOCK_LIMIT_20, PEER_VERSION_EPOCH_1_0,
PEER_VERSION_EPOCH_2_0, PEER_VERSION_EPOCH_2_05, PEER_VERSION_EPOCH_2_1,
PEER_VERSION_EPOCH_2_2, PEER_VERSION_EPOCH_2_3, PEER_VERSION_EPOCH_2_4, PEER_VERSION_EPOCH_2_5,
};
use stacks::net::api::getaccount::AccountEntryResponse;
use stacks::net::api::getcontractsrc::ContractSrcResponse;
Expand All @@ -55,10 +57,15 @@ use stacks::net::atlas::{
};
use stacks::util_lib::boot::boot_code_id;
use stacks::util_lib::db::{query_row_columns, query_rows, u64_to_sql};
use stacks::util_lib::signed_structured_data::pox4::{
make_pox_4_signer_key_signature, Pox4SignatureTopic,
};
use stacks_common::address::AddressHashMode;
use stacks_common::codec::StacksMessageCodec;
use stacks_common::types::chainstate::{
BlockHeaderHash, BurnchainHeaderHash, StacksAddress, StacksBlockId,
};
use stacks_common::types::StacksPublicKeyBuffer;
use stacks_common::util::hash::{bytes_to_hex, hex_bytes, to_hex, Hash160};
use stacks_common::util::secp256k1::{Secp256k1PrivateKey, Secp256k1PublicKey};
use stacks_common::util::{get_epoch_time_ms, get_epoch_time_secs, sleep_ms};
Expand Down Expand Up @@ -2214,6 +2221,310 @@ fn stx_delegate_btc_integration_test() {
channel.stop_chains_coordinator();
}

#[test]
#[ignore]
fn stack_stx_burn_op_test() {
if env::var("BITCOIND_TEST") != Ok("1".into()) {
return;
}

let spender_sk = StacksPrivateKey::from_hex(SK_1).unwrap();
let spender_stx_addr: StacksAddress = to_addr(&spender_sk);
let spender_addr: PrincipalData = spender_stx_addr.clone().into();

let recipient_sk = StacksPrivateKey::new();
let recipient_addr = to_addr(&recipient_sk);
let pox_pubkey = Secp256k1PublicKey::from_hex(
"02f006a09b59979e2cb8449f58076152af6b124aa29b948a3714b8d5f15aa94ede",
)
.unwrap();
let _pox_pubkey_hash = bytes_to_hex(
&Hash160::from_node_public_key(&pox_pubkey)
.to_bytes()
.to_vec(),
);

let (mut conf, _miner_account) = neon_integration_test_conf();

let first_bal = 6_000_000_000 * (core::MICROSTACKS_PER_STACKS as u64);
let second_bal = 2_000_000_000 * (core::MICROSTACKS_PER_STACKS as u64);
let stacked_bal = 1_000_000_000 * (core::MICROSTACKS_PER_STACKS as u128);

conf.initial_balances.push(InitialBalance {
address: spender_addr.clone(),
amount: first_bal,
});
conf.initial_balances.push(InitialBalance {
address: recipient_addr.clone().into(),
amount: second_bal,
});

// update epoch info so that Epoch 2.1 takes effect
conf.burnchain.epochs = Some(vec![
StacksEpoch {
epoch_id: StacksEpochId::Epoch20,
start_height: 0,
end_height: 1,
block_limit: BLOCK_LIMIT_MAINNET_20.clone(),
network_epoch: PEER_VERSION_EPOCH_2_0,
},
StacksEpoch {
epoch_id: StacksEpochId::Epoch2_05,
start_height: 1,
end_height: 2,
block_limit: BLOCK_LIMIT_MAINNET_205.clone(),
network_epoch: PEER_VERSION_EPOCH_2_05,
},
StacksEpoch {
epoch_id: StacksEpochId::Epoch21,
start_height: 2,
end_height: 3,
block_limit: BLOCK_LIMIT_MAINNET_21.clone(),
network_epoch: PEER_VERSION_EPOCH_2_1,
},
StacksEpoch {
epoch_id: StacksEpochId::Epoch22,
start_height: 3,
end_height: 4,
block_limit: BLOCK_LIMIT_MAINNET_21.clone(),
network_epoch: PEER_VERSION_EPOCH_2_2,
},
StacksEpoch {
epoch_id: StacksEpochId::Epoch23,
start_height: 4,
end_height: 5,
block_limit: BLOCK_LIMIT_MAINNET_21.clone(),
network_epoch: PEER_VERSION_EPOCH_2_3,
},
StacksEpoch {
epoch_id: StacksEpochId::Epoch24,
start_height: 5,
end_height: 6,
block_limit: BLOCK_LIMIT_MAINNET_21.clone(),
network_epoch: PEER_VERSION_EPOCH_2_4,
},
StacksEpoch {
epoch_id: StacksEpochId::Epoch25,
start_height: 6,
end_height: 9223372036854775807,
block_limit: BLOCK_LIMIT_MAINNET_21.clone(),
network_epoch: PEER_VERSION_EPOCH_2_5,
},
]);
conf.burnchain.pox_2_activation = Some(3);

test_observer::spawn();
conf.events_observers.insert(EventObserverConfig {
endpoint: format!("localhost:{}", test_observer::EVENT_OBSERVER_PORT),
events_keys: vec![EventKeyType::AnyEvent],
});

let mut btcd_controller = BitcoinCoreController::new(conf.clone());
btcd_controller
.start_bitcoind()
.map_err(|_e| ())
.expect("Failed starting bitcoind");

let mut burnchain_config = Burnchain::regtest(&conf.get_burn_db_path());

// reward cycle length = 5, so 3 reward cycle slots + 2 prepare-phase burns
let reward_cycle_len = 5;
let prepare_phase_len = 2;
let pox_constants = PoxConstants::new(
reward_cycle_len,
prepare_phase_len,
2,
5,
15,
(16 * reward_cycle_len - 1).into(),
(17 * reward_cycle_len).into(),
u32::MAX,
u32::MAX,
u32::MAX,
u32::MAX,
);
burnchain_config.pox_constants = pox_constants.clone();

let mut btc_regtest_controller = BitcoinRegtestController::with_burnchain(
conf.clone(),
None,
Some(burnchain_config.clone()),
None,
);
let http_origin = format!("http://{}", &conf.node.rpc_bind);

btc_regtest_controller.bootstrap_chain(201);

eprintln!("Chain bootstrapped...");

let mut run_loop = neon::RunLoop::new(conf.clone());
let blocks_processed = run_loop.get_blocks_processed_arc();

let channel = run_loop.get_coordinator_channel().unwrap();

thread::spawn(move || run_loop.start(None, 0));

// give the run loop some time to start up!
wait_for_runloop(&blocks_processed);

test_observer::clear();

next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);

info!("Bootstrapped to 2.5, submitting stack-stx and pre-stx op...");

// setup stack-stx tx

let signer_sk = spender_sk.clone();
let signer_pk = StacksPublicKey::from_private(&signer_sk);

let pox_addr = PoxAddress::Standard(spender_stx_addr, Some(AddressHashMode::SerializeP2PKH));

let mut block_height = channel.get_sortitions_processed();

let reward_cycle = burnchain_config
.block_height_to_reward_cycle(block_height)
.unwrap();

// let signature = make_pox_4_signer_key_signature(
// &pox_addr,
// &signer_sk,
// reward_cycle.into(),
// &Pox4SignatureTopic::StackStx,
// CHAIN_ID_TESTNET,
// 12,
// )
// .unwrap();

let signer_pk_bytes = signer_pk.to_bytes_compressed();

// let stacking_tx = make_contract_call(
// &spender_sk,
// 0,
// 500,
// &StacksAddress::from_string("ST000000000000000000002AMW42H").unwrap(),
// "pox-4",
// "stack-stx",
// &[
// Value::UInt(stacked_bal),
// Value::Tuple(pox_addr.as_clarity_tuple().unwrap()),
// Value::UInt(block_height.into()),
// Value::UInt(12),
// Value::some(Value::buff_from(signature.to_rsv()).unwrap()).unwrap(),
// Value::buff_from(signer_pk_bytes.clone()).unwrap(),
// ],
// );

let mut miner_signer = Keychain::default(conf.node.seed.clone()).generate_op_signer();
let pre_stx_op = PreStxOp {
output: spender_stx_addr.clone(),
// to be filled in
txid: Txid([0u8; 32]),
vtxindex: 0,
block_height: 0,
burn_header_hash: BurnchainHeaderHash([0u8; 32]),
};

assert!(
btc_regtest_controller
.submit_operation(
StacksEpochId::Epoch25,
BlockstackOperationType::PreStx(pre_stx_op),
&mut miner_signer,
1
)
.is_some(),
"Pre-stx operation should submit successfully"
);

// push the stacking transaction
// submit_tx(&http_origin, &stacking_tx);

info!("Submitted stack-stx and pre-stx op at block {block_height}, mining a few blocks...");

// Wait a few blocks to be registered
for _i in 0..5 {
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
block_height = channel.get_sortitions_processed();
}

let reward_cycle = burnchain_config
.block_height_to_reward_cycle(block_height)
.unwrap();

let signer_key: StacksPublicKeyBuffer = signer_pk_bytes.clone().as_slice().into();

info!(
"Submitting stack stx op";
"block_height" => block_height,
"reward_cycle" => reward_cycle,
);

let stack_stx_op = BlockstackOperationType::StackStx(StackStxOp {
sender: spender_stx_addr.clone(),
reward_addr: pox_addr,
stacked_ustx: 100000,
num_cycles: 4,
signer_key: Some(signer_key),
// to be filled in
vtxindex: 0,
txid: Txid([0u8; 32]),
block_height: 0,
burn_header_hash: BurnchainHeaderHash::zero(),
});

let mut spender_signer = BurnchainOpSigner::new(signer_sk.clone(), false);
assert!(
btc_regtest_controller
.submit_operation(StacksEpochId::Epoch25, stack_stx_op, &mut spender_signer, 1)
.is_some(),
"Stack STX operation should submit successfully"
);

info!("Submitted stack STX op at height {block_height}, mining a few blocks...");

// the second block should process the vote, after which the balaces should be unchanged
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);

let mut stack_stx_found = false;
let blocks = test_observer::get_blocks();
info!("stack event observer num blocks: {:?}", blocks.len());
for block in blocks.iter() {
let transactions = block.get("transactions").unwrap().as_array().unwrap();
info!(
"stack event observer num transactions: {:?}",
transactions.len()
);
for tx in transactions.iter() {
let raw_tx = tx.get("raw_tx").unwrap().as_str().unwrap();
if raw_tx == "0x00" {
info!("Found a burn op: {:?}", tx);
let burnchain_op = tx.get("burnchain_op").unwrap().as_object().unwrap();
if !burnchain_op.contains_key("stack_stx") {
warn!("Got unexpected burnchain op: {:?}", burnchain_op);
panic!("unexpected btc transaction type");
}
let stack_stx_obj = burnchain_op.get("stack_stx").unwrap();
let signer_key_found = stack_stx_obj
.get("signer_key")
.expect("Expected signer_key in burn op")
.as_str()
.unwrap();
assert_eq!(signer_key_found, signer_key.to_hex());

stack_stx_found = true;
}
}
}
assert!(stack_stx_found, "Expected stack STX op");

test_observer::clear();
channel.stop_chains_coordinator();
}

#[test]
#[ignore]
fn bitcoind_resubmission_test() {
Expand Down

0 comments on commit 525ba04

Please sign in to comment.