• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacks-network / stacks-core / 26250451051-1

21 May 2026 08:11PM UTC coverage: 85.585% (-0.1%) from 85.712%
26250451051-1

Pull #7215

github

ec9d4c
web-flow
Merge 9487bf852 into af1280aac
Pull Request #7215: Chore: fix flake in non_blocking_minority_configured_to_favour_...

188844 of 220651 relevant lines covered (85.58%)

18975267.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.47
/stackslib/src/core/test_util.rs
1
// Copyright (C) 2025-2026 Stacks Open Internet Foundation
2
//
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// This program is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15

16
use std::io::Cursor;
17

18
use chrono::Utc;
19
use clarity::codec::StacksMessageCodec;
20
use clarity::types::chainstate::{
21
    BlockHeaderHash, ConsensusHash, StacksAddress, StacksPrivateKey, StacksPublicKey,
22
};
23
use clarity::vm::costs::ExecutionCost;
24
use clarity::vm::tests::BurnStateDB;
25
use clarity::vm::types::PrincipalData;
26
use clarity::vm::{ClarityName, ClarityVersion, ContractName, Value};
27

28
use crate::chainstate::stacks::db::StacksChainState;
29
use crate::chainstate::stacks::miner::{BlockBuilderSettings, StacksMicroblockBuilder};
30
use crate::chainstate::stacks::{
31
    CoinbasePayload, StacksBlock, StacksMicroblock, StacksMicroblockHeader, StacksTransaction,
32
    StacksTransactionSigner, TenureChangePayload, TokenTransferMemo, TransactionAnchorMode,
33
    TransactionAuth, TransactionContractCall, TransactionPayload, TransactionPostConditionMode,
34
    TransactionSmartContract, TransactionSpendingCondition, TransactionVersion,
35
};
36
use crate::util_lib::strings::StacksString;
37

38
#[allow(clippy::too_many_arguments)]
39
pub fn sign_sponsored_sig_tx_anchor_mode_version(
9✔
40
    payload: TransactionPayload,
9✔
41
    sender: &StacksPrivateKey,
9✔
42
    payer: &StacksPrivateKey,
9✔
43
    sender_nonce: u64,
9✔
44
    payer_nonce: u64,
9✔
45
    tx_fee: u64,
9✔
46
    chain_id: u32,
9✔
47
    anchor_mode: TransactionAnchorMode,
9✔
48
    version: TransactionVersion,
9✔
49
) -> StacksTransaction {
9✔
50
    sign_tx_anchor_mode_version(
9✔
51
        payload,
9✔
52
        sender,
9✔
53
        Some(payer),
9✔
54
        sender_nonce,
9✔
55
        Some(payer_nonce),
9✔
56
        tx_fee,
9✔
57
        chain_id,
9✔
58
        anchor_mode,
9✔
59
        version,
9✔
60
    )
61
}
9✔
62

63
pub fn sign_standard_single_sig_tx(
12,718,161✔
64
    payload: TransactionPayload,
12,718,161✔
65
    sender: &StacksPrivateKey,
12,718,161✔
66
    nonce: u64,
12,718,161✔
67
    tx_fee: u64,
12,718,161✔
68
    chain_id: u32,
12,718,161✔
69
) -> StacksTransaction {
12,718,161✔
70
    sign_standard_single_sig_tx_anchor_mode(
12,718,161✔
71
        payload,
12,718,161✔
72
        sender,
12,718,161✔
73
        nonce,
12,718,161✔
74
        tx_fee,
12,718,161✔
75
        chain_id,
12,718,161✔
76
        TransactionAnchorMode::OnChainOnly,
12,718,161✔
77
    )
78
}
12,718,161✔
79

80
pub fn sign_standard_single_sig_tx_anchor_mode(
12,718,233✔
81
    payload: TransactionPayload,
12,718,233✔
82
    sender: &StacksPrivateKey,
12,718,233✔
83
    nonce: u64,
12,718,233✔
84
    tx_fee: u64,
12,718,233✔
85
    chain_id: u32,
12,718,233✔
86
    anchor_mode: TransactionAnchorMode,
12,718,233✔
87
) -> StacksTransaction {
12,718,233✔
88
    sign_standard_single_sig_tx_anchor_mode_version(
12,718,233✔
89
        payload,
12,718,233✔
90
        sender,
12,718,233✔
91
        nonce,
12,718,233✔
92
        tx_fee,
12,718,233✔
93
        chain_id,
12,718,233✔
94
        anchor_mode,
12,718,233✔
95
        TransactionVersion::Testnet,
12,718,233✔
96
    )
97
}
12,718,233✔
98

99
pub fn sign_standard_single_sig_tx_anchor_mode_version(
12,718,242✔
100
    payload: TransactionPayload,
12,718,242✔
101
    sender: &StacksPrivateKey,
12,718,242✔
102
    nonce: u64,
12,718,242✔
103
    tx_fee: u64,
12,718,242✔
104
    chain_id: u32,
12,718,242✔
105
    anchor_mode: TransactionAnchorMode,
12,718,242✔
106
    version: TransactionVersion,
12,718,242✔
107
) -> StacksTransaction {
12,718,242✔
108
    sign_tx_anchor_mode_version(
12,718,242✔
109
        payload,
12,718,242✔
110
        sender,
12,718,242✔
111
        None,
12,718,242✔
112
        nonce,
12,718,242✔
113
        None,
12,718,242✔
114
        tx_fee,
12,718,242✔
115
        chain_id,
12,718,242✔
116
        anchor_mode,
12,718,242✔
117
        version,
12,718,242✔
118
    )
119
}
12,718,242✔
120

121
#[allow(clippy::too_many_arguments)]
122
pub fn make_unsigned_tx(
12,718,296✔
123
    payload: TransactionPayload,
12,718,296✔
124
    sender: &StacksPrivateKey,
12,718,296✔
125
    payer: Option<&StacksPrivateKey>,
12,718,296✔
126
    sender_nonce: u64,
12,718,296✔
127
    payer_nonce: Option<u64>,
12,718,296✔
128
    tx_fee: u64,
12,718,296✔
129
    chain_id: u32,
12,718,296✔
130
    anchor_mode: TransactionAnchorMode,
12,718,296✔
131
    version: TransactionVersion,
12,718,296✔
132
) -> StacksTransaction {
12,718,296✔
133
    let mut sender_spending_condition =
12,718,296✔
134
        TransactionSpendingCondition::new_singlesig_p2pkh(StacksPublicKey::from_private(sender))
12,718,296✔
135
            .expect("Failed to create p2pkh spending condition from public key.");
12,718,296✔
136
    sender_spending_condition.set_nonce(sender_nonce);
12,718,296✔
137

138
    let auth = match (payer, payer_nonce) {
12,718,296✔
139
        (Some(payer), Some(payer_nonce)) => {
9✔
140
            let mut payer_spending_condition = TransactionSpendingCondition::new_singlesig_p2pkh(
9✔
141
                StacksPublicKey::from_private(payer),
9✔
142
            )
143
            .expect("Failed to create p2pkh spending condition from public key.");
9✔
144
            payer_spending_condition.set_nonce(payer_nonce);
9✔
145
            payer_spending_condition.set_tx_fee(tx_fee);
9✔
146
            TransactionAuth::Sponsored(sender_spending_condition, payer_spending_condition)
9✔
147
        }
148
        _ => {
149
            sender_spending_condition.set_tx_fee(tx_fee);
12,718,287✔
150
            TransactionAuth::Standard(sender_spending_condition)
12,718,287✔
151
        }
152
    };
153
    let mut unsigned_tx = StacksTransaction::new(version, auth, payload);
12,718,296✔
154
    unsigned_tx.anchor_mode = anchor_mode;
12,718,296✔
155
    unsigned_tx.post_condition_mode = TransactionPostConditionMode::Allow;
12,718,296✔
156
    unsigned_tx.chain_id = chain_id;
12,718,296✔
157
    unsigned_tx
12,718,296✔
158
}
12,718,296✔
159

160
#[allow(clippy::too_many_arguments)]
161
pub fn sign_tx_anchor_mode_version(
12,718,251✔
162
    payload: TransactionPayload,
12,718,251✔
163
    sender: &StacksPrivateKey,
12,718,251✔
164
    payer: Option<&StacksPrivateKey>,
12,718,251✔
165
    sender_nonce: u64,
12,718,251✔
166
    payer_nonce: Option<u64>,
12,718,251✔
167
    tx_fee: u64,
12,718,251✔
168
    chain_id: u32,
12,718,251✔
169
    anchor_mode: TransactionAnchorMode,
12,718,251✔
170
    version: TransactionVersion,
12,718,251✔
171
) -> StacksTransaction {
12,718,251✔
172
    let unsigned_tx = make_unsigned_tx(
12,718,251✔
173
        payload,
12,718,251✔
174
        sender,
12,718,251✔
175
        payer,
12,718,251✔
176
        sender_nonce,
12,718,251✔
177
        payer_nonce,
12,718,251✔
178
        tx_fee,
12,718,251✔
179
        chain_id,
12,718,251✔
180
        anchor_mode,
12,718,251✔
181
        version,
12,718,251✔
182
    );
183

184
    let mut tx_signer = StacksTransactionSigner::new(&unsigned_tx);
12,718,251✔
185
    tx_signer.sign_origin(sender).unwrap();
12,718,251✔
186
    if let (Some(payer), Some(_)) = (payer, payer_nonce) {
12,718,251✔
187
        tx_signer.sign_sponsor(payer).unwrap();
9✔
188
    }
12,718,242✔
189

190
    tx_signer.get_tx().unwrap()
12,718,251✔
191
}
12,718,251✔
192

193
#[allow(clippy::too_many_arguments)]
194
pub fn serialize_sign_tx_anchor_mode_version(
×
195
    payload: TransactionPayload,
×
196
    sender: &StacksPrivateKey,
×
197
    payer: Option<&StacksPrivateKey>,
×
198
    sender_nonce: u64,
×
199
    payer_nonce: Option<u64>,
×
200
    tx_fee: u64,
×
201
    chain_id: u32,
×
202
    anchor_mode: TransactionAnchorMode,
×
203
    version: TransactionVersion,
×
204
) -> Vec<u8> {
×
205
    let tx = sign_tx_anchor_mode_version(
×
206
        payload,
×
207
        sender,
×
208
        payer,
×
209
        sender_nonce,
×
210
        payer_nonce,
×
211
        tx_fee,
×
212
        chain_id,
×
213
        anchor_mode,
×
214
        version,
×
215
    );
216

217
    let mut buf = vec![];
×
218
    tx.consensus_serialize(&mut buf).unwrap();
×
219
    buf
×
220
}
×
221

222
pub fn make_contract_publish_tx(
4,102✔
223
    sender: &StacksPrivateKey,
4,102✔
224
    nonce: u64,
4,102✔
225
    tx_fee: u64,
4,102✔
226
    chain_id: u32,
4,102✔
227
    contract_name: &str,
4,102✔
228
    contract_content: &str,
4,102✔
229
    version: Option<ClarityVersion>,
4,102✔
230
) -> StacksTransaction {
4,102✔
231
    let name = ContractName::try_from(contract_name).expect("invalid contract name");
4,102✔
232
    let code_body = StacksString::from_string(&contract_content.to_string()).unwrap();
4,102✔
233

234
    let payload =
4,102✔
235
        TransactionPayload::SmartContract(TransactionSmartContract { name, code_body }, version);
4,102✔
236

237
    sign_standard_single_sig_tx(payload, sender, nonce, tx_fee, chain_id)
4,102✔
238
}
4,102✔
239

240
pub fn make_contract_publish_versioned(
4,096✔
241
    sender: &StacksPrivateKey,
4,096✔
242
    nonce: u64,
4,096✔
243
    tx_fee: u64,
4,096✔
244
    chain_id: u32,
4,096✔
245
    contract_name: &str,
4,096✔
246
    contract_content: &str,
4,096✔
247
    version: Option<ClarityVersion>,
4,096✔
248
) -> Vec<u8> {
4,096✔
249
    make_contract_publish_tx(
4,096✔
250
        sender,
4,096✔
251
        nonce,
4,096✔
252
        tx_fee,
4,096✔
253
        chain_id,
4,096✔
254
        contract_name,
4,096✔
255
        contract_content,
4,096✔
256
        version,
4,096✔
257
    )
4,096✔
258
    .serialize_to_vec()
4,096✔
259
}
4,096✔
260

261
pub fn make_contract_publish(
1,018✔
262
    sender: &StacksPrivateKey,
1,018✔
263
    nonce: u64,
1,018✔
264
    tx_fee: u64,
1,018✔
265
    chain_id: u32,
1,018✔
266
    contract_name: &str,
1,018✔
267
    contract_content: &str,
1,018✔
268
) -> Vec<u8> {
1,018✔
269
    make_contract_publish_versioned(
1,018✔
270
        sender,
1,018✔
271
        nonce,
1,018✔
272
        tx_fee,
1,018✔
273
        chain_id,
1,018✔
274
        contract_name,
1,018✔
275
        contract_content,
1,018✔
276
        None,
1,018✔
277
    )
278
}
1,018✔
279

280
pub fn make_contract_publish_microblock_only_versioned(
63✔
281
    sender: &StacksPrivateKey,
63✔
282
    nonce: u64,
63✔
283
    tx_fee: u64,
63✔
284
    chain_id: u32,
63✔
285
    contract_name: &str,
63✔
286
    contract_content: &str,
63✔
287
    version: Option<ClarityVersion>,
63✔
288
) -> Vec<u8> {
63✔
289
    let name = ContractName::try_from(contract_name).expect("invalid contract name");
63✔
290
    let code_body = StacksString::from_string(&contract_content.to_string()).unwrap();
63✔
291

292
    let payload =
63✔
293
        TransactionPayload::SmartContract(TransactionSmartContract { name, code_body }, version);
63✔
294

295
    let tx = sign_standard_single_sig_tx_anchor_mode(
63✔
296
        payload,
63✔
297
        sender,
63✔
298
        nonce,
63✔
299
        tx_fee,
63✔
300
        chain_id,
63✔
301
        TransactionAnchorMode::OffChainOnly,
63✔
302
    );
303
    let mut tx_bytes = vec![];
63✔
304
    tx.consensus_serialize(&mut tx_bytes).unwrap();
63✔
305
    tx_bytes
63✔
306
}
63✔
307

308
pub fn make_contract_publish_microblock_only(
63✔
309
    sender: &StacksPrivateKey,
63✔
310
    nonce: u64,
63✔
311
    tx_fee: u64,
63✔
312
    chain_id: u32,
63✔
313
    contract_name: &str,
63✔
314
    contract_content: &str,
63✔
315
) -> Vec<u8> {
63✔
316
    make_contract_publish_microblock_only_versioned(
63✔
317
        sender,
63✔
318
        nonce,
63✔
319
        tx_fee,
63✔
320
        chain_id,
63✔
321
        contract_name,
63✔
322
        contract_content,
63✔
323
        None,
63✔
324
    )
325
}
63✔
326

327
pub fn to_addr(sk: &StacksPrivateKey) -> StacksAddress {
13,227,085✔
328
    StacksAddress::p2pkh(false, &StacksPublicKey::from_private(sk))
13,227,085✔
329
}
13,227,085✔
330

331
pub fn make_stacks_transfer_tx(
12,696,419✔
332
    sender: &StacksPrivateKey,
12,696,419✔
333
    nonce: u64,
12,696,419✔
334
    tx_fee: u64,
12,696,419✔
335
    chain_id: u32,
12,696,419✔
336
    recipient: &PrincipalData,
12,696,419✔
337
    amount: u64,
12,696,419✔
338
) -> StacksTransaction {
12,696,419✔
339
    let payload =
12,696,419✔
340
        TransactionPayload::TokenTransfer(recipient.clone(), amount, TokenTransferMemo([0; 34]));
12,696,419✔
341
    sign_standard_single_sig_tx(payload, sender, nonce, tx_fee, chain_id)
12,696,419✔
342
}
12,696,419✔
343

344
/// Make a stacks transfer transaction, returning the serialized transaction bytes
345
pub fn make_stacks_transfer_serialized(
12,696,313✔
346
    sender: &StacksPrivateKey,
12,696,313✔
347
    nonce: u64,
12,696,313✔
348
    tx_fee: u64,
12,696,313✔
349
    chain_id: u32,
12,696,313✔
350
    recipient: &PrincipalData,
12,696,313✔
351
    amount: u64,
12,696,313✔
352
) -> Vec<u8> {
12,696,313✔
353
    let tx = make_stacks_transfer_tx(sender, nonce, tx_fee, chain_id, recipient, amount);
12,696,313✔
354
    let mut tx_bytes = vec![];
12,696,313✔
355
    tx.consensus_serialize(&mut tx_bytes).unwrap();
12,696,313✔
356
    tx_bytes
12,696,313✔
357
}
12,696,313✔
358

359
#[allow(clippy::too_many_arguments)]
360
pub fn make_sponsored_stacks_transfer_on_testnet(
9✔
361
    sender: &StacksPrivateKey,
9✔
362
    payer: &StacksPrivateKey,
9✔
363
    sender_nonce: u64,
9✔
364
    payer_nonce: u64,
9✔
365
    tx_fee: u64,
9✔
366
    chain_id: u32,
9✔
367
    recipient: &PrincipalData,
9✔
368
    amount: u64,
9✔
369
) -> Vec<u8> {
9✔
370
    let payload =
9✔
371
        TransactionPayload::TokenTransfer(recipient.clone(), amount, TokenTransferMemo([0; 34]));
9✔
372
    let tx = sign_sponsored_sig_tx_anchor_mode_version(
9✔
373
        payload,
9✔
374
        sender,
9✔
375
        payer,
9✔
376
        sender_nonce,
9✔
377
        payer_nonce,
9✔
378
        tx_fee,
9✔
379
        chain_id,
9✔
380
        TransactionAnchorMode::OnChainOnly,
9✔
381
        TransactionVersion::Testnet,
9✔
382
    );
383
    let mut tx_bytes = vec![];
9✔
384
    tx.consensus_serialize(&mut tx_bytes).unwrap();
9✔
385
    tx_bytes
9✔
386
}
9✔
387

388
pub fn make_stacks_transfer_mblock_only(
9✔
389
    sender: &StacksPrivateKey,
9✔
390
    nonce: u64,
9✔
391
    tx_fee: u64,
9✔
392
    chain_id: u32,
9✔
393
    recipient: &PrincipalData,
9✔
394
    amount: u64,
9✔
395
) -> Vec<u8> {
9✔
396
    let payload =
9✔
397
        TransactionPayload::TokenTransfer(recipient.clone(), amount, TokenTransferMemo([0; 34]));
9✔
398
    let tx = sign_standard_single_sig_tx_anchor_mode(
9✔
399
        payload,
9✔
400
        sender,
9✔
401
        nonce,
9✔
402
        tx_fee,
9✔
403
        chain_id,
9✔
404
        TransactionAnchorMode::OffChainOnly,
9✔
405
    );
406
    let mut tx_bytes = vec![];
9✔
407
    tx.consensus_serialize(&mut tx_bytes).unwrap();
9✔
408
    tx_bytes
9✔
409
}
9✔
410

411
pub fn make_poison(
36✔
412
    sender: &StacksPrivateKey,
36✔
413
    nonce: u64,
36✔
414
    tx_fee: u64,
36✔
415
    chain_id: u32,
36✔
416
    header_1: StacksMicroblockHeader,
36✔
417
    header_2: StacksMicroblockHeader,
36✔
418
) -> Vec<u8> {
36✔
419
    let payload = TransactionPayload::PoisonMicroblock(header_1, header_2);
36✔
420
    let tx = sign_standard_single_sig_tx(payload, sender, nonce, tx_fee, chain_id);
36✔
421
    let mut tx_bytes = vec![];
36✔
422
    tx.consensus_serialize(&mut tx_bytes).unwrap();
36✔
423
    tx_bytes
36✔
424
}
36✔
425

426
pub fn make_coinbase_tx(
9✔
427
    sender: &StacksPrivateKey,
9✔
428
    nonce: u64,
9✔
429
    tx_fee: u64,
9✔
430
    chain_id: u32,
9✔
431
) -> StacksTransaction {
9✔
432
    let payload = TransactionPayload::Coinbase(CoinbasePayload([0; 32]), None, None);
9✔
433
    let tx = sign_standard_single_sig_tx(payload, sender, nonce, tx_fee, chain_id);
9✔
434
    tx
9✔
435
}
9✔
436

437
pub fn make_coinbase(sender: &StacksPrivateKey, nonce: u64, tx_fee: u64, chain_id: u32) -> Vec<u8> {
9✔
438
    let tx = make_coinbase_tx(sender, nonce, tx_fee, chain_id);
9✔
439
    tx.serialize_to_vec()
9✔
440
}
9✔
441

442
#[allow(clippy::too_many_arguments)]
443
pub fn make_contract_call_tx(
17,550✔
444
    sender: &StacksPrivateKey,
17,550✔
445
    nonce: u64,
17,550✔
446
    tx_fee: u64,
17,550✔
447
    chain_id: u32,
17,550✔
448
    contract_addr: &StacksAddress,
17,550✔
449
    contract_name: ContractName,
17,550✔
450
    function_name: ClarityName,
17,550✔
451
    function_args: &[Value],
17,550✔
452
) -> StacksTransaction {
17,550✔
453
    let payload = TransactionContractCall {
17,550✔
454
        address: contract_addr.clone(),
17,550✔
455
        contract_name,
17,550✔
456
        function_name,
17,550✔
457
        function_args: function_args.to_vec(),
17,550✔
458
    };
17,550✔
459

460
    sign_standard_single_sig_tx(payload.into(), sender, nonce, tx_fee, chain_id)
17,550✔
461
}
17,550✔
462

463
#[allow(clippy::too_many_arguments)]
464
pub fn make_contract_call(
17,533✔
465
    sender: &StacksPrivateKey,
17,533✔
466
    nonce: u64,
17,533✔
467
    tx_fee: u64,
17,533✔
468
    chain_id: u32,
17,533✔
469
    contract_addr: &StacksAddress,
17,533✔
470
    contract_name: &str,
17,533✔
471
    function_name: &str,
17,533✔
472
    function_args: &[Value],
17,533✔
473
) -> Vec<u8> {
17,533✔
474
    make_contract_call_tx(
17,533✔
475
        sender,
17,533✔
476
        nonce,
17,533✔
477
        tx_fee,
17,533✔
478
        chain_id,
17,533✔
479
        contract_addr,
17,533✔
480
        contract_name.try_into().expect("invalid contract name"),
17,533✔
481
        function_name.try_into().expect("invalid function name"),
17,533✔
482
        function_args,
17,533✔
483
    )
17,533✔
484
    .serialize_to_vec()
17,533✔
485
}
17,533✔
486

487
#[allow(clippy::too_many_arguments)]
488
pub fn make_contract_call_mblock_only(
×
489
    sender: &StacksPrivateKey,
×
490
    nonce: u64,
×
491
    tx_fee: u64,
×
492
    chain_id: u32,
×
493
    contract_addr: &StacksAddress,
×
494
    contract_name: &'static str,
×
495
    function_name: &'static str,
×
496
    function_args: &[Value],
×
497
) -> Vec<u8> {
×
498
    let contract_name = ContractName::from_literal(contract_name);
×
499
    let function_name = ClarityName::from_literal(function_name);
×
500

501
    let payload = TransactionContractCall {
×
502
        address: contract_addr.clone(),
×
503
        contract_name,
×
504
        function_name,
×
505
        function_args: function_args.to_vec(),
×
506
    };
×
507

508
    let tx = sign_standard_single_sig_tx_anchor_mode(
×
509
        payload.into(),
×
510
        sender,
×
511
        nonce,
×
512
        tx_fee,
×
513
        chain_id,
×
514
        TransactionAnchorMode::OffChainOnly,
×
515
    );
516
    let mut tx_bytes = vec![];
×
517
    tx.consensus_serialize(&mut tx_bytes).unwrap();
×
518
    tx_bytes
×
519
}
×
520

521
pub fn make_microblock(
9✔
522
    privk: &StacksPrivateKey,
9✔
523
    chainstate: &mut StacksChainState,
9✔
524
    burn_dbconn: &dyn BurnStateDB,
9✔
525
    consensus_hash: ConsensusHash,
9✔
526
    block: StacksBlock,
9✔
527
    txs: Vec<StacksTransaction>,
9✔
528
) -> StacksMicroblock {
9✔
529
    let mut block_bytes = vec![];
9✔
530
    block.consensus_serialize(&mut block_bytes).unwrap();
9✔
531

532
    let mut microblock_builder = StacksMicroblockBuilder::new(
9✔
533
        block.block_hash(),
9✔
534
        consensus_hash,
9✔
535
        chainstate,
9✔
536
        burn_dbconn,
9✔
537
        BlockBuilderSettings::max_value(),
9✔
538
    )
539
    .unwrap();
9✔
540
    let mempool_txs: Vec<_> = txs
9✔
541
        .into_iter()
9✔
542
        .map(|tx| {
18✔
543
            // TODO: better fee estimation
544
            let mut tx_bytes = vec![];
18✔
545
            tx.consensus_serialize(&mut tx_bytes).unwrap();
18✔
546
            (tx, tx_bytes.len() as u64)
18✔
547
        })
18✔
548
        .collect();
9✔
549

550
    // NOTE: we intentionally do not check the block's microblock pubkey hash against the private
551
    // key, because we may need to test that microblocks get rejected due to bad signatures.
552
    microblock_builder
9✔
553
        .mine_next_microblock_from_txs(mempool_txs, privk)
9✔
554
        .unwrap()
9✔
555
}
9✔
556

557
pub fn insert_tx_in_mempool(
12,679,600✔
558
    db_tx: &rusqlite::Transaction,
12,679,600✔
559
    tx_hex: Vec<u8>,
12,679,600✔
560
    origin_addr: &StacksAddress,
12,679,600✔
561
    origin_nonce: u64,
12,679,600✔
562
    fee: u64,
12,679,600✔
563
    consensus_hash: &ConsensusHash,
12,679,600✔
564
    block_header_hash: &BlockHeaderHash,
12,679,600✔
565
    height: u64,
12,679,600✔
566
) {
12,679,600✔
567
    let sql = "INSERT OR REPLACE INTO mempool (
12,679,600✔
568
        txid,
12,679,600✔
569
        origin_address,
12,679,600✔
570
        origin_nonce,
12,679,600✔
571
        sponsor_address,
12,679,600✔
572
        sponsor_nonce,
12,679,600✔
573
        tx_fee,
12,679,600✔
574
        length,
12,679,600✔
575
        consensus_hash,
12,679,600✔
576
        block_header_hash,
12,679,600✔
577
        height,
12,679,600✔
578
        accept_time,
12,679,600✔
579
        tx,
12,679,600✔
580
        fee_rate)
12,679,600✔
581
        VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)";
12,679,600✔
582

583
    let origin_addr_str = origin_addr.to_string();
12,679,600✔
584
    let length = tx_hex.len() as u64;
12,679,600✔
585
    let fee_rate = fee / length * 30;
12,679,600✔
586

587
    let txid = {
12,679,600✔
588
        let mut cursor = Cursor::new(&tx_hex);
12,679,600✔
589
        StacksTransaction::consensus_deserialize(&mut cursor)
12,679,600✔
590
            .expect("Failed to deserialize transaction")
12,679,600✔
591
            .txid()
12,679,600✔
592
    };
593
    let args = rusqlite::params![
12,679,600✔
594
        txid,
595
        origin_addr_str,
596
        origin_nonce,
597
        origin_addr_str,
598
        origin_nonce,
599
        fee,
600
        length,
601
        consensus_hash,
602
        block_header_hash,
603
        height,
604
        Utc::now().timestamp(),
12,679,600✔
605
        tx_hex,
606
        fee_rate
607
    ];
608
    db_tx
12,679,600✔
609
        .execute(sql, args)
12,679,600✔
610
        .expect("Failed to insert transaction into mempool");
12,679,600✔
611
}
12,679,600✔
612

613
/// Generate source code for a contract that exposes a public function
614
/// `big-tx`. This function uses `proportion` of read_count when called
615
pub fn make_big_read_count_contract(limit: ExecutionCost, proportion: u64) -> String {
63✔
616
    let read_count = (limit.read_count * proportion) / 100;
63✔
617

618
    let read_lines = (0..read_count)
63✔
619
        .map(|_| format!("(var-get my-var)"))
918,000✔
620
        .collect::<Vec<_>>()
63✔
621
        .join("\n");
63✔
622

623
    format!(
63✔
624
        "
625
(define-data-var my-var uint u0)
626
(define-public (big-tx)
627
(begin
628
{}
629
(ok true)))
630
        ",
631
        read_lines
632
    )
633
}
63✔
634

635
/// Make a tenure change transaction
636
pub fn make_tenure_change_tx(
45✔
637
    sender: &StacksPrivateKey,
45✔
638
    nonce: u64,
45✔
639
    tx_fee: u64,
45✔
640
    chain_id: u32,
45✔
641
    tc_payload: TenureChangePayload,
45✔
642
) -> StacksTransaction {
45✔
643
    sign_standard_single_sig_tx(
45✔
644
        TransactionPayload::TenureChange(tc_payload),
45✔
645
        sender,
45✔
646
        nonce,
45✔
647
        tx_fee,
45✔
648
        chain_id,
45✔
649
    )
650
}
45✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc