Replies: 10 comments 21 replies
-
Under Nakamoto Stacks forks with Bitcoin, so if there's Bitcoin fork the Stacks chain would get rewritten starting at the point of the fork. The TX to mint sBTC would then be on an invalid Stacks block and the signers would refuse to build upon it. Is this post only relevant if there's 1-1 transaction replay? This exact concern is why it's not included in SIP-021 but I'm wondering if I'm missing something. |
Beta Was this translation helpful? Give feedback.
-
Seems like for withdrawal there might need to be a 3 block delay to make sure the Withdrawal is final? |
Beta Was this translation helpful? Give feedback.
-
Would it be feasible for there to be a "staging" contract where any sBTC would live and if it's been in there for more than 3 Bitcoin blocks the peg out can be confirmed in 1 Bitcoin block? The staging contract would not be dependent on the Bitcoin blockchain so there's no potential for taint, which is the crux of this issue. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Thinking out loud about the constraints of this, once a Bitcoin transaction is created for a withdrawal there's nothing we can do to guarantee that we take it back. The singular constraint should be this: There must be a valid confirmed sBTC withdrawal on Stacks for there to be a withdrawal on Bitcoin. I see no way for a Bitcoin transaction's validity to be conditional on the chain instance that it lives in. As far as I see, transactions have no way to access any part of the overall Bitcoin chain that differentiates one fork from another except in the transactions that came before it, and those transactions are also incapable of accessing fork related data, so the issue cascades. @netrome It sounds like you are suggesting a way around this but I'll admit I'm also not following it entirely. My above reasoning makes me think that it's information-theoretically impossible to impose any kind of restriction on when a transaction is valid once it has been sent because the act of expecting transactions to come before doesn't impose a greater restriction. The problem then is this: Signers can make a withdrawal on Bitcoin before the withdrawal on Stacks is sufficiently final. This is where we need to determine some of comfort in finality that sBTC should be comfortable with. I believe it's possible to maintain a contract that we can guarantee isn't conditional on any aspect of the Bitcoin blockchain so on any Bitcoin fork it's guaranteed to be valid, and the Signers can then only accept withdrawals from sBTC tokens that have "lived" in a verifiably un-Bitcoin-impacted state for the last Under a scheme like this the withdrawal will be a single Bitcoin block if the sBTC tokens have been living in that contract for the last several blocks, but will take I'm making some assertions about what it means for a SIP-10 token to "live" in a certain state, so I defer to you two on whether this makes any sense. I believe there's a path here where sBTC Bootstrap Signers can just reject any transactions that could be invalidated by the act of Bitcoin forking, and instead of doing some complex taint analysis the sBTC signers just verify that the tokens went through what is effectively a "cleaning procedure" ahead of time. Note on Bitcoin FinalityThe Stacks Blockchain has Bitcoin finality because each tenure is meant to have a valid sortition on the bitcoin blockchain. Tenures can be extended without a valid sortition. This means that if there are three tenure extends because there were three Bitcoin blocks that for whatever reason didn't have a valid sortition winner those Bitcoin blocks would have no impact on the finality of the Stacks Blockchain. For precision we may want to talk about finality in terms of tenure changes as opposed to Bitcoin blocks, because a tenure change needs a Bitcoin block and is the mechanism for finality, but a Bitcoin block does not need a tenure change. Waiting |
Beta Was this translation helpful? Give feedback.
-
There's no way to deterministically know which withdraws are verifiably "immune" to Bitcoin forks. If I'm missing something here, please let me know! You could theoretically say "you can only make a withdrawal if you call our contract directly, and not via a different contract". This would prevent the "coin flip" example. But then you have a different problem - the attacker can simply make two transactions. The first would be a coin flip that transfers their sBTC, and the second would be the withdraw request. So then you have to try and solve "what is the total state tree above this transaction that could have effected this withdraw". And even then, if we said "you can't have made any transactions within X blocks of your withdrawals" (which is infeasible from a UX perspective), the attack vector comes from transferring funds from A to B after a coin flip, and then withdrawing from B. |
Beta Was this translation helpful? Give feedback.
-
We need to revisit the discussion on the Withdrawal script because I think there's no way to avoid initiating it on Bitcoin: #17 |
Beta Was this translation helpful? Give feedback.
-
I think I only digested 30% of this ticket, but it's sort of related to bitcoin finality. Can’t the Clarity dataspace + stacks chain be our source of truth? (especially since we won’t have forks post-Nakamoto) |
Beta Was this translation helpful? Give feedback.
-
Two different options
It sounds like 6 Bitcoin blocks would be a better option because it's an industry standard. We need to finalize this aspect as soon as possible. If we think the two transaction approach could be faster to implement lets look otherwise lets commit to the 6 block approach. |
Beta Was this translation helpful? Give feedback.
-
I'm closing this discussion because we've solidified that sBTC-v1 will handle forks by ensuring the withdrawal is on a block in the Stacks blockchain that is sufficiently final. We will want to revisit this for sBTC-v2 and beyond; perhaps there's a BitVM procedure that can tie a transaction to a specific Bitcoin Chainstate. The next steps is to include the following information into #16.
|
Beta Was this translation helpful? Give feedback.
-
A stated high-level goal is to process both deposits and withdraws as soon as possible. Ideally, this could have a 1-block gap. As I've been thinking about v1 and how we can build it without being consensus-critical, I think there are few unresolved questions we need to figure out regarding this time.
As background for this issue, I'm working under the assumption that Signers will maintain strict transaction ordering, even in the case of Bitcoin forks.
To demonstrate the potential issues, let me outline an "attack scenario", along with potential mitigations:
Deposits
N
N+1
N
, such as via replace-by-fee. A miner would be able to easily trigger this scenario (a "Finney attack").I think the solution here is that our sBTC
mint
function must include a reference to the known latest Bitcoin(block-hash, height)
tuple as part of the contract call payload. Inside the function, the contract checks that(get-burn-block-info? header-hash height)
is equal to the signer-provided block hash. If this check fails, the whole mint function fails, thus preventing a double spend.While this prevents a double spent deposit, it means the signers would have to re-submit mint transactions in the case of Bitcoin forks. This adds a decent amount of complexity, because in the "happy path" we've already consumed the deposit UTXO, but we need to re-process the mint transaction.
In sBTC v2, where these mechanisms are consensus-critical, the sBTC mint would never occur, because it would be part of Stacks nodes' internal processing of sBTC deposits.
Withdraws
An attack scenario for withdraws is:
u128::MAX / 2
. 50% of the time, this check will be "heads".Then, Bitcoin forks, and the Stacks signers preserve transaction ordering while re-executing each transaction. This time the result is "heads", so the sBTC withdraw request is not made. But Alice has already received her BTC withdraw. Thus, Alice has "double spent".
This attack isn't costly other than in transaction fees - in both cases Alice keeps control of her funds (in either sBTC or BTC).
I still need to think through this more, but my current thought is that the only way to handle this in sBTC v1 is to mandate a delay between withdraw requests and sending BTC withdraws. A typical delay that exchanges use is 6 blocks, but I'm sure there is good research out there about the occurrence of re-orgs. 2 blocks is relatively common, and more than that is rare.
Beta Was this translation helpful? Give feedback.
All reactions