Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions api-server/stack-test-suite/tests/v2/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use chainstate_test_framework::empty_witness;
use chainstate_test_framework::{TestFramework, TransactionBuilder};
use common::chain::make_delegation_id;
use chainstate_test_framework::{empty_witness, TestFramework, TransactionBuilder};
use common::{
address::pubkeyhash::PublicKeyHash,
chain::{
make_token_id,
make_delegation_id, make_token_id,
output_value::OutputValue,
stakelock::StakePoolData,
tokens::{TokenId, TokenIssuance, TokenTotalSupply},
Expand Down Expand Up @@ -154,20 +152,25 @@ pub struct IssueAndMintTokensResult {
}

pub fn issue_and_mint_tokens_from_genesis(
min_mint_amount: Amount,
rng: &mut (impl Rng + CryptoRng),
tf: &mut TestFramework,
) -> IssueAndMintTokensResult {
let token_issuance_fee = tf.chainstate.get_chain_config().fungible_token_issuance_fee();

let issuance = test_utils::token_utils::random_token_issuance_v1(
let min_mint_amount_atoms = min_mint_amount.into_atoms();
let issuance = test_utils::token_utils::random_token_issuance_v1_with_min_supply(
tf.chain_config(),
Destination::AnyoneCanSpend,
min_mint_amount_atoms,
rng,
);
let amount_to_mint = match issuance.total_supply {
TokenTotalSupply::Fixed(limit) => Amount::from_atoms(rng.gen_range(1..=limit.into_atoms())),
TokenTotalSupply::Fixed(limit) => {
Amount::from_atoms(rng.gen_range(min_mint_amount_atoms..=limit.into_atoms()))
}
TokenTotalSupply::Lockable | TokenTotalSupply::Unlimited => {
Amount::from_atoms(rng.gen_range(100..1000))
Amount::from_atoms(rng.gen_range(min_mint_amount_atoms..min_mint_amount_atoms * 10))
}
};

Expand Down
13 changes: 4 additions & 9 deletions api-server/stack-test-suite/tests/v2/htlc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ async fn spend(#[case] seed: Seed) {
.build();

// Issue and mint some tokens to lock in htlc
let tokens_amount = Amount::from_atoms(100);
let issue_and_mint_result =
helpers::issue_and_mint_tokens_from_genesis(&mut rng, &mut tf);
helpers::issue_and_mint_tokens_from_genesis(tokens_amount, &mut rng, &mut tf);

// Create htlc
let (htlc, _) = create_htlc(&chain_config, &alice_pk, &bob_pk, secret.hash());
Expand All @@ -99,10 +100,7 @@ async fn spend(#[case] seed: Seed) {
InputWitness::NoSignature(None),
)
.add_output(TxOutput::Htlc(
OutputValue::TokenV1(
issue_and_mint_result.token_id,
Amount::from_atoms(100),
),
OutputValue::TokenV1(issue_and_mint_result.token_id, tokens_amount),
Box::new(htlc),
))
.build();
Expand All @@ -118,10 +116,7 @@ async fn spend(#[case] seed: Seed) {
InputWitness::NoSignature(None),
)
.add_output(TxOutput::Transfer(
OutputValue::TokenV1(
issue_and_mint_result.token_id,
Amount::from_atoms(100),
),
OutputValue::TokenV1(issue_and_mint_result.token_id, tokens_amount),
Destination::AnyoneCanSpend,
))
.build()
Expand Down
10 changes: 6 additions & 4 deletions api-server/stack-test-suite/tests/v2/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ async fn create_fill_conclude_order(#[case] seed: Seed, #[case] version: OrdersV
.build();

// Issue and mint some tokens to create an order with different currencies
let tokens_amount = Amount::from_atoms(10);
let issue_and_mint_result =
helpers::issue_and_mint_tokens_from_genesis(&mut rng, &mut tf);
helpers::issue_and_mint_tokens_from_genesis(tokens_amount, &mut rng, &mut tf);

// Create order
let order_data = OrderData::new(
Destination::AnyoneCanSpend,
OutputValue::Coin(Amount::from_atoms(10)),
OutputValue::TokenV1(issue_and_mint_result.token_id, Amount::from_atoms(10)),
OutputValue::TokenV1(issue_and_mint_result.token_id, tokens_amount),
);
let tx_1 = TransactionBuilder::new()
.add_input(
Expand Down Expand Up @@ -223,14 +224,15 @@ async fn order_pairs(#[case] seed: Seed) {
.build();

// Issue and mint some tokens to create an order with different currencies
let tokens_amount = Amount::from_atoms(10);
let issue_and_mint_result =
helpers::issue_and_mint_tokens_from_genesis(&mut rng, &mut tf);
helpers::issue_and_mint_tokens_from_genesis(tokens_amount, &mut rng, &mut tf);

// Create order
let order_data = OrderData::new(
Destination::AnyoneCanSpend,
OutputValue::Coin(Amount::from_atoms(10)),
OutputValue::TokenV1(issue_and_mint_result.token_id, Amount::from_atoms(10)),
OutputValue::TokenV1(issue_and_mint_result.token_id, tokens_amount),
);
let tx_1 = TransactionBuilder::new()
.add_input(
Expand Down
26 changes: 25 additions & 1 deletion chainstate/test-framework/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use common::{
},
primitives::{Amount, BlockHeight, Id, Idable},
};
use orders_accounting::OrdersAccountingDB;
use orders_accounting::{OrdersAccountingDB, OrdersAccountingView as _};
use randomness::{CryptoRng, Rng, SliceRandom as _};
use test_utils::random_ascii_alphanumeric_string;

Expand Down Expand Up @@ -203,6 +203,30 @@ pub fn calculate_fill_order(
.unwrap()
}

pub fn order_min_non_zero_fill_amount(
tf: &TestFramework,
order_id: &OrderId,
orders_version: OrdersVersion,
) -> Amount {
match orders_version {
// Note: in orders v0 even direct zero fills are allowed.
// However, this function is supposed to only return non-zero amounts.
OrdersVersion::V0 => Amount::from_atoms(1),

// In orders v1, the fill amount must be big enough so that the filled amount is non-zero.
OrdersVersion::V1 => {
let db_tx = tf.storage.transaction_ro().unwrap();
let orders_db = OrdersAccountingDB::new(&db_tx);

let order_data = orders_db.get_order_data(order_id).unwrap().unwrap();
let original_ask = order_data.ask().amount().into_atoms();
let original_give = order_data.give().amount().into_atoms();

Amount::from_atoms(original_ask.div_ceil(original_give))
}
}
}

/// Split an u128 value into the specified number of "randomish" parts (the min part size is half
/// the average part size).
pub fn split_u128(rng: &mut (impl Rng + CryptoRng), amount: u128, parts_count: usize) -> Vec<u128> {
Expand Down
57 changes: 39 additions & 18 deletions chainstate/test-suite/src/tests/orders_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ use chainstate::{
ConnectTransactionError,
};
use chainstate_test_framework::{
helpers::{calculate_fill_order, issue_and_mint_random_token_from_best_block},
helpers::{
calculate_fill_order, issue_and_mint_random_token_from_best_block,
order_min_non_zero_fill_amount,
},
output_value_amount, TestFramework, TransactionBuilder,
};
use common::{
Expand Down Expand Up @@ -669,7 +672,10 @@ fn fill_order_check_storage(#[case] seed: Seed, #[case] version: OrdersVersion)
tf.make_block_builder().add_transaction(tx).build_and_process(&mut rng).unwrap();

// Fill the order partially
let fill_amount = Amount::from_atoms(rng.gen_range(1..ask_amount.into_atoms()));
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, version);
let fill_amount = Amount::from_atoms(
rng.gen_range(min_fill_amount.into_atoms()..=ask_amount.into_atoms()),
);
let filled_amount = calculate_fill_order(&tf, &order_id, fill_amount, version);
let left_to_fill = (ask_amount - fill_amount).unwrap();

Expand Down Expand Up @@ -799,7 +805,10 @@ fn fill_partially_then_conclude(#[case] seed: Seed, #[case] version: OrdersVersi
tf.make_block_builder().add_transaction(tx).build_and_process(&mut rng).unwrap();

// Fill the order partially
let fill_amount = Amount::from_atoms(rng.gen_range(1..=ask_amount.into_atoms()));
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, version);
let fill_amount = Amount::from_atoms(
rng.gen_range(min_fill_amount.into_atoms()..=ask_amount.into_atoms()),
);
let filled_amount = calculate_fill_order(&tf, &order_id, fill_amount, version);

let fill_input = match version {
Expand Down Expand Up @@ -1475,7 +1484,10 @@ fn reorg_before_create(#[case] seed: Seed, #[case] version: OrdersVersion) {
.unwrap();

// Fill the order partially
let fill_amount = Amount::from_atoms(rng.gen_range(1..ask_amount.into_atoms()));
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, version);
let fill_amount = Amount::from_atoms(
rng.gen_range(min_fill_amount.into_atoms()..ask_amount.into_atoms()),
);
let filled_amount = calculate_fill_order(&tf, &order_id, fill_amount, version);
let left_to_fill = (ask_amount - fill_amount).unwrap();

Expand Down Expand Up @@ -1594,7 +1606,10 @@ fn reorg_after_create(#[case] seed: Seed, #[case] version: OrdersVersion) {
let reorg_common_ancestor = tf.best_block_id();

// Fill the order partially
let fill_amount = Amount::from_atoms(rng.gen_range(1..ask_amount.into_atoms()));
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, version);
let fill_amount = Amount::from_atoms(
rng.gen_range(min_fill_amount.into_atoms()..ask_amount.into_atoms()),
);
let filled_amount = calculate_fill_order(&tf, &order_id, fill_amount, version);
let left_to_fill = (ask_amount - fill_amount).unwrap();

Expand Down Expand Up @@ -2626,7 +2641,7 @@ fn orders_v1_activation(#[case] seed: Seed) {
.build_and_process(&mut rng)
.unwrap();

// Try to fill order before activation, check an error
// Try to fill order before activation, expect an error
{
let tx = TransactionBuilder::new()
.add_input(
Expand Down Expand Up @@ -2654,7 +2669,7 @@ fn orders_v1_activation(#[case] seed: Seed) {
);
}

// Try to conclude order before activation, check an error
// Try to conclude order before activation, expect an error
{
let tx = TransactionBuilder::new()
.add_input(
Expand Down Expand Up @@ -2682,7 +2697,7 @@ fn orders_v1_activation(#[case] seed: Seed) {
// produce an empty block and activate fork
tf.make_block_builder().build_and_process(&mut rng).unwrap();

// Try to fill order with deprecated command, check an error
// Try to fill order with deprecated command, expect an error
{
let tx = TransactionBuilder::new()
.add_input(
Expand Down Expand Up @@ -2714,7 +2729,7 @@ fn orders_v1_activation(#[case] seed: Seed) {
);
}

// Try to conclude order before activation, check an error
// Try to conclude order with deprecated command, expect an error
{
let tx = TransactionBuilder::new()
.add_input(
Expand Down Expand Up @@ -3175,7 +3190,10 @@ fn fill_freeze_conclude_order(#[case] seed: Seed) {
tf.make_block_builder().add_transaction(tx).build_and_process(&mut rng).unwrap();

// Fill order partially
let fill_amount = Amount::from_atoms(rng.gen_range(1..=ask_amount.into_atoms()));
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, OrdersVersion::V1);
let fill_amount = Amount::from_atoms(
rng.gen_range(min_fill_amount.into_atoms()..=ask_amount.into_atoms()),
);
let filled_amount = calculate_fill_order(&tf, &order_id, fill_amount, OrdersVersion::V1);
let left_to_fill = (ask_amount - fill_amount).unwrap();
let fill_tx = TransactionBuilder::new()
Expand Down Expand Up @@ -3260,7 +3278,7 @@ fn fill_freeze_conclude_order(#[case] seed: Seed) {
}
}

//Try freezing the order once more
// Try freezing the order once more
{
let result = tf
.make_block_builder()
Expand Down Expand Up @@ -3644,10 +3662,9 @@ fn fill_order_v1_must_not_be_signed(#[case] seed: Seed) {
let (sk, pk) = PrivateKey::new_from_rng(&mut rng, KeyKind::Secp256k1Schnorr);
let output_destination = Destination::PublicKey(pk);

let min_fill_amount =
initial_ask_amount.into_atoms().div_ceil(initial_give_amount.into_atoms());
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, OrdersVersion::V1);
let fill_amount = Amount::from_atoms(
rng.gen_range(min_fill_amount..initial_ask_amount.into_atoms() / 10),
rng.gen_range(min_fill_amount.into_atoms()..initial_ask_amount.into_atoms() / 10),
);
let filled_amount = calculate_fill_order(&tf, &order_id, fill_amount, OrdersVersion::V1);
let fill_order_input =
Expand Down Expand Up @@ -3778,6 +3795,7 @@ fn fill_order_v1_must_not_be_signed(#[case] seed: Seed) {
#[rstest]
#[trace]
#[case(Seed::from_entropy(), OrdersVersion::V0)]
#[trace]
#[case(Seed::from_entropy(), OrdersVersion::V1)]
fn fill_order_twice_in_same_block(
#[case] seed: Seed,
Expand Down Expand Up @@ -3810,15 +3828,18 @@ fn fill_order_twice_in_same_block(
let (_, pk) = PrivateKey::new_from_rng(&mut rng, KeyKind::Secp256k1Schnorr);
let output_destination = Destination::PublicKey(pk);

let fill_amount1 =
Amount::from_atoms(rng.gen_range(1..initial_ask_amount.into_atoms() / 3));
let min_fill_amount = order_min_non_zero_fill_amount(&tf, &order_id, version);
let fill_amount1 = Amount::from_atoms(
rng.gen_range(min_fill_amount.into_atoms()..initial_ask_amount.into_atoms() / 3),
);
let fill_amount2 = if use_same_amount {
fill_amount1
} else {
(|| {
for _ in 0..1000 {
let new_amount =
Amount::from_atoms(rng.gen_range(1..initial_ask_amount.into_atoms() / 3));
let new_amount = Amount::from_atoms(rng.gen_range(
min_fill_amount.into_atoms()..initial_ask_amount.into_atoms() / 3,
));
if new_amount != fill_amount1 {
return new_amount;
}
Expand Down
Loading