Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase test coverage for transaction pool module #16415

Open
wants to merge 4 commits into
base: compatible
Choose a base branch
from

Conversation

dkijania
Copy link
Member

@dkijania dkijania commented Dec 12, 2024

Increase coverage for ledger reorg functionality with new property based tests. Apart from general all valid commands generator one can also configure generator to send some edge cases (zkapp which blocking sending further transactions or replace small amount transaction with big amount transaction which should prevent from applying entire chain of commands due to balance drain) . Last commit propose reorganization of all transaction tests since reorg tests require mini test framework.

PR related to #16401

Tests currently are failing but after we merge above PR they should be green.

Notes to reviewer:

  • I'm not sure if test reorganization is a good idea (commit e38d28d), no problem with reverting this to commit 9cdcb4d). My reasoning was that I added a quite big chunk of code and thought that maybe we should split tests for better readibility. There is already network_pool/tests folder which contains alco tests. Maybe we can put all of them there too ?
  • I've done one uber property test, which helped me understand how reorg is working. I'm wondering if we should add more fine grain tests which could be used also documentation for reorg mechanism
  • I had a big troubles to nicely modify already built User_command (adding nonces or create mirror transactions in other branch), so i decided to work on specification on minor/major sequences first and then create commands based on them.

@dkijania
Copy link
Member Author

!ci-build-me

@dkijania dkijania self-assigned this Dec 13, 2024
@dkijania dkijania marked this pull request as ready for review December 13, 2024 11:23
@dkijania dkijania requested a review from a team as a code owner December 13, 2024 11:23
@georgeee
Copy link
Member

georgeee commented Jan 7, 2025

I like the idea of extraction of transaction pool tests to a standalone file. Let's restructure the PR in the following way:

  1. Create a separate predecessor PR that will move the test code out of transaction_pool.ml to test/ subdirectory
  2. Retain in this PR only what's related to new tests

@dkijania

Copy link
Member

@georgeee georgeee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review is still in progress, posting the first few comments...

src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
if Keypair.equal test_keys.(n) x then n
else find_in_test_keys x ~n:(n+1)

let create key_idx balance nonce =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this function and create values directly

Mina_ledger.Ledger.apply_initial_ledger_state new_ledger init_ledger_state ;
t.best_tip_ref := new_ledger

let ledger_snapshot t =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest to inline it into src/lib/network_pool/transacation_pool_reorg_tests.ml and return Account_spec.t instead of a tuple

let apply_payment amount fee t =
create t.key_idx (t.balance - amount - fee) (t.nonce + 1)

let apply_zkapp fee t = create t.key_idx (t.balance - fee) (t.nonce + 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all zkapps in this test created with with zero account updates?

If so, this looks ok, but let's add a comment in the code about this matter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe name is misleading. apply_zkapp function in context of account_spec is only modify spec state which we are using for tracking balance and nonce. So no zkapp command or update is done. Just noting that from this account zkapp was sent and we are deducting fee and increases nonce

let minor_acc_opt = Array.find_map minor ~f:(fun minor_acc ->
Array.find major ~f:(fun major_acc ->
Int.equal minor_acc.nonce major_acc.nonce &&
minor_acc.balance - major_acc.balance < 100_000_000_000
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the chance that such two accounts won't be found?

Won't the probability of the test being executed be too low?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we:

  • pick a random account with initial balance B (which won't be used in a generator for other transactions)
  • generate two random sequences s1 and s2 (small, 2-10 transactions) of transactions using it, which won't use more than B/2 MINA in total, let's assume |s1| < |s2|
  • calculate total balance spent in sequence s1 as b1
  • select a number i: |s1| < i < |s2|
  • calculate sum t2 as balance spent by transactions in s2 with index range [|s1|, i)
  • increase amount of a random transaction in s1 by B - b1 - t2
  • inject the resulting sequences s1 and s2 randomly into major and minor sequences (at random indices, preserving order)

This way we deterministically have a use case, not on the luck (later sounds a bit more complicated to analyze than it should be, to my taste). Also, I am not sure if the current method is correct at all.

src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
; ("major accounts state", `List log_major_accounts_state)
];

let prefix = gen_commands_from_specs (Array.concat [prefix_specs]) test in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply let prefix = gen_commands_from_specs prefix_specs test in ??

Copy link
Member Author

@dkijania dkijania Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see it. thanks!

src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
src/lib/network_pool/transacation_pool_reorg_tests.ml Outdated Show resolved Hide resolved
let minor_acc_opt = Array.find_map minor ~f:(fun minor_acc ->
Array.find major ~f:(fun major_acc ->
Int.equal minor_acc.nonce major_acc.nonce &&
minor_acc.balance - major_acc.balance < 100_000_000_000
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we:

  • pick a random account with initial balance B (which won't be used in a generator for other transactions)
  • generate two random sequences s1 and s2 (small, 2-10 transactions) of transactions using it, which won't use more than B/2 MINA in total, let's assume |s1| < |s2|
  • calculate total balance spent in sequence s1 as b1
  • select a number i: |s1| < i < |s2|
  • calculate sum t2 as balance spent by transactions in s2 with index range [|s1|, i)
  • increase amount of a random transaction in s1 by B - b1 - t2
  • inject the resulting sequences s1 and s2 randomly into major and minor sequences (at random indices, preserving order)

This way we deterministically have a use case, not on the luck (later sounds a bit more complicated to analyze than it should be, to my taste). Also, I am not sure if the current method is correct at all.

let gen_branches init_ledger_state ~permission_change ~limited_capacity ?(sequence_max_length=3) () =
let open Quickcheck.Generator.Let_syntax in
let%bind prefix_length = Int.gen_incl 1 sequence_max_length in
let%bind branch_length = Int.gen_incl 1 sequence_max_length in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's generate sequence length separately for minor and major, they do not have to be the same

Otherwise it will be dropped as we already have transaction with the same nonce from major sequence
*)
let sender = major.(sender.key_idx) in
let%bind aux_minor_cmd = Command_spec.gen_single_from minor (sender.key_idx,sender) in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic won't imitate the required behavior if maj1 >= min1, where maj1 and min1 represent the number of txs from sender in major and minor respectively.

I.e. aux_minor_cmd will simply be thrown away. We need to add as many aux cmds as necessary to ensure that resulting minor sequence has more transactions from sender than major.

*)
let%bind permission_change_cmd = Command_spec.gen_zkapp_blocking_send major in
let sender = Command_spec.sender permission_change_cmd in
(* We need to increase nonce so transaction has a chance to be placed in the pool.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is the actual increase happening?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In gen_single_from function

let%bind receiver_idx = test_keys |> Array.mapi ~f:(fun i _-> i) |> Quickcheck_lib.of_array in
let%bind amount = Int.gen_incl 5_000_000_000_000 10_000_000_000_000 in
let new_account_spec = Account_spec.apply_payment amount minimum_fee account_spec in
Array.set spec idx new_account_spec;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if balance goes negative? Perhaps we set amount to 0 if amount is less than balance. And if balance is less than min fee, throw an exception.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case of fee applies to zkapp tx above as well

];

let assert_pool_contains pool_state (pk,nonce)=
let actual_opt = List.find pool_state ~f:(fun (fee_payer_pk, actual_nonce ) ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrite this and next function: extract calculation of actual_opt into a helper function

)
in
match account_spec with
| Some account_spec ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract sent_blocking_zkapp, total_cost out of match construction (put it before).

Rewrite match without ifs:

| Some account_spec when sender.nonce < account_spec.nonce -> (..)
| Some account_spec when sent_blocking_zkapp major_specs pk -> (..)
| Some account_spec when account_spec.balance > total_cost  -> (..)
| Some account_spec -> (..)
| None -> (..)

@dkijania dkijania mentioned this pull request Jan 8, 2025
@@ -17,7 +17,7 @@ module Account_spec = struct
; nonce: int
} [@@deriving sexp]

let rec find_in_test_keys ?(n=0) (x:Keypair.t) =
let find_in_test_keys (x : Keypair.t) = Array.findi_exn test_keys ~f:(fun _ -> Keypair.equal x) |> fst
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And remove the two lines below

@dkijania dkijania changed the base branch from master to compatible January 8, 2025 19:34
@dkijania dkijania requested a review from a team as a code owner January 8, 2025 19:34
@dkijania dkijania force-pushed the dkijania/transaction_pool_tests branch from cb1b2ac to 07d610b Compare January 11, 2025 16:21
…ds from limited account capacity with rest of commands
@dkijania
Copy link
Member Author

!ci-build-me

@dkijania
Copy link
Member Author

!ci-build-me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants