Skip to content

Provide guidance on microblocks UX for app integration #1232

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

Closed
markmhendrickson opened this issue Jul 2, 2021 · 7 comments · Fixed by #1254
Closed

Provide guidance on microblocks UX for app integration #1232

markmhendrickson opened this issue Jul 2, 2021 · 7 comments · Fixed by #1254

Comments

@markmhendrickson
Copy link
Contributor

markmhendrickson commented Jul 2, 2021

Currently we have a bit of stub guidance for how apps should integrate microblocks into their UX here:

https://docs.stacks.co/understand-stacks/microblocks#application-design

The state of microblock transactions should be carefully communicated to users. No transaction is final until it's included in an anchor block, and your application design should reflect this.

I wonder whether we could start providing more specific guidance here that would be actionable for developers such as @yknl who was asking about this for Xverse.

I also notice that we're suggesting the UX should not reflect finality of transactions until inclusion in anchor blocks whereas @jasperjansz has expressed the opposite approach may be best (that apps can consider transactions final upon inclusion in microblocks and before anchor blocks). So we may need to decide more clearly just what approach we want to recommend.

We're also planning to release our own UX implementations in the wallets and explorer soon, which consider transactions as rather final upon inclusion in microblocks – but also distinguish between the two states with visual treatment in the explorer only. Perhaps we could simply lay out our two distinct approaches for the wallets and explorer, explaining our rationale for each.

See https://www.figma.com/proto/i2H9felRYWAZQgsfX7EpZz/microblocks?node-id=39%3A4125

cc @pgray-hiro @jasperjansz

@pgray-hiro
Copy link
Contributor

the opposite approach may be best (that apps can consider transactions final upon inclusion in microblocks and before anchor blocks)

This is really something that I would want to get @diwakergupta to weigh in on.

@diwakergupta
Copy link
Member

the opposite approach may be best (that apps can consider transactions final upon inclusion in microblocks and before anchor blocks)

This is really something that I would want to get @diwakergupta to weigh in on.

Happy to chime in. Agreed we should provide more specific guidance: the biggest challenge here will be to provide simple, clear, concise and actionable guidance while taking care to set expectations / capture relevant nuance for microblock behavior.

It's fine to point to Hiro's wallets as one way apps could design the UX for microblocks. Other apps could make different choices if they want to.

Note that we now have some empirical data for microblocks, and we should use that to inform the guidance.

No transaction is final until it's included in an anchor block, and your application design should reflect this.

Aside: The original "no transaction is final until" language could be softened IMO -- as I've mentioned previously, using "final" in the colloquial sense (i.e. permanently irreversible) is technically inaccurate in any blockchain that permits forks. In theory, even a transaction included in an anchor block has some non-zero probability of being reversed (that decreases exponentially as more blocks build on top of that anchor block)

@markmhendrickson
Copy link
Contributor Author

Thanks @diwakergupta 🙏 I spoke with @jasperjansz about this earlier today and he's going to chime in with his thoughts as well.

@jasperjansz
Copy link
Contributor

If I were to advise a developer I'd say:

  1. There's no "final", finality is always probabilistic. More block confirmations leads to a higher probability.
  2. For your app, what is more important: speed or finality? Coinbase used to wait 6 block confirmations before crediting an incoming transaction to your account — that's very cautious and not fast.

If you're dealing with an app where the value of a transaction is low and speed is important, such as Heystack, it makes sense to consider inclusion in a microblock "confirmed". It would lead to a much better user experience. Now let's say you're an exchange where value can be really high and speed is not that important, you'd probably want to wait for at least one anchor block.

@kantai
Copy link
Collaborator

kantai commented Jul 14, 2021

Apologies in advance for a brain dump in (perhaps) the wrong place, but to follow up on some of the discussion here and expand a bit on @jasperjansz's response, which I agree with:

Dr. Microblocks or: How I Learned to Stop Worrying and Love Reorgs

First things first, what are microblocks, and why are they so scary?

Microblocks are merely blocks of transactions included by a miner after they mined their block, but before the next block has been selected. Transactions included in these microblocks have been processed by the network, and their results are known. But these transactions are not as confirmed as the transactions in the preceding block.

The way to think about this is that transactions in microblocks are really “pending” state, not terribly different from a transaction that is still in the mempool. It’s more likely to get confirmed than a transaction just sitting in the mempool, but the security status of the transaction isn’t different.

If you think of the world purely in terms of the number of “confirmations” a transaction has, you can compare the lifecycle of transactions in microblocks and transactions in anchor blocks as follows:

Transaction 1 is broadcasted to the mempool. It has 0 confirmations.
Transaction 1 is included in a microblock. It still has 0 confirmations, but the results of the transaction are know “known”.
The next Stacks block confirms the prior microblock. Transaction 1 has 1 confirmation.
The next Stacks block confirms the prior block. Transaction 1 has 2 confirmations.
The next Stacks block confirms the prior block. Transaction 1 has 3 confirmations.

Now instead, think about a transaction included in an anchor block directly:

Transaction 2 is broadcasted to the mempool. It has 0 confirmations.
The next Stacks block includes Transaction 2. Transaction 2 has 1 confirmation.
The next Stacks block confirms the prior block. Transaction 2 has 2 confirmations.
The next Stacks block confirms the prior block. Transaction 2 has 3 confirmations.

The lifecycles of the two transactions are very similar. So what’s the point of the microblocks? The answer is in computing pending state.

In Bitcoin wallets, it’s very common for wallets to display 0-confirmation balances: i.e., your wallet balance with any mempool transactions affecting your wallet applied. This is useful, because it tells you when you’ve sent a transaction or received one. Many applications which aren’t so worried about transactions being reversed can even operate with a 0-confirmation transaction. However, in blockchains with smart contracts, displaying pending state is much harder. A given transaction isn’t just transferring inputs to outputs, it could be calling smart contracts, emitting events, etc. A transaction processed in a microblock generates all of that information.

So how do I work with microblocks?

In most cases, information from microblocks should be treated like information from any other block. Wallets and explorer should display the consequences of microblock transactions as the current state of the network. However, this state should be acknowledged as tentative somehow. Below is how blockchain.com displays an address. The balance includes pending state. That mempool transaction can easily be replaced and double-spent.

Screen Shot 2021-07-14 at 4 04 33 PM

Furthermore, a microblock transaction can end up being “reorganized” into the next block rather than just confirmed as is — this happens roughly 25% of the time according to our statistics so far (see: hirosystems/stacks-blockchain-api#640 (comment)). Because of this, the UI should be able to explain to users what “happened” if the outputs of the transaction changed, or if the transaction’s associated block changed (even a tooltip like: “this transaction was originally included in a microblock, but ended up moving into an anchor block instead”). This is the exact same outcome as if a 1-block fork occurred.

But really, how do I work with microblocks?

  • APIs
    • State querying endpoints (like say a balance lookup) should come in two varieties (or, to reduce API calls, include two sets of results): “confirmed” and “unconfirmed”. We can hard code what “confirmed” means (i.e., 1 confirmation), or it could be made configurable (someone could specify that “confirmed” means 3 confirmations). Unconfirmed would always return state with all known microblocks applied.
    • Transaction lookups would return information about the transaction in the canonical fork. They should also return information about whether or not the transaction was previously included in another block in another canonical fork.
  • Explorers
    • Display pending state, but warn that a transaction is still pending. Indicate in the balance that it depends on pending state.
  • Wallets
    • Display pending state, but warn that a transaction is still pending. Indicate in the balance that it depends on pending state.
  • Exchanges
    • Continue to count confirmations like before — microblocks shouldn’t make any difference here.
  • Applications
    • This is super-app-dependent. In many applications, 0-confirmations is fine! BNS is almost certainly one of these. In other applications, 3-confirmations is probably prefered. But like exchanges, microblocks don’t change that calculus at all!

@markmhendrickson
Copy link
Contributor Author

markmhendrickson commented Jul 15, 2021

Thanks @kantai, this is a great level of detail to provide for developers. Something like the last section will be especially helpful for articulating the "it depends" nature of this UX challenge, for different types of interfaces with different needs.

@jasperjansz perhaps we should add an indicator alongside any balance in the wallets or explorer that has proactively incorporated pending / microblock state, as Aaron suggests here?

The Figma linked above doesn't exhibit balance UX for the wallets or explorer in general, so perhaps we should add it (not only to clarify implementation for these products but also to serve as material for this documentation)?

Note as well that we've recently decided on the UserX team to distinguish all microblock-included transactions in the wallets in addition to the explorer (e.g. with a ⚡️ symbol). This change also aligns with Aaron's guidance above.

@diwakergupta
Copy link
Member

@pgray-hiro @agraebe not sure if we've already used this, but Aaron and Ludo had put together this helpful state diagram for microblocks a while back:

Microblocks State Diagram

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

Successfully merging a pull request may close this issue.

5 participants