@@ -5,7 +5,15 @@ import {
5
5
TransactionEventsResponse ,
6
6
TransactionEventStxLock ,
7
7
} from '@stacks/stacks-blockchain-api-types' ;
8
- import { AnchorMode , makeSTXTokenTransfer } from '@stacks/transactions' ;
8
+ import {
9
+ AnchorMode ,
10
+ boolCV ,
11
+ bufferCV ,
12
+ makeContractCall ,
13
+ makeSTXTokenTransfer ,
14
+ stringAsciiCV ,
15
+ uintCV ,
16
+ } from '@stacks/transactions' ;
9
17
import { testnetKeys } from '../api/routes/debug' ;
10
18
import { StacksCoreRpcClient } from '../core-rpc/client' ;
11
19
import { ECPair } from '../ec-helpers' ;
@@ -29,17 +37,21 @@ import { StacksNetwork } from '@stacks/network';
29
37
import { RPCClient } from 'rpc-bitcoin' ;
30
38
import * as supertest from 'supertest' ;
31
39
import { ClarityValueUInt , decodeClarityValue } from 'stacks-encoding-native-js' ;
32
- import { decodeBtcAddress } from '@stacks/stacking' ;
40
+ import { decodeBtcAddress , poxAddressToTuple } from '@stacks/stacking' ;
33
41
import { timeout } from '@hirosystems/api-toolkit' ;
42
+ import { hexToBytes } from '@stacks/common' ;
34
43
35
44
// Perform Stack-STX operation on Bitcoin.
36
45
// See https://github.com/stacksgov/sips/blob/0da29c6911c49c45e4125dbeaed58069854591eb/sips/sip-007/sip-007-stacking-consensus.md#stx-operations-on-bitcoin
37
- async function createPox2StackStx ( args : {
46
+ async function createPox4StackStx ( args : {
38
47
stxAmount : bigint ;
39
48
cycleCount : number ;
40
49
stackerAddress : string ;
41
50
bitcoinWif : string ;
42
51
poxAddrPayout : string ;
52
+ signerKey : string ;
53
+ maxAmount : bigint ;
54
+ authID : number ;
43
55
} ) {
44
56
const btcAccount = ECPair . fromWIF ( args . bitcoinWif , btc . networks . regtest ) ;
45
57
const feeAmount = 0.0001 ;
@@ -97,14 +109,17 @@ async function createPox2StackStx(args: {
97
109
} ) ;
98
110
99
111
// StackStxOp: this operation executes the stack-stx operation.
100
- // 0 2 3 19 20
101
- // |------|--|-----------------------------|---------|
102
- // magic op uSTX to lock (u128) cycles (u8)
112
+ // 0 2 3 19 20 53 69 73
113
+ // |------|--|-----------------------------|------------|-------------------|-------------------|------------------------- |
114
+ // magic op uSTX to lock (u128) cycles (u8) signer key (optional) max_amount (optional u128) auth_id (optional u32 )
103
115
const stackStxOpTxPayload = Buffer . concat ( [
104
116
Buffer . from ( 'id' ) , // magic: 'id' ascii encoded (for krypton)
105
117
Buffer . from ( 'x' ) , // op: 'x' ascii encoded,
106
118
Buffer . from ( args . stxAmount . toString ( 16 ) . padStart ( 32 , '0' ) , 'hex' ) , // uSTX to lock (u128)
107
119
Buffer . from ( [ args . cycleCount ] ) , // cycles (u8)
120
+ Buffer . from ( args . signerKey , 'hex' ) , // signer key (33 bytes)
121
+ Buffer . from ( args . maxAmount . toString ( 16 ) . padStart ( 32 , '0' ) , 'hex' ) , // max_amount (u128)
122
+ Buffer . from ( args . authID . toString ( 16 ) . padStart ( 8 , '0' ) , 'hex' ) , // auth_id (u32)
108
123
] ) ;
109
124
const stackStxOpTxHex = new btc . Psbt ( { network : btc . networks . regtest } )
110
125
. setVersion ( 1 )
@@ -153,6 +168,8 @@ describe('PoX-4 - Stack using Bitcoin-chain stack ops', () => {
153
168
154
169
let testAccountBalance : bigint ;
155
170
const testAccountBtcBalance = 5 ;
171
+ const testStackAuthID = 123456789 ;
172
+ const cycleCount = 6 ;
156
173
let testStackAmount : bigint ;
157
174
158
175
let stxOpBtcTxs : {
@@ -247,15 +264,49 @@ describe('PoX-4 - Stack using Bitcoin-chain stack ops', () => {
247
264
await standByUntilBurnBlock ( poxInfo . next_cycle . reward_phase_start_block_height ) ; // a good time to stack
248
265
} ) ;
249
266
250
- test ( 'Stack via Bitcoin tx ' , async ( ) => {
267
+ test ( 'Submit set-signer-key-authorization transaction ' , async ( ) => {
251
268
const poxInfo = await client . getPox ( ) ;
252
269
testStackAmount = BigInt ( poxInfo . min_amount_ustx * 1.2 ) ;
253
- stxOpBtcTxs = await createPox2StackStx ( {
270
+ const [ contractAddress , contractName ] = poxInfo . contract_id . split ( '.' ) ;
271
+ const tx = await makeContractCall ( {
272
+ senderKey : seedAccount . secretKey ,
273
+ contractAddress,
274
+ contractName,
275
+ functionName : 'set-signer-key-authorization' ,
276
+ functionArgs : [
277
+ poxAddressToTuple ( poxAddrPayoutAccount . btcAddr ) , // (pox-addr { version: (buff 1), hashbytes: (buff 32)})
278
+ uintCV ( cycleCount ) , // (period uint)
279
+ uintCV ( poxInfo . current_cycle . id ) , // (reward-cycle uint)
280
+ stringAsciiCV ( 'stack-stx' ) , // (topic (string-ascii 14))
281
+ bufferCV ( hexToBytes ( seedAccount . pubKey ) ) , // (signer-key (buff 33))
282
+ boolCV ( true ) , // (allowed bool)
283
+ uintCV ( testStackAmount ) , // (max-amount uint)
284
+ uintCV ( testStackAuthID ) , // (auth-id uint)
285
+ ] ,
286
+ network : testEnv . stacksNetwork ,
287
+ anchorMode : AnchorMode . OnChainOnly ,
288
+ fee : 10000 ,
289
+ validateWithAbi : false ,
290
+ } ) ;
291
+ const expectedTxId = '0x' + tx . txid ( ) ;
292
+ const sendResult = await testEnv . client . sendTransaction ( Buffer . from ( tx . serialize ( ) ) ) ;
293
+ expect ( sendResult . txId ) . toBe ( expectedTxId ) ;
294
+
295
+ // Wait for API to receive and ingest tx
296
+ await standByForTxSuccess ( expectedTxId ) ;
297
+ } ) ;
298
+
299
+ test ( 'Stack via Bitcoin tx' , async ( ) => {
300
+ const poxInfo = await client . getPox ( ) ;
301
+ stxOpBtcTxs = await createPox4StackStx ( {
254
302
bitcoinWif : account . wif ,
255
303
stackerAddress : account . stxAddr ,
256
304
poxAddrPayout : poxAddrPayoutAccount . btcAddr ,
257
305
stxAmount : testStackAmount ,
258
- cycleCount : 6 ,
306
+ cycleCount : cycleCount ,
307
+ signerKey : seedAccount . pubKey ,
308
+ maxAmount : testStackAmount ,
309
+ authID : testStackAuthID ,
259
310
} ) ;
260
311
} ) ;
261
312
@@ -281,8 +332,7 @@ describe('PoX-4 - Stack using Bitcoin-chain stack ops', () => {
281
332
await standByUntilBlock ( curInfo . stacks_tip_height + 1 ) ;
282
333
} ) ;
283
334
284
- // TODO: this is blocked by a blockchain bug: https://github.com/stacks-network/stacks-core/issues/4282
285
- test . skip ( 'Test synthetic STX tx' , async ( ) => {
335
+ test ( 'Test synthetic STX tx' , async ( ) => {
286
336
const coreNodeBalance = await client . getAccount ( account . stxAddr ) ;
287
337
const addressEventsResp = await supertest ( api . server )
288
338
. get ( `/extended/v1/tx/events?address=${ account . stxAddr } ` )
0 commit comments