Merge remote-tracking branch 'origin/3481-sbtc-peg-in-wire-formats' into feat/sbtc-burn-ops-rpc

This commit is contained in:
Aaron Blankstein
2023-01-19 13:03:34 -06:00
3 changed files with 181 additions and 3 deletions

View File

@@ -20,8 +20,8 @@ impl PegInOp {
}
let (amount, peg_wallet_address) =
if let Some(Some(recepient)) = tx.get_recipients().first() {
(recepient.amount, recepient.address.clone())
if let Some(Some(recipient)) = tx.get_recipients().first() {
(recipient.amount, recipient.address.clone())
} else {
warn!("Invalid tx: Output 2 not provided");
return Err(OpError::InvalidInput);

View File

@@ -38,7 +38,7 @@ use crate::chainstate::burn::operations::leader_block_commit::*;
use crate::chainstate::burn::operations::*;
use crate::chainstate::burn::*;
use crate::chainstate::coordinator::{Error as CoordError, *};
use crate::chainstate::stacks::address::PoxAddress;
use crate::chainstate::stacks::address::{PoxAddress, PoxAddressType32};
use crate::chainstate::stacks::boot::PoxStartCycleInfo;
use crate::chainstate::stacks::boot::POX_1_NAME;
use crate::chainstate::stacks::boot::POX_2_NAME;
@@ -3236,6 +3236,183 @@ fn test_stx_transfer_btc_ops() {
}
}
#[test]
fn test_sbtc_peg_in_btc_op() {
let path = "/tmp/stacks-blockchain-sbtc-peg-in-btc-ops";
let _r = std::fs::remove_dir_all(path);
let pox_v1_unlock_ht = 12;
let sunset_ht = 8000;
let pox_consts = Some(PoxConstants::new(
100,
3,
3,
25,
5,
7010,
sunset_ht,
pox_v1_unlock_ht,
));
let burnchain_conf = get_burnchain(path, pox_consts.clone());
let vrf_keys: Vec<_> = (0..50).map(|_| VRFPrivateKey::new()).collect();
let committers: Vec<_> = (0..50).map(|_| StacksPrivateKey::new()).collect();
let stacker = p2pkh_from(&StacksPrivateKey::new());
let recipient = p2pkh_from(&StacksPrivateKey::new());
let balance = 6_000_000_000 * (core::MICROSTACKS_PER_STACKS as u64);
let transfer_amt = 1_000_000_000 * (core::MICROSTACKS_PER_STACKS as u128);
let initial_balances = vec![(stacker.clone().into(), balance)];
setup_states(
&[path],
&vrf_keys,
&committers,
pox_consts.clone(),
Some(initial_balances),
StacksEpochId::Epoch21,
);
let mut coord = make_coordinator(path, Some(burnchain_conf.clone()));
coord.handle_new_burnchain_block().unwrap();
let sort_db = get_sortition_db(path, pox_consts.clone());
let tip = SortitionDB::get_canonical_burn_chain_tip(sort_db.conn()).unwrap();
assert_eq!(tip.block_height, 1);
assert_eq!(tip.sortition, false);
let (_, ops) = sort_db
.get_sortition_result(&tip.sortition_id)
.unwrap()
.unwrap();
// we should have all the VRF registrations accepted
assert_eq!(ops.accepted_ops.len(), vrf_keys.len());
assert_eq!(ops.consumed_leader_keys.len(), 0);
// process sequential blocks, and their sortitions...
let mut stacks_blocks: Vec<(SortitionId, StacksBlock)> = vec![];
let mut burnchain_block_hashes = vec![];
for ix in 0..vrf_keys.len() {
let vrf_key = &vrf_keys[ix];
let miner = &committers[ix];
let mut burnchain = get_burnchain_db(path, pox_consts.clone());
let mut chainstate = get_chainstate(path);
let parent = if ix == 0 {
BlockHeaderHash([0; 32])
} else {
stacks_blocks[ix - 1].1.header.block_hash()
};
let burnchain_tip = burnchain.get_canonical_chain_tip().unwrap();
let next_mock_header = BurnchainBlockHeader {
block_height: burnchain_tip.block_height + 1,
block_hash: BurnchainHeaderHash([0; 32]),
parent_block_hash: burnchain_tip.block_hash,
num_txs: 0,
timestamp: 1,
};
let b = get_burnchain(path, pox_consts.clone());
let (good_op, block) = if ix == 0 {
make_genesis_block_with_recipients(
&sort_db,
&mut chainstate,
&parent,
miner,
10000,
vrf_key,
ix as u32,
None,
)
} else {
make_stacks_block_with_recipients(
&sort_db,
&mut chainstate,
&b,
&parent,
burnchain_tip.block_height,
miner,
1000,
vrf_key,
ix as u32,
None,
)
};
let expected_winner = good_op.txid();
let mut ops = vec![good_op];
let peg_wallet_address = PoxAddress::Addr32(false, PoxAddressType32::P2TR, [0; 32]);
if ix == 0 {
// add a peg-in op
ops.push(BlockstackOperationType::PegIn(PegInOp {
recipient: stacker,
recipient_contract_name: None,
peg_wallet_address,
amount: 1337,
txid: next_txid(),
vtxindex: 5,
block_height: 0,
burn_header_hash: BurnchainHeaderHash([0; 32]),
}));
} else if ix == 1 {
// shouldn't be accepted -- amount must be positive
ops.push(BlockstackOperationType::PegIn(PegInOp {
recipient: stacker,
recipient_contract_name: None,
peg_wallet_address,
amount: 0,
txid: next_txid(),
vtxindex: 5,
block_height: 0,
burn_header_hash: BurnchainHeaderHash([0; 32]),
}));
}
let burnchain_tip = burnchain.get_canonical_chain_tip().unwrap();
produce_burn_block(
&b,
&mut burnchain,
&burnchain_tip.block_hash,
ops,
vec![].iter_mut(),
);
burnchain_block_hashes.push(burnchain_tip.block_hash);
// handle the sortition
coord.handle_new_burnchain_block().unwrap();
let tip = SortitionDB::get_canonical_burn_chain_tip(sort_db.conn()).unwrap();
assert_eq!(&tip.winning_block_txid, &expected_winner);
// load the block into staging
let block_hash = block.header.block_hash();
assert_eq!(&tip.winning_stacks_block_hash, &block_hash);
stacks_blocks.push((tip.sortition_id.clone(), block.clone()));
preprocess_block(&mut chainstate, &sort_db, &tip, block);
// handle the stacks block
coord.handle_new_stacks_block().unwrap();
}
let total_number_of_peg_in_ops = burnchain_block_hashes
.into_iter()
.flat_map(|block_hash| {
SortitionDB::get_peg_in_ops(&sort_db.conn(), &block_hash)
.expect("Failed to get peg in ops")
})
.count();
assert_eq!(total_number_of_peg_in_ops, 1);
}
// This helper function retrieves the delegation info from the delegate address
// from the pox-2 contract.
// Given an address, it retrieves the fields `amount-ustx` and `pox-addr` from the map

View File

@@ -10470,6 +10470,7 @@ fn test_submit_and_observe_peg_in_request() {
// Let's send a Peg-in op.
let peg_in_op = PegInOp {
recipient: receiver_stx_addr,
recipient_contract_name: None,
peg_wallet_address,
amount: 1337,
txid: Txid([0u8; 32]),