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

Thv/#145 reorganization of mempool #153

Merged
merged 14 commits into from
May 23, 2024
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ test: export RUST_BACKTRACE = 1
test:
$(info RUSTFLAGS is $(RUSTFLAGS))
cargo nextest r
cargo test --doc

bench:
$(info RUSTFLAGS is $(RUSTFLAGS))
Expand Down
51 changes: 51 additions & 0 deletions developer_docs/reorganizations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# How neptune-core handles reorganizations
Neptune is a blockchain which features recursive STARK proofs as part of its
consensus mechanism. This implies that participants can synchronize trustlessly
by simply downloading the latest block and verifying this. Unlike most other
blockchains, it is not necessary to download all historical blocks to get a
cryptographically verified view of the state of the blockchain.

It is possible, though, to run an archival node that downloads all historical
blocks. This archival node comes with additional functionality such as being
able to reconstruct transaction's membership proofs, provide some historical
transaction statistics, and allow other archival nodes to synchronize.

This document provides an overview of how different parts of the client's state
handle reorganizations.

## State overview
The client's state consists of the following parts:
- wallet
- light state
- archival state (optional)
- mempool

The wallet handles transactions that the client holds the spending keys for.
The light state contains the latest block which verifies the validity of the
entire history of the blockchain. The archival state is optional and allows,
among other things, the client to re-synchronize wallets that are no longer
Sword-Smith marked this conversation as resolved.
Show resolved Hide resolved
up-to-date. The mempool keeps track of transactions that are not yet included
in blocks, thus allowing miners to confirm transactions by picking some from
the mempool to include in the next block.

### Wallet
The wallet can handle reorganizations that are up to `n` blocks deep, where `n`
Copy link
Collaborator

@dan-da dan-da May 22, 2024

Choose a reason for hiding this comment

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

What happens if my wallet has a (monitored) utxo that gets dropped from the mempool during re-org? iiuc, it seems the wallet would be out-of-sync with the mempool, but not the wallet's fault.

edit: I guess that prune-abandoned-monitored-utxos can deal with this situation. Perhaps it deserves a mention here.

Copy link
Member Author

@Sword-Smith Sword-Smith May 23, 2024

Choose a reason for hiding this comment

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

The wallet currently only deals with and displays transactions that have been mined. It completely ignores anything that's in the mempool.

I'd be happy to have the wallet be able to read from the mempool eventually, but that is not a concern for this PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

Does that address your question? If not, please elaborate :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

It completely ignores anything that's in the mempool.

Ok, so that implies that spends are not reflected in the wallet prior to confirmation either.

Eg, when I send a payment P for amount A, and P is not yet confirmed in a block:

  1. A is not reflected in the wallet balance.
  2. P is not shown in the wallet's transaction history.
  3. The wallet would let me attempt to re-spend P's inputs because it is unaware that those utxo are already in the mempool. But any such attempt would fail, because spend() actually does check the mempool.

Is the above accurate?

If so, then I think this behavior deserves a mention in the docs somewhere also, until such time as the wallet becomes mempool-aware.

can be controlled with the CLI argument `number_of_mps_per_utxo`.
Reorganizations that are deeper than this will make the membership proofs of
the transactions temporarily invalid until they can be recovered either through
the client's own archival state (if it exists), or through a peer's archival
state. This recovery process happens automatically.

### Light State
The light state only contains the latest block and thus can handle arbitrarily
deep reorganizations.

### Archival State
The archival state can handle arbitrarily deep reorganizations.

### Mempool
The mempool can *currently* not handle reorganizations. If a reorganization
occurs, all transactions in the mempool will be deleted, and the initiator of a
transaction will have to publish the transaction again. The transactions that
were included in blocks that are abandoned through this reorganization are not
added to the mempool again, they also have to be published again.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub async fn initialize(cli_args: cli_args::Args) -> Result<()> {
archival_state,
};
let blockchain_state = BlockchainState::Archival(blockchain_archival_state);
let mempool = Mempool::new(cli_args.max_mempool_size);
let mempool = Mempool::new(cli_args.max_mempool_size, latest_block.hash());
let global_state_lock = GlobalStateLock::new(
wallet_state,
blockchain_state,
Expand Down
Loading
Loading