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

unconfirmed tx chaining. spend unconfirmed utxos. #197

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

dan-da
Copy link
Collaborator

@dan-da dan-da commented Oct 3, 2024

Addresses #189

Extends #184. ( diff )

This PR implements chaining of unconfirmed transactions.

Or at least it appears to. I've been told this is not feasible without triton-vm programs.

So maybe it only appears to work, but is not fully correct. That's for reviewers to decide, and tell me how the approach is wrong. Or maybe it is only cut-through that requires tricky triton-vm stuff, and this PR doesn't attempt cut-through.

Primarily for this reason, I am making this a draft PR. Another reason is that this PR does not (yet?) attempt to handle (or test) the case where unconfirmed tx B depends on A, and B has a higher fee, so it gets confirmed in a block and A does not. I'm not certain what the code will do... undefined behavior.

The approach taken here is a natural extension of the changes in #184. Namely the wallet-state keeps track of all wallet-affecting utxos in the mempool. It considers them for balance calculations, for selecting inputs, when scanning for spent-inputs, and when updating wallet state with a new block.

The PR includes a test case, spend_unconfirmed_tx() in wallet_state.rs. The test case starts with a single input utxo then sends Tx A worth 5, then tx B worth 10 in the same block (B depends on A) and verifies balances, then mines another block and verifies balances. In detail:

  1. mines a block to our wallet, creating confirmed utxo A with 100 tokens.
  2. sends 5 coins to an external address spending A and creating unconfirmed utxo B with 95 tokens.
  3. sends 10 coins to an external address spending B and creating unconfirmed utxo C with 85 tokens.
  4. verifies that confirmed balance is 100 (A) and unconfirmed balance is 85 (C).
  5. mines a block to our wallet, confirming B and C, and creating utxo D with 100 tokens, for total confirmed balance of 185 (C+D)
  6. confirms that both the unconfirmed and confirmed balance is 185.

steps 5 and 6 were the trickiest as it required some changes to WalletState::update_wallet_state_with_new_block() which is a complex method.

There may be better way(s) to represent the unconfirmed utxos in WalletStatus for more efficient balance calcs.

But for now, I don't want to put further effort into improving unless/until the concept/direction is approved by reviewers.

My thought is that this approach may not be the best/ideal way to achieve this functionality, but if not fatally incorrect then it may be worth having as a stop-gap for now, until a better approach can be implemented.

wallet subscribes to mempool via tokio broadcast to track owned utxos.

Changes:

 * add spent_utxos, unspent_utxos lists to WalletState struct
 * add WalletState::handle_mempool_event()
 * add test confirmed_and_unconfirmed_balance()
 * add Mempool::event_channel (tokio broadcast channel)
 * Mempool faillible mutation methods return Result()
 * Mempool mutable methods broadcast MempoolEvent
 * add tests::shared::mine_block_to_wallet()
 * lib.rs: spawn wallet task for listening to mempool events
   and dispatch to WalletState for handling.
 * add locks::tokio::AtomicRw::try_lock_guard_mut()
removes the mempool broadcast channel and wallet listener task.

Instead all mempool mutations go through GlobalState methods
which inform wallet of the changes.  This makes changes atomic
over mempool+wallet so they are always in sync.

Changes:
 * remove Mempool::event_channel
 * Mempool &mut methods only callable by super
 * Mempool &mut methods return MempoolEvent(s)
 * add MempoolEvent::UpdateTxMutatorSet.  (unused)
 * add GlobalState methods: mempool_clear, mempool_insert,
    mempool_prune_stale_transactions
 * remove spawn_wallet_task from lib.rs
 * add/improve doc-comments
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.

1 participant