@@ -34,7 +34,8 @@ use rand::RngCore;
34
34
use stacks:: burnchains:: { MagicBytes , Txid } ;
35
35
use stacks:: chainstate:: burn:: db:: sortdb:: SortitionDB ;
36
36
use stacks:: chainstate:: burn:: operations:: {
37
- BlockstackOperationType , PreStxOp , StackStxOp , VoteForAggregateKeyOp ,
37
+ BlockstackOperationType , DelegateStxOp , PreStxOp , StackStxOp , TransferStxOp ,
38
+ VoteForAggregateKeyOp ,
38
39
} ;
39
40
use stacks:: chainstate:: coordinator:: comm:: CoordinatorChannels ;
40
41
use stacks:: chainstate:: coordinator:: OnChainRewardSetProvider ;
@@ -4012,7 +4013,17 @@ fn follower_bootup_across_multiple_cycles() {
4012
4013
4013
4014
#[ test]
4014
4015
#[ ignore]
4015
- fn stack_stx_burn_op_integration_test ( ) {
4016
+ /// Test out various burn operations being processed in Nakamoto.
4017
+ ///
4018
+ /// There are 4 burn ops submitted:
4019
+ ///
4020
+ /// - stx-transfer
4021
+ /// - delegate-stx
4022
+ /// - stack-stx
4023
+ ///
4024
+ /// Additionally, a stack-stx without a signer key is submitted, which should
4025
+ /// not be processed in Nakamoto.
4026
+ fn burn_ops_integration_test ( ) {
4016
4027
if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
4017
4028
return ;
4018
4029
}
@@ -4027,10 +4038,26 @@ fn stack_stx_burn_op_integration_test() {
4027
4038
let signer_sk_2 = Secp256k1PrivateKey :: new ( ) ;
4028
4039
let signer_addr_2 = tests:: to_addr ( & signer_sk_2) ;
4029
4040
4041
+ let stacker_sk_1 = Secp256k1PrivateKey :: new ( ) ;
4042
+ let stacker_addr_1 = tests:: to_addr ( & stacker_sk_1) ;
4043
+
4044
+ let stacker_sk_2 = Secp256k1PrivateKey :: new ( ) ;
4045
+ let stacker_addr_2 = tests:: to_addr ( & stacker_sk_2) ;
4046
+
4030
4047
let mut signers = TestSigners :: new ( vec ! [ signer_sk_1. clone( ) ] ) ;
4031
4048
4032
4049
let stacker_sk = setup_stacker ( & mut naka_conf) ;
4033
4050
4051
+ // Add the initial balances to the other accounts
4052
+ naka_conf. add_initial_balance (
4053
+ PrincipalData :: from ( stacker_addr_1. clone ( ) ) . to_string ( ) ,
4054
+ 1000000 ,
4055
+ ) ;
4056
+ naka_conf. add_initial_balance (
4057
+ PrincipalData :: from ( stacker_addr_2. clone ( ) ) . to_string ( ) ,
4058
+ 1000000 ,
4059
+ ) ;
4060
+
4034
4061
test_observer:: spawn ( ) ;
4035
4062
let observer_port = test_observer:: EVENT_OBSERVER_PORT ;
4036
4063
naka_conf. events_observers . insert ( EventObserverConfig {
@@ -4135,7 +4162,49 @@ fn stack_stx_burn_op_integration_test() {
4135
4162
. is_ok( ) ,
4136
4163
"Pre-stx operation should submit successfully"
4137
4164
) ;
4138
- info ! ( "Submitted 2 pre-stx ops at block {block_height}, mining a few blocks..." ) ;
4165
+
4166
+ let mut miner_signer_3 = Keychain :: default ( naka_conf. node . seed . clone ( ) ) . generate_op_signer ( ) ;
4167
+ info ! ( "Submitting third pre-stx op" ) ;
4168
+ let pre_stx_op_3 = PreStxOp {
4169
+ output : stacker_addr_1. clone ( ) ,
4170
+ txid : Txid ( [ 0u8 ; 32 ] ) ,
4171
+ vtxindex : 0 ,
4172
+ block_height : 0 ,
4173
+ burn_header_hash : BurnchainHeaderHash ( [ 0u8 ; 32 ] ) ,
4174
+ } ;
4175
+ assert ! (
4176
+ btc_regtest_controller
4177
+ . submit_operation(
4178
+ StacksEpochId :: Epoch30 ,
4179
+ BlockstackOperationType :: PreStx ( pre_stx_op_3) ,
4180
+ & mut miner_signer_3,
4181
+ 1
4182
+ )
4183
+ . is_ok( ) ,
4184
+ "Pre-stx operation should submit successfully"
4185
+ ) ;
4186
+
4187
+ info ! ( "Submitting fourth pre-stx op" ) ;
4188
+ let mut miner_signer_4 = Keychain :: default ( naka_conf. node . seed . clone ( ) ) . generate_op_signer ( ) ;
4189
+ let pre_stx_op_4 = PreStxOp {
4190
+ output : stacker_addr_2. clone ( ) ,
4191
+ txid : Txid ( [ 0u8 ; 32 ] ) ,
4192
+ vtxindex : 0 ,
4193
+ block_height : 0 ,
4194
+ burn_header_hash : BurnchainHeaderHash ( [ 0u8 ; 32 ] ) ,
4195
+ } ;
4196
+ assert ! (
4197
+ btc_regtest_controller
4198
+ . submit_operation(
4199
+ StacksEpochId :: Epoch30 ,
4200
+ BlockstackOperationType :: PreStx ( pre_stx_op_4) ,
4201
+ & mut miner_signer_4,
4202
+ 1
4203
+ )
4204
+ . is_ok( ) ,
4205
+ "Pre-stx operation should submit successfully"
4206
+ ) ;
4207
+ info ! ( "Submitted 4 pre-stx ops at block {block_height}, mining a few blocks..." ) ;
4139
4208
4140
4209
// Mine until the next prepare phase
4141
4210
let block_height = btc_regtest_controller. get_headers_height ( ) ;
@@ -4216,6 +4285,8 @@ fn stack_stx_burn_op_integration_test() {
4216
4285
4217
4286
let mut signer_burnop_signer_1 = BurnchainOpSigner :: new ( signer_sk_1. clone ( ) , false ) ;
4218
4287
let mut signer_burnop_signer_2 = BurnchainOpSigner :: new ( signer_sk_2. clone ( ) , false ) ;
4288
+ let mut stacker_burnop_signer_1 = BurnchainOpSigner :: new ( stacker_sk_1. clone ( ) , false ) ;
4289
+ let mut stacker_burnop_signer_2 = BurnchainOpSigner :: new ( stacker_sk_2. clone ( ) , false ) ;
4219
4290
4220
4291
info ! (
4221
4292
"Before stack-stx op, signer 1 total: {}" ,
@@ -4247,6 +4318,55 @@ fn stack_stx_burn_op_integration_test() {
4247
4318
info ! ( "Signer 1 addr: {}" , signer_addr_1. to_b58( ) ) ;
4248
4319
info ! ( "Signer 2 addr: {}" , signer_addr_2. to_b58( ) ) ;
4249
4320
4321
+ info ! ( "Submitting transfer STX op" ) ;
4322
+ let transfer_stx_op = TransferStxOp {
4323
+ sender : stacker_addr_1. clone ( ) ,
4324
+ recipient : stacker_addr_2. clone ( ) ,
4325
+ transfered_ustx : 10000 ,
4326
+ memo : vec ! [ ] ,
4327
+ txid : Txid ( [ 0u8 ; 32 ] ) ,
4328
+ vtxindex : 0 ,
4329
+ block_height : 0 ,
4330
+ burn_header_hash : BurnchainHeaderHash ( [ 0u8 ; 32 ] ) ,
4331
+ } ;
4332
+ assert ! (
4333
+ btc_regtest_controller
4334
+ . submit_operation(
4335
+ StacksEpochId :: Epoch30 ,
4336
+ BlockstackOperationType :: TransferStx ( transfer_stx_op) ,
4337
+ & mut stacker_burnop_signer_1,
4338
+ 1
4339
+ )
4340
+ . is_ok( ) ,
4341
+ "Transfer STX operation should submit successfully"
4342
+ ) ;
4343
+
4344
+ info ! ( "Submitting delegate STX op" ) ;
4345
+ let del_stx_op = DelegateStxOp {
4346
+ sender : stacker_addr_2. clone ( ) ,
4347
+ delegate_to : stacker_addr_1. clone ( ) ,
4348
+ reward_addr : None ,
4349
+ delegated_ustx : 100_000 ,
4350
+ // to be filled in
4351
+ txid : Txid ( [ 0u8 ; 32 ] ) ,
4352
+ vtxindex : 0 ,
4353
+ block_height : 0 ,
4354
+ burn_header_hash : BurnchainHeaderHash ( [ 0u8 ; 32 ] ) ,
4355
+ until_burn_height : None ,
4356
+ } ;
4357
+
4358
+ assert ! (
4359
+ btc_regtest_controller
4360
+ . submit_operation(
4361
+ StacksEpochId :: Epoch30 ,
4362
+ BlockstackOperationType :: DelegateStx ( del_stx_op) ,
4363
+ & mut stacker_burnop_signer_2,
4364
+ 1
4365
+ )
4366
+ . is_ok( ) ,
4367
+ "Delegate STX operation should submit successfully"
4368
+ ) ;
4369
+
4250
4370
let pox_info = get_pox_info ( & http_origin) . unwrap ( ) ;
4251
4371
let min_stx = pox_info. next_cycle . min_threshold_ustx ;
4252
4372
@@ -4318,6 +4438,8 @@ fn stack_stx_burn_op_integration_test() {
4318
4438
}
4319
4439
4320
4440
let mut stack_stx_found = false ;
4441
+ let mut transfer_stx_found = false ;
4442
+ let mut delegate_stx_found = false ;
4321
4443
let mut stack_stx_burn_op_tx_count = 0 ;
4322
4444
let blocks = test_observer:: get_blocks ( ) ;
4323
4445
info ! ( "stack event observer num blocks: {:?}" , blocks. len( ) ) ;
@@ -4332,6 +4454,45 @@ fn stack_stx_burn_op_integration_test() {
4332
4454
if raw_tx == "0x00" {
4333
4455
info ! ( "Found a burn op: {:?}" , tx) ;
4334
4456
let burnchain_op = tx. get ( "burnchain_op" ) . unwrap ( ) . as_object ( ) . unwrap ( ) ;
4457
+ if burnchain_op. contains_key ( "transfer_stx" ) {
4458
+ let transfer_stx_obj = burnchain_op. get ( "transfer_stx" ) . unwrap ( ) ;
4459
+ let sender_obj = transfer_stx_obj. get ( "sender" ) . unwrap ( ) ;
4460
+ let sender = sender_obj. get ( "address" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
4461
+ let recipient_obj = transfer_stx_obj. get ( "recipient" ) . unwrap ( ) ;
4462
+ let recipient = recipient_obj. get ( "address" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
4463
+ let transfered_ustx = transfer_stx_obj
4464
+ . get ( "transfered_ustx" )
4465
+ . unwrap ( )
4466
+ . as_u64 ( )
4467
+ . unwrap ( ) ;
4468
+ assert_eq ! ( sender, stacker_addr_1. to_string( ) ) ;
4469
+ assert_eq ! ( recipient, stacker_addr_2. to_string( ) ) ;
4470
+ assert_eq ! ( transfered_ustx, 10000 ) ;
4471
+ info ! (
4472
+ "Transfer STX op: sender: {}, recipient: {}, transfered_ustx: {}" ,
4473
+ sender, recipient, transfered_ustx
4474
+ ) ;
4475
+ transfer_stx_found = true ;
4476
+ continue ;
4477
+ }
4478
+ if burnchain_op. contains_key ( "delegate_stx" ) {
4479
+ info ! ( "Got delegate STX op: {:?}" , burnchain_op) ;
4480
+ let delegate_stx_obj = burnchain_op. get ( "delegate_stx" ) . unwrap ( ) ;
4481
+ let sender_obj = delegate_stx_obj. get ( "sender" ) . unwrap ( ) ;
4482
+ let sender = sender_obj. get ( "address" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
4483
+ let delegate_to_obj = delegate_stx_obj. get ( "delegate_to" ) . unwrap ( ) ;
4484
+ let delegate_to = delegate_to_obj. get ( "address" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
4485
+ let delegated_ustx = delegate_stx_obj
4486
+ . get ( "delegated_ustx" )
4487
+ . unwrap ( )
4488
+ . as_u64 ( )
4489
+ . unwrap ( ) ;
4490
+ assert_eq ! ( sender, stacker_addr_2. to_string( ) ) ;
4491
+ assert_eq ! ( delegate_to, stacker_addr_1. to_string( ) ) ;
4492
+ assert_eq ! ( delegated_ustx, 100_000 ) ;
4493
+ delegate_stx_found = true ;
4494
+ continue ;
4495
+ }
4335
4496
if !burnchain_op. contains_key ( "stack_stx" ) {
4336
4497
warn ! ( "Got unexpected burnchain op: {:?}" , burnchain_op) ;
4337
4498
panic ! ( "unexpected btc transaction type" ) ;
@@ -4378,7 +4539,8 @@ fn stack_stx_burn_op_integration_test() {
4378
4539
stack_stx_burn_op_tx_count, 1 ,
4379
4540
"Stack-stx tx without a signer_key shouldn't have been submitted"
4380
4541
) ;
4381
-
4542
+ assert ! ( transfer_stx_found, "Expected transfer STX op" ) ;
4543
+ assert ! ( delegate_stx_found, "Expected delegate STX op" ) ;
4382
4544
let sortdb = btc_regtest_controller. sortdb_mut ( ) ;
4383
4545
let sortdb_conn = sortdb. conn ( ) ;
4384
4546
let tip = SortitionDB :: get_canonical_burn_chain_tip ( sortdb_conn) . unwrap ( ) ;
0 commit comments