stacksgov / sips

Community-submitted Stacks Improvement Proposals (SIPs)
130 stars 80 forks source link

SIP 021: Trustless Two-way Peg to Bitcoin #113

Closed jcnelson closed 9 months ago

jcnelson commented 1 year ago

This SIP proposes a trustless two-way peg for Bitcoin, backed by Stackers and PoX.

For more background, see the following:

hstove commented 1 year ago

Nice job on the SIP!

Is there a place to discuss the lower-level mechanics of peg-in and peg-out?

For peg-in, I'd want to suggest mechanisms other than OP_RETURN-style transactions. Primarily for the benefit of user experience. For example, Magic uses a scheme where the STX address (pubkey) is "embedded" with an OP_DROP in the Bitcoin script. The big upside is being compatible with any vanilla BTC wallet. One downside is that it's non-discoverable - you'd have to notify the sBTC signers of the peg-in.

Anyways, not sure if this is the right place for discussion, but I'm just signaling:

wbnns commented 1 year ago

Would also be interested in what Hank said. :+1:

FriendsFerdinand commented 1 year ago

The OP_DROP method is worth exploring. Aside from the Bitcoin wallet flexibility, we might be able to offer the option to select a specific Stacks principal (maybe even Contract principal) which will receive the sBTC.

jcnelson commented 1 year ago

Is OP_DROP standard? OP_RETURN is, but if I were to craft a Bitcoin transaction with OP_DROP and a long data payload, would normal Bitcoin nodes relay it?

hstove commented 1 year ago

Is OP_DROP standard? OP_RETURN is, but if I were to craft a Bitcoin transaction with OP_DROP and a long data payload, would normal Bitcoin nodes relay it?

Yep! Here's a tx from the Magic protocol - the input includes OP_DROP (Click "details" next to the inputs/outputs section to see the redeem script)

edit: forgot the link 😛 https://mempool.space/tx/39b1019ec7b76cf852dad9440babbb8eea6d42d8f9825faaae7d5604338dfe1a

hstove commented 1 year ago

If we wanted to crudely "translate" this SIP's wire format for peg-ins to something using OP_DROP:

OP_PUSHBYTES_80 {sbtc_recipient_stacks_principal}
OP_DROP
// whatever the script sig is for the peg wallet:
OP_PUSHYBYTES_33 {peg_wallet_key}
OP_CHECKSIG
jcnelson commented 1 year ago

Interesting! I'll have to think about that. I confirmed by looking at IsStandardTx() in Bitcoin Core that the node doesn't care too much about the contents of the scriptSig when checking to see if it's standard, so that's reassuring.

How much easier is it to create a custom scriptSig in a vanilla Bitcoin wallet than an OP_RETURN output? Does the need for a custom scriptSig make it more difficult to support hardware wallets? These considerations still tilt me towards using the OP_RETURN approach. My goal here is to pick the serialization format that makes integration with other Bitcoin wallets the least painful.

@hstove The big upside is being compatible with any vanilla BTC wallet.

I'd like to know more about this, if you have any links or resources handy. I'm currently under the impression that any attempt to embed extra data into a Bitcoin transaction is going to be iffy at best, since either way we're expecting wallets to offer users a way to paste some additional data into the transaction. I'd be keen to know how well Trezors and Ledgers support this, too, since these systems are expected to decode a given scriptSig and determine where to insert the signature?

One downside is that it's non-discoverable - you'd have to notify the sBTC signers of the peg-in.

The sBTC signers are already going to be running a custom daemon that interacts with a Stacks node to learn about peg-ins and peg-out requests.

jcnelson commented 1 year ago

@FriendsFerdinand The OP_DROP method is worth exploring. Aside from the Bitcoin wallet flexibility, we might be able to offer the option to select a specific Stacks principal (maybe even Contract principal) which will receive the sBTC.

You can already do that with the OP_RETURN method. The appendix will need updating, but there's plenty of space in the peg-in transaction's OP_RETURN payload to encode a contract principal. I left a comment on it yesterday.

jcnelson commented 1 year ago

Something interesting came up in a working group call today that I want to field here.

What if sBTC holders got a PoX yield? We can do this without affecting the current PoX yield for STX holders.

Right now, between ~75 and ~325 reward slots per PoX reward phase are burnt. This is a consequence of how the stacking minimum is calculated -- unless 100% of STX are stacking, there will be some unclaimed reward slots.

What if, instead of burning BTC for those slots, the system diverted PoX payouts to sBTC holders? It would be used to incentivize people to move BTC into sBTC, and keep it there. The protocol wouldn't require you to lock your sBTC per se; instead, it could do something like use your lowest-ever sBTC balance in the prior reward cycle to determine how many of these leftover slots you'd qualify for, and distribute them similar to how they're distributed to Stackers today. There'd be a "sBTC balance minimum" that your lowest-ever balance must exceed in order to receive one or more reward slots.

Stackers would continue to receive PoX rewards as-is, and would thus be prioritized for PoX rewards over sBTC holders (which I think is fair, because STX has higher price risk than BTC). But there's no reason to burn the excess BTC in a reward phase when we could instead use it to help incentivize people to use sBTC.

What do you all think?

diwakergupta commented 1 year ago

Right now, between ~75 and ~325 reward slots per PoX reward phase are burnt. This is a consequence of how the stacking minimum is calculated -- unless 100% of STX are stacking, there will be some unclaimed reward slots.

What if, instead of burning BTC for those slots, the system diverted PoX payouts to sBTC holders?

In general I like the idea of doing some more useful with the BTC that currently gets burnt. What about a generalization where we decouple the actual usage: basically never burn any BTC; any BTC that would have been burnt gets locked up in a contract. And then you could have optionality in what happens to this BTC: as incentives for sBTC early adopters or for other "swim lanes" as @muneeb-ali calls them.

Thoughts?

jcnelson commented 1 year ago

basically never burn any BTC

Any BTC is untenable, which is why I specifically referred to the unused slots in the reward phase. In particular, the prepare phase must burn, for two reasons:

The unused slots could go to an arbitrary address. But if we want to redirect unused reward slots to sBTC holders in order to given them a yield, then I think the sBTC user experience would be best served by directing the rewards to them automatically instead of requiring users to go and claim them. As we learned with PoX, part of the "magic" of the UX is that you can watch BTC materialize in the Bitcoin wallet of your choice.

JoseSK999 commented 1 year ago

Hi everyone, I would like to point to some issues and concerns about the draft proposal.

First issue is about the Recovery Mode. Indeed peg-outs are theoretically processed in a finite period of time. However presumably the amount of sBTC would be high compared to the PoX rewards. At this moment there are $111 M of value stacked, and assuming a 200% collateralization ratio we could have up to $55 M in sBTC. In Recovery Mode, we can roughly process $14 million in a year ($0.27 per STX 1,000 of subsidy 52,500 blocks).

If a lot of users want to peg-out in such case they would need to wait for even more than a year. However if Stacks reputation was affected by this and price dropped with the uncertainty then it would take longer and longer to process the peg-outs, which is a negative feedback loop causing the peg to never be processed (less PoX rewards -> slower peg-outs -> less value of STX -> less PoX...) and the loss of value of sBTC.

Another issue is what happens if the collateralization limit is exceed. It's mentioned that no peg-ins are allowed, but the system needs to incentive somehow that people get their sBTC out so that the collateralization ratio is considered safe. If STX falls enough against BTC then we will reach under-collateralization. If peg-outs aren't sufficient we could perhaps burn sBTC to increase the collateralization ratio.

Finally, and most important, the mentioned oracle mechanism doesn't seem reliable. As mentioned in the draft, we need to pick the mining data for long periods of time to increase the cost of manipulating the oracle price. However this basically means that the oracle price doesn't reflect the current STX price but the mean price over the last N blocks.

If we choose N to be low the oracle can be cheaply manipulated, and if we choose N to be high it's expensive to manipulate but it doesn't reflect the current price.

Taking into account that price movements can be very sharp, it's risky to rely on such oracle.

jcnelson commented 1 year ago

First issue is about the Recovery Mode

The alternative is that a peg failure means that sBTC holders get nothing. Even if the Stacks chain takes years to pay back sBTC holders, or stops running PoX due to a lack of interest, that's still a preferable outcome.

Another issue is what happens if the collateralization limit is exceed.

Please see this thread: https://github.com/stacks-network/stacks/discussions/469#discussioncomment-4430658. The TL;DR is that the negative consequence of an undercollateralized peg -- i.e. theft of funds by Stackers -- is both unlikely in practice and easy to mitigate because (1) that would require that fewer than 30% of the stacked STX holders are honest, and (2) stackers can do many things to render themselves trustworthy, such as disclose their identities and operate in jurisdictions where theft of the BTC will result in criminal charges and jail time.

Also, please see the list of things that I'm actually worried will threaten the peg at the end of the thread. Banal concerns like security vunlerabilities in the implementation scare me a lot more than peg undercollateralization.

If peg-outs aren't sufficient we could perhaps burn sBTC to increase the collateralization ratio.

This is a non-starter. We're not going to burn sBTC, since that's protocol-level theft.

If we choose N to be low the oracle can be cheaply manipulated, and if we choose N to be high it's expensive to manipulate but it doesn't reflect the current price.

The alternative is to use an off-chain oracle, which can simply be hacked to return garbage data. Yes, using the behaviors of on-chain actors like miners and Stackers to derive the STX/BTC price means that there is a finite BTC expenditure by which these actors can change the derived STX/BTC price by an arbitrary amount. But, keep in mind that this behavior is visible on the Bitcoin chain, so anyone who would be negatively impacted by this behavior would be alerted well beforehand and can take appropriate action. Hacking an off-chain oracle, by contrast, is an invisible act, in which case affected parties would not be able to proactively protect themselves. Also, the cost of hacking an off-chain oracle is effectively unknowable and could be as low as $0. Making the oracle part of the consensus protocol at least gives us a lower bound on how costly it is to attack the system, which is pertinent information to would-be sBTC users.

JoseSK999 commented 1 year ago

Banal concerns like security vulnerabilities in the implementation scare me a lot more than peg undercollateralization.

I think the same. More than 70% of dishonest stackers doesn't seem realistic, but if the back-up script lowers that threshold (which seems necessary to prevent the loss of peg funds) then under-collateralization may become a more serious concern.

these actors can change the derived STX/BTC price

Yes, but the issue I was mentioning is that the oracle is not sensitive to sudden market movements, because the price returned is a mean of the price of last N blocks. If STX price crashes against BTC, then it will take some time for the oracle to reflect this. This would allow processing peg-ins in a moment where it shouldn't be allowed. There's a tradeoff between sensitivity of price and cost of manipulating it.

anyone who would be negatively impacted by this behavior would be alerted well beforehand and can take appropriate action.

What would be the specific actions that users could take in case miners spend too much?

FriendsFerdinand commented 1 year ago

@jcnelson How much easier is it to create a custom scriptSig in a vanilla Bitcoin wallet than an OP_RETURN output? Does the need for a custom scriptSig make it more difficult to support hardware wallets? These considerations still tilt me towards using the OP_RETURN approach. My goal here is to pick the serialization format that makes integration with other Bitcoin wallets the least painful.

In the case of Magic, the scriptsig is not generated in the Bitcoin wallet. It is generated in the app. The web app generates a HTLC with data from the Hiro wallet then displays a P2SH address so that the user can make a payment to it. The Bitcoin wallet used by the user does not have to be aware of the sBTC implementation.

This is why the sBTC signers would need to be notified of the peg-in. Because, the transaction just looks like a regular payment to an address, unless you know what the scriptsig looks like.

You can see Magic working here: https://testnet.magic.fun/

jcnelson commented 1 year ago

but if the back-up script lowers that threshold (which seems necessary to prevent the loss of peg funds) then under-collateralization may become a more serious concern.

Right, that's one way a security vulnerability could slip in. In this specific case, the vulnerability is mitigated by a lengthy voting process by which a backup script is chosen, so there would be plenty of time to voice concerns and even peg-out if the upcoming peg wallet is not trustworthy.

because the price returned is a mean of the price of last N blocks

I don't think it will be the average of N blocks. I think it will be a non-linear function of the last N blocks, and would take into account multiple parameters such as the distribution of STX/BTC spends per block (e.g. perhaps taking the median), how old the block is, whether or not the block is a flashblock, how many miners participated, and so on.

There's a tradeoff between sensitivity of price and cost of manipulating it.

I think the system will err on the side of being expensive to manipulate. The reason is that it's very apparent to sBTC holders what the USD prices of STX and BTC are, so if there's a sudden drop in the price of STX to BTC, they would be more inclined to peg-out regardless of what the oracle calculated.

The oracle's primary purpose here is to warn users not to put too much BTC in that Stacker incentives could be warped. The calculation would also low-ball the true STX/BTC price.

What would be the specific actions that users could take in case miners spend too much?

If evil miners (who could also be evil Stackers) are deliberately mining at a loss for a prolonged period of time, ostensibly to manipulate the oracle, then the following actions could be taken:

JoseSK999 commented 1 year ago

it's very apparent to sBTC holders what the USD prices of STX and BTC are, so if there's a sudden drop in the price of STX to BTC, they would be more inclined to peg-out regardless of what the oracle calculated. The oracle's primary purpose here is to warn users not to put too much BTC in that Stacker incentives could be warped.

So I don't really know what is the point of the on-chain oracle. The oracle is not used to limit the collateralization ratio, since the only thing perhaps enforced is pausing peg-ins, which is not enough if STX price keeps falling against BTC. Not even pausing peg-ins can actually be enforced (without consensus changes) if the oracle is manipulated. And anyway, if it's manipulated, users can see the real STX and BTC price, and use that information to peg-out and not peg-in if necessary.

In other words the oracle is not reliable and we instead rely on users and wallets self-verifying the actual STX and BTC prices, and pegging-out if the collateral ratio seems risky to them. But it's likely that most users do not peg-out (perhaps because they are using smart contracts that lock their funds, they lost their private keys, or other reasons) even when the collateralization ratio is way too low. This damages the Stacker incentives.

JoseSK999 commented 1 year ago

@hstove @FriendsFerdinand I think in this case embedding the Stacks destination data inside the Bitcoin peg-in address is not suitable because the actual data is only revealed on-chain after spending from that address (by revealing the redeem script). The Stacks network needs, however, to agree on these destination addresses soon after the transaction is made to enforce and verify the peg-ins.

By using OP_RETURNs it's guaranteed that we are in consensus about Stacks destinations, since peg-in transactions record it. But if we just commit to the data in the Bitcoin peg-in address, reaching consensus is non-trivial (and if the data is missing we cannot identify the peg-in transaction) which may open up potential network attacks.

jcnelson commented 9 months ago

Hey folks, thanks for everyone's feedback! This SIP has been superseded by #155 and #156. Let's continue the discussion there! :heart: