stacks-network / sbtc-developer-release

sBTC primitives, signer components, helper tools
https://sbtc.tech
MIT License
1.98k stars 20 forks source link

Make sure key spend is impossible and predictable #416

Open MarvinJanssen opened 7 months ago

MarvinJanssen commented 7 months ago

(Forgive me if this is already documented elsewhere. I also remember writing it up before during the Mini era but I honestly cannot find it anymore given that we moved repositories, etc., a few times. The topic came up again during the latest Clarity WG call so I thought I would open a fresh issue. If there is another somewhere else, kindly link it and I will close this one.)

For all Taproot addresses used by sBTC, we need to make sure that spends via the key path are impossible. This is a known factor, but what we were discussing was the ability to verify that a specific set of Taproot scripts allow a particular Taproot output to be spent. It appeared during the meeting that so far the only requirement was to provide all Taproot scripts to calculate the script root hash. However, just the script information is not enough to arrive at the final public key, we also need the internal public key. We can either supply it when we supply the other information but then we need to make sure we only allow internal public key(s) that are known to be unspendable. There thus needs to be an allow list or we simply need to hardcode a key and expect all Taproot addresses to use it.

One such key given by BIP341 is 50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0

radicleart commented 7 months ago

Thanks Marvin - i remember this issue and also think its important to communication between UI (creating deposit commitments), revealer api and other parts of sBTC system.

At present the Bridge uses Miller suggestion for the unspendable key - quoting from millers scure btc signer code

// Another stupid decision, where lack of standard affects security.
// Multisig needs to be generated with some key.
// We are using approach from BIP 341/bitcoinjs-lib: SHA256(uncompressedDER(SECP256K1_GENERATOR_POINT))
// It is possible to switch SECP256K1_GENERATOR_POINT with some random point;
// but it's too complex to prove.
// Also used by bitcoin-core and bitcoinjs-lib
export const TAPROOT_UNSPENDABLE_KEY = sha256(ProjPoint.BASE.toRawBytes(false));
radicleart commented 7 months ago

Has value

50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0

so this looks good !

MarvinJanssen commented 6 months ago

@radicleart forgot to follow up on this. Thank you for providing another source. What we need to do is make sure that we all agree on a the same key and make it a standard, that would make everyone's job a lot easier. Tagging @jcnelson @jferrant @setzeus for visibility.