Skip to content

Commit 6cd5f00

Browse files
committed
Token timelock test
1 parent 0fad4bf commit 6cd5f00

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

chainstate/test-suite/src/tests/fungible_tokens_v1.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use common::{
2525
chain::{
2626
output_value::OutputValue,
2727
signature::inputsig::{standard_signature::StandardInputSignature, InputWitness},
28+
timelock::OutputTimeLock,
2829
tokens::{
2930
make_token_id, TokenId, TokenIssuance, TokenIssuanceV1, TokenIssuanceVersion,
3031
TokenTotalSupply,
@@ -3138,3 +3139,117 @@ fn check_signature_on_lock_supply(#[case] seed: Seed) {
31383139
tf.make_block_builder().add_transaction(tx).build_and_process().unwrap();
31393140
});
31403141
}
3142+
3143+
// Issue a token and mint some with locked outputs for 2 blocks.
3144+
// Try transfer tokens in the next block and check it's the timelock error.
3145+
// Produce a block.
3146+
// Transfer tokens and check that now it's ok.
3147+
#[rstest]
3148+
#[trace]
3149+
#[case(Seed::from_entropy())]
3150+
fn mint_with_timelock(#[case] seed: Seed) {
3151+
utils::concurrency::model(move || {
3152+
let mut rng = make_seedable_rng(seed);
3153+
let mut tf = make_test_framework_with_v1(&mut rng);
3154+
3155+
let token_min_supply_change_fee =
3156+
tf.chainstate.get_chain_config().token_min_supply_change_fee();
3157+
3158+
let amount_to_mint =
3159+
Amount::from_atoms(rng.gen_range(2..SignedAmount::MAX.into_atoms() as u128));
3160+
let (token_id, _, utxo_with_change) =
3161+
issue_token_from_genesis(&mut rng, &mut tf, TokenTotalSupply::Lockable);
3162+
3163+
// Mint with locked output
3164+
let mint_tx = TransactionBuilder::new()
3165+
.add_input(
3166+
TxInput::from_account(
3167+
AccountNonce::new(0),
3168+
AccountOp::MintTokens(token_id, amount_to_mint),
3169+
),
3170+
InputWitness::NoSignature(None),
3171+
)
3172+
.add_input(
3173+
utxo_with_change.clone().into(),
3174+
InputWitness::NoSignature(None),
3175+
)
3176+
.add_output(TxOutput::LockThenTransfer(
3177+
OutputValue::TokenV1(token_id, amount_to_mint),
3178+
Destination::AnyoneCanSpend,
3179+
OutputTimeLock::ForBlockCount(2),
3180+
))
3181+
.add_output(TxOutput::Burn(OutputValue::Coin(
3182+
token_min_supply_change_fee,
3183+
)))
3184+
.add_output(TxOutput::Transfer(
3185+
OutputValue::Coin(token_min_supply_change_fee),
3186+
Destination::AnyoneCanSpend,
3187+
))
3188+
.build();
3189+
let mint_tx_id = mint_tx.transaction().get_id();
3190+
tf.make_block_builder().add_transaction(mint_tx).build_and_process().unwrap();
3191+
3192+
let actual_supply =
3193+
TokensAccountingStorageRead::get_circulating_supply(&tf.storage, &token_id).unwrap();
3194+
assert_eq!(actual_supply, Some(amount_to_mint));
3195+
3196+
// Try spend tokens at once
3197+
let token_mint_outpoint = UtxoOutPoint::new(mint_tx_id.into(), 0);
3198+
let result = tf
3199+
.make_block_builder()
3200+
.add_transaction(
3201+
TransactionBuilder::new()
3202+
.add_input(
3203+
TxInput::Utxo(token_mint_outpoint.clone()),
3204+
InputWitness::NoSignature(None),
3205+
)
3206+
.add_output(TxOutput::Transfer(
3207+
OutputValue::TokenV1(token_id, amount_to_mint),
3208+
Destination::AnyoneCanSpend,
3209+
))
3210+
.build(),
3211+
)
3212+
.build_and_process();
3213+
3214+
assert_eq!(
3215+
result.unwrap_err(),
3216+
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
3217+
ConnectTransactionError::TimeLockViolation(token_mint_outpoint.clone()),
3218+
))
3219+
);
3220+
3221+
// Produce 1 more block to get past timelock
3222+
tf.make_block_builder()
3223+
.add_transaction(
3224+
TransactionBuilder::new()
3225+
.add_input(
3226+
TxInput::from_utxo(mint_tx_id.into(), 2),
3227+
InputWitness::NoSignature(None),
3228+
)
3229+
.add_output(TxOutput::Transfer(
3230+
OutputValue::Coin(token_min_supply_change_fee),
3231+
Destination::AnyoneCanSpend,
3232+
))
3233+
.build(),
3234+
)
3235+
.build_and_process()
3236+
.unwrap();
3237+
3238+
// Spend again, now timelock should pass
3239+
tf.make_block_builder()
3240+
.add_transaction(
3241+
TransactionBuilder::new()
3242+
.add_input(
3243+
TxInput::Utxo(token_mint_outpoint.clone()),
3244+
InputWitness::NoSignature(None),
3245+
)
3246+
.add_output(TxOutput::Transfer(
3247+
OutputValue::TokenV1(token_id, amount_to_mint),
3248+
Destination::AnyoneCanSpend,
3249+
))
3250+
.build(),
3251+
)
3252+
.build_and_process()
3253+
.unwrap();
3254+
});
3255+
}

0 commit comments

Comments
 (0)