cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
December 18, 2023, 04:15:37 PM Last edit: January 30, 2024, 10:24:51 AM by cmpeq |
|
BitIDE - The Bitcoin TapScript IDE Quick Links>> Open BitIDE Web <<(*NEW*) Setup Local Testnet + Block Explorer + Deploy your first TapScript BTCitcoin Script on SteroidsCustom OpCodes for Code Reuse Meta Programming and JavaScript Macros Symbol/Tag Based Stack Management Integrated Local Block Explorer + Local RegTest Testnet Developer FirstFull trace debugger with human readable symbol tagging Polyfills for disabled op codes Transpile to Bitcoin Mainnet compatible TapScript with the press of a button Install and start a fresh testnet environment with a single command Cross platform: Browser based and local docker versions Install and Start Local Environment(Includes Testnet, BitIDE and Block Explorer) docker run -p 1337:1337 -it --rm qedprotocol/bitide:latest
*NEW* Install and Start Local Environment for Elements/Liquid(Includes Elements 23.3.1 Local Testnet, BitIDE and Block Explorer) docker run -p 1337:1337 -it --rm qedprotocol/bitide-liquid:latest
(Docker pull to update to the latest version)
Watch the Pay to Script Path Tutorial
Watch the Getting Started Tutorial
Release Notes ===== Release 0.7.0 ===== - Added support for elements/liquid + partial support for elements op codes (OP_MUL64, OP_SUB64, OP_ADD64, OP_DIV64, OP_CAT, etc.) ===================
===== Release 0.6.0 ===== - Bug fixes - Fixed file explorer resizing issue ===================
===== Release 0.5.3 ===== - Added local testnet, block explorer and electrs API - Added TapScript deployment tool and test unlocker ===================
More to come, would appreciate any feedback/feature requests! Hope this helps encorage more innovation within the framework of the features Bitcoin has already enabled and spur on debates for future BIPs.
|
founder of QED find me on twitter @cmpeq
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
December 19, 2023, 01:43:07 AM Last edit: December 19, 2023, 02:11:14 AM by cmpeq |
|
Just forgot , For the curious, here are the promised polyfills for OP_XOR, OP_OR and OP_AND: OP_XOR_POLYFILLb.OP_0().tag("result"); b.OP_TOALTSTACK(); var numBits = 31; for (let i = numBits-1; i >= 1; i--) { b.OP_DUP(); b.constant(1 << i); b.OP_LESSTHAN(); b.OP_IF(); b.OP_0().tag("y_bit"); b.OP_ELSE(); b.constant(1 << i); b.OP_SUB().tag("y"); b.OP_1().tag("y_bit"); b.OP_ENDIF();
b.OP_ROT(); b.OP_DUP();
b.constant(1 << i); b.OP_LESSTHAN(); b.OP_IF(); b.OP_0().tag("x_bit"); b.OP_ELSE(); b.constant(1 << i); b.OP_SUB().tag("x"); b.OP_1().tag("x_bit"); b.OP_ENDIF(); b.OP_ROT();
// xor b.OP_NUMEQUAL(); b.OP_NOT(); b.OP_IF(); b.constant(1 << i); b.OP_FROMALTSTACK(); b.OP_ADD(); b.OP_TOALTSTACK(); b.OP_ENDIF(); }
// xor b.OP_NUMEQUAL(); b.OP_NOT(); b.OP_IF(); b.OP_FROMALTSTACK(); b.OP_1(); b.OP_ADD(); b.OP_ELSE(); b.OP_FROMALTSTACK(); b.OP_ENDIF();
OP_OR_POLYFILLvar numBits = 31; b.OP_0().tag("result"); b.OP_TOALTSTACK(); for (let i = numBits - 1; i >= 1; i--) { tb.OP_DUP(); tb.constant(1 << i); tb.OP_LESSTHAN(); tb.OP_IF(); tb.OP_0().tag("y_bit"); tb.OP_ELSE(); tb.constant(1 << i); tb.OP_SUB().tag("y"); tb.OP_1().tag("y_bit"); tb.OP_ENDIF();
tb.OP_ROT(); tb.OP_DUP();
tb.constant(1 << i); tb.OP_LESSTHAN(); tb.OP_IF(); tb.OP_0().tag("x_bit"); tb.OP_ELSE(); tb.constant(1 << i); tb.OP_SUB().tag("x"); tb.OP_1().tag("x_bit"); tb.OP_ENDIF(); tb.OP_ROT();
// or b.OP_BOOLOR(); b.OP_IF(); b.constant(1 << i); b.OP_FROMALTSTACK(); b.OP_ADD(); b.OP_TOALTSTACK(); b.OP_ENDIF(); }
//or b.OP_BOOLOR(); b.OP_IF(); b.OP_FROMALTSTACK(); b.OP_1(); b.OP_ADD(); b.OP_ELSE(); b.OP_FROMALTSTACK(); b.OP_ENDIF();
OP_AND_POLYFILLvar numBits = 31; b.OP_0().tag("result"); b.OP_TOALTSTACK(); for (let i = numBits - 1; i >= 1; i--) { tb.OP_DUP(); tb.constant(1 << i); tb.OP_LESSTHAN(); tb.OP_IF(); tb.OP_0().tag("y_bit"); tb.OP_ELSE(); tb.constant(1 << i); tb.OP_SUB().tag("y"); tb.OP_1().tag("y_bit"); tb.OP_ENDIF();
tb.OP_ROT(); tb.OP_DUP();
tb.constant(1 << i); tb.OP_LESSTHAN(); tb.OP_IF(); tb.OP_0().tag("x_bit"); tb.OP_ELSE(); tb.constant(1 << i); tb.OP_SUB().tag("x"); tb.OP_1().tag("x_bit"); tb.OP_ENDIF(); tb.OP_ROT();
// and b.OP_BOOLAND(); b.OP_IF(); b.constant(1 << i); b.OP_FROMALTSTACK(); b.OP_ADD(); b.OP_TOALTSTACK(); b.OP_ENDIF(); }
// and b.OP_BOOLAND(); b.OP_IF(); b.OP_FROMALTSTACK(); b.OP_1(); b.OP_ADD(); b.OP_ELSE(); b.OP_FROMALTSTACK(); b.OP_ENDIF();
OP_NANDvar numBits = 31; b.OP_0().tag("result"); b.OP_TOALTSTACK(); for (let i = numBits - 1; i >= 1; i--) { tb.OP_DUP(); tb.constant(1 << i); tb.OP_LESSTHAN(); tb.OP_IF(); tb.OP_0().tag("y_bit"); tb.OP_ELSE(); tb.constant(1 << i); tb.OP_SUB().tag("y"); tb.OP_1().tag("y_bit"); tb.OP_ENDIF();
tb.OP_ROT(); tb.OP_DUP();
tb.constant(1 << i); tb.OP_LESSTHAN(); tb.OP_IF(); tb.OP_0().tag("x_bit"); tb.OP_ELSE(); tb.constant(1 << i); tb.OP_SUB().tag("x"); tb.OP_1().tag("x_bit"); tb.OP_ENDIF(); tb.OP_ROT();
// nand b.OP_BOOLAND(); b.OP_NOT(); b.OP_IF(); b.constant(1 << i); b.OP_FROMALTSTACK(); b.OP_ADD(); b.OP_TOALTSTACK(); b.OP_ENDIF(); }
// nand b.OP_BOOLAND(); b.OP_NOT(); b.OP_IF(); b.OP_FROMALTSTACK(); b.OP_1(); b.OP_ADD(); b.OP_ELSE(); b.OP_FROMALTSTACK(); b.OP_ENDIF();
|
founder of QED find me on twitter @cmpeq
|
|
|
NotATether
Legendary
Offline
Activity: 1778
Merit: 7374
Top Crypto Casino
|
It looks good, but there doesn't seem to be a desktop version. If this is using a JS framework, you know, like React or Angular or Vue or like that, you can just slap Electron on it and you'll be good to go on all platforms.
Maybe you can add a feature where a the compiled script can run on testnet if you deposit a small amount of BTC for the transaction fee. You can make the outputs 0.
|
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
December 19, 2023, 12:47:28 PM |
|
It looks good, but there doesn't seem to be a desktop version. If this is using a JS framework, you know, like React or Angular or Vue or like that, you can just slap Electron on it and you'll be good to go on all platforms.
Maybe you can add a feature where a the compiled script can run on testnet if you deposit a small amount of BTC for the transaction fee. You can make the outputs 0.
Great idea! will definitely add an offline electron version in the next release. Also right now we are working on a 1-liner that spins up a clean regtest network in a docker container with funded wallets and automining so you don't have to mess around with faucets, but testnet integration also makes a lot of sense.
|
founder of QED find me on twitter @cmpeq
|
|
|
garlonicon
Copper Member
Legendary
Offline
Activity: 923
Merit: 2214
Pawns are the soul of chess
|
|
December 19, 2023, 08:55:49 PM |
|
You can make the outputs 0. Not only that. You can also hide your scripts behind a TapScript, and then spend by key, if your TapScript will turn out to be unspendable or expensive.
|
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 06, 2024, 10:47:32 AM |
|
Hey all, added docker image for offline development, integration with local testnet (regtest), a block explorer and and a GUI that walks you through how to perform a pay to tapscript (script path) transaction (I saw a lot of people have been asking about this on the forum, so hope this helps). Grab the new version and start a new local testnet with a one liner: docker run -p 1337:1337 -it --rm qedprotocol/bitide:latest
Also shot a quick tutorial video for anyone that wants to get started with TapScript: Edit:If you want to use bitcoin-cli with your testnet, just change the docker command to: docker run -p 1337:1337 -p 18443:18443 -it --rm qedprotocol/bitide:latest
|
founder of QED find me on twitter @cmpeq
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 09, 2024, 07:50:28 AM |
|
You can make the outputs 0. Not only that. You can also hide your scripts behind a TapScript, and then spend by key, if your TapScript will turn out to be unspendable or expensive. Great idea, we will also added support for key paths in the next version! In the meantime, for development purposes it shouldn't be an issue if you are using the docker image with bundled regtest + explorer and use Fund via RPC (regtest btc is free ), as clicking the button first runs generatetoaddress to mine 50 btc to the default wallet, and then transfers 1 BTC to the P2TR address (see screenshot below).
|
founder of QED find me on twitter @cmpeq
|
|
|
warpanomaly
Newbie
Offline
Activity: 19
Merit: 25
|
|
January 15, 2024, 02:45:38 AM |
|
Is BitIDE open source?
|
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 16, 2024, 12:59:25 PM |
|
Is BitIDE open source?
Cleaning up the source and adding some tests, will be open sourced this week =)
|
founder of QED find me on twitter @cmpeq
|
|
|
warpanomaly
Newbie
Offline
Activity: 19
Merit: 25
|
|
January 16, 2024, 07:11:26 PM |
|
Cleaning up the source and adding some tests, will be open sourced this week =) Awesome! Thanks!
|
|
|
|
d3bt3
Jr. Member
Offline
Activity: 51
Merit: 20
|
|
January 17, 2024, 01:29:00 PM |
|
Is BitIDE open source?
Cleaning up the source and adding some tests, will be open sourced this week =) Will appreciate the source. But is the real testnet version of this available?
|
https://altquick.com/exchange/market/BitcoinTestnet
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 17, 2024, 04:06:33 PM |
|
Is BitIDE open source?
Cleaning up the source and adding some tests, will be open sourced this week =) Will appreciate the source. But is the real testnet version of this available? Yep! BitIDE works with regtest, testnet and mainnet. To fund and unlock a script UTXO on the official Bitcoin testnet, just chose "Testnet" in the tapscript executor window and follow the steps below: Note that Fund via RPC only works with regtest (you can't just mint testnet tBTC at will), so for step two you need to either faucet the address with a testnet faucet or send from your testnet wallet before clicking "Check for UTXOs"
|
founder of QED find me on twitter @cmpeq
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
I see this is not mobile friendly 😂 , but this is great to see people are actually developing something useful rather than trying to spam the network for more money.
Just wanted to tell you, fantastic work, amazing and thank you. Hope you could add some ECC related functions to have things in one place. 🤭
Btw, you founded QED? Any web address for it? Oh I saw it on your profile.
No plans for a mobile version (don't code on your phone haha), but more features on the way, namely: 1. Export standalone bitcoinjs-lib code in the TapScript runner (so you can see how to perform all the steps programmatically as well) 2. Support for OP_CHECKSIG/other sig related stuff + basic wallet/key manager 3. Option to pay with keypath rather than script in the TapScript runner (currently we just use a "Nothing Up My Sleeve" point which no one knows the private key of) 4. Support for Liquid
|
founder of QED find me on twitter @cmpeq
|
|
|
vjudeu
Copper Member
Legendary
Offline
Activity: 900
Merit: 2243
|
|
January 19, 2024, 05:32:07 AM |
|
currently we just use a "Nothing Up My Sleeve" point which no one knows the private key of You should not use that, unless it is strictly necessary. It is better to pick a public key, that is just N-of-N multisig of everyone involved. In this way, there is always a chance to spend by key (and make it cheaper) if everyone agrees. In general, Taproot addresses should be "always spendable by key, and sometimes spendable by key, and by TapScript".
|
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 21, 2024, 01:41:03 PM |
|
currently we just use a "Nothing Up My Sleeve" point which no one knows the private key of You should not use that, unless it is strictly necessary. It is better to pick a public key, that is just N-of-N multisig of everyone involved. In this way, there is always a chance to spend by key (and make it cheaper) if everyone agrees. In general, Taproot addresses should be "always spendable by key, and sometimes spendable by key, and by TapScript". For situations where a multisig is appropriate
|
founder of QED find me on twitter @cmpeq
|
|
|
ercewubam
Newbie
Offline
Activity: 26
Merit: 62
|
|
January 21, 2024, 03:23:15 PM |
|
For situations where a multisig is appropriate Could you give any example, where it is not?
|
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 21, 2024, 10:37:29 PM |
|
For situations where a multisig is appropriate Could you give any example, where it is not? 1. Password Recovery Let's say I want to crack a sha256 password hash (your own personal password and not someone else's, of course). If know the hash is 5bf01f36fa15d5ccf2dea7a53c777426d559a9a8d1384e58bc8d3dc423cd2f12, I could offer a reward in bitcoin for anyone who can provide the preimage to the password with the following script: OP_SHA256 <5bf01f36fa15d5ccf2dea7a53c777426d559a9a8d1384e58bc8d3dc423cd2f12> OP_EQUAL
You can try it out if you like on testnet (the password is supersecretpassword) 2. Recursive Covenants + Trustless peg-in/peg-out for layer 2s Imagine we have a layer 2 which posts a withdrawals tree of the chain to bitcoin, and we want to allow users to trustlessly withdraw their bitcoins from layer 2. When block producers submit a block they spend and existing block script which has two outputs: 1. an output to a withdrawal UTXO script which can be spent by the users who withdrew funds from layer 2 back to layer 1 in the most recent block (includes a withdrawal tree merkle root) 2. a new block UTXO for the next block (recurse) The withdrawal script can only be spent by spending a recursive covenant which includes a delta merkle proof proving the validity of the spend of one of the withdrawals and an additional recursive covenant that creates a new withdrawal script with the updated withdrawal tree root (the withdrawal made is set to the null value so you can't spend a withdrawal more than once). The locked BTC in the layer 2 block UTXO can only be sent to a script which publishes a new block (1 output) or a withdrawal script which allows users to withdraw a portion of the BTC and sends the rest to a new script with the updated merkle root (2 outputs). In our withdrawal script, we verify a merkle proof which links the previously submitted state root/withdrawals tree root with a spender: <0x8fe1e5f7bc9333914565f011a63942d988c88b00547b35af859635b00cbbc64c> // old root, must be this value as enforced by the block UTXO covenant <0x7163998f26fec2e57db7413d706d30e7b9f14e13b416217160221ff05690fb65> // new root after spending the withdrawal and removing it from the withdrawals tree
// merkle proof siblings <0x2f0935c2963ead8b3be0ee5d4d4dcb3af23646c6bbfc330e41e90a47ee8cf7f7> // sibling at level 14 <0xeac71276dd976b550cace2fb1097ad5d296193fea0359202ca4899b398ab2436> // sibling at level 13 <0x2c7011733c31c9c58e0d5cbe40be77c714a4b77b281ffd72155276af21452e24> // sibling at level 12 <0x5cc411ccc9b0ce4704798316824afffbbeb724d7fb06701bf7c57f1fa122102f> // sibling at level 11 <0x485a020e9ce6f948b88528bc38ac34838283bd4a001db1f99b84cbe87ebe3e99> // sibling at level 10 <0x885fb789bdd39eee523ade57bedba8fa308b9014c910d6db04b779732139c5b7> // sibling at level 9 <0x8b4578b4daaa30f78eaa2f5537142c9fe277a87fc4e8c5dd872ab95524d34c48> // sibling at level 8 <0xdcd5818eaddf2de1a4fd8792664403a1b1e24779baf3bfac02f169ae63b46d95> // sibling at level 7 <0x7900bfb52e43f1c0b93a87e4b42bc652a1de0c6e72becc37a4f1d26a3eac42a6> // sibling at level 6 <0x2013541c218b99def8301bb9b283f3696605e39a267e757e61692e47623bebdb> // sibling at level 5 <0x9e5a86f32a7231309e3f4bc44473a181b3482352acc8e332d10b493a8acca77c> // sibling at level 4 <0xca67e1b7055afe377bd9fb285335a3685472b1c08f94cf133481320b0fe63653> // sibling at level 3 <0xf464a8d91ca7029a4b88483b7d778403c310c2eaabf46a905874343f975b49a0> // sibling at level 2 <0xaa6ef54b7988700bbcffcaf327be3ade37a68573e9fd6a498a00600059644a28> //sibling at leaf level
<999> // index of the withdrawal leaf we are spending with in the withdrawals tree
// recursive covenant inputs... <0x3905000000000000> // 8 byte spend amount (1337) <0xb4a2ef4141dfdedc3b548222b11fcf90bf81782ed6bf998b6552ab08978b2ce6> // spender OP_2DUP OP_CAT OP_SHA256 // compute the withdrawal hash -> 0xeac7f4e4689862aa7baf72c1673a48a66561ab222eb6a6d8af38c32393265d90 OP_TOALTSTACK // move the withdrawal hash to the alt stack for later // the rest of the recursive covenant code
// now only the merkle roots + siblings + index remains in the stack OP_FROMALTSTACK // old leaf value computed earlier (withdrawal hash) <0x0000000000000000000000000000000000000000000000000000000000000000>// new value OP_ROT // move the index to the top of the stack
// start decompose the index into bits // we decompose the number into bits which are stored on the alt stack <8192> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <4096> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <2048> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <1024> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <512> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <256> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <128> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <64> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF <32> OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF OP_16 OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF OP_8 OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF OP_4 OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF OP_2 OP_2DUP OP_GREATERTHANOREQUAL OP_DUP OP_TOALTSTACK OP_DUP OP_TOALTSTACK OP_IF OP_SUB OP_ELSE OP_DROP OP_ENDIF OP_DUP OP_TOALTSTACK OP_TOALTSTACK
// end decompose the index into bits
// now the lowest bit of the index is on the alt stack
// compute old and new merkle roots OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
OP_ROT OP_ROT OP_OVER OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute old merkle path at level OP_ROT OP_ROT OP_FROMALTSTACK OP_ROLL OP_CAT OP_SHA256 // compute new merkle path at level
// end compute old and new merkle roots
Now we just check the old and new roots from the inputs to make sure the match the computed ones (ie. proof that the withdrawal exists in the tree, and that the merkle tree with merkle root new root has all the same leaves as old tree, except for the leaf at the specified index that has just been spent (and has been nulled out): /*
now the stack is as follows:
<old merkle root> // guarenteed correct via the covenant <new merkle root> // attested by the spender
<computed old merkle root> // computed from the index/siblings/withdrawal hash value <computed new merkle root> // computed from the index/siblings/nulled out value
*/
OP_ROT OP_EQUALVERIFY // check that the attested new merkle root is a copy of the old tree with the spent leaf nulled out
|
founder of QED find me on twitter @cmpeq
|
|
|
vjudeu
Copper Member
Legendary
Offline
Activity: 900
Merit: 2243
|
|
January 22, 2024, 05:48:43 AM |
|
Password Recovery When it comes to any puzzles, there is for example this puzzle: https://bitcointalk.org/index.php?topic=5469657.0And then, people may think, that SHA-1 was used, to create them, and make TapScripts, unspendable by key: 1) OP_SHA1 <3045ae6fc8422f64ed579528d38120eae12196d5> OP_EQUAL 2) OP_SHA1 <bd71344799d5c7fcdc45b59fa3b9ab8f6a948bc5> OP_EQUAL 3) OP_SHA1 <c49d360886e704936a6678e1139d26b7819f7e90> OP_EQUAL 4) OP_SHA1 <a335926aa319a27a1d00896a6773a4827acdac73> OP_EQUAL 5) OP_SHA1 <d09e8800291cb85396cc6717393284aaa0da64ba> OP_EQUAL Imagine, how the person solving that would feel, if it would turn out, that those coins are unspendable, because of the wrong endianness. So, instead of using unspendable key-path, it can be just "multisig behind all interested parties". It is possible to start with a single key, just like the creator of the famous puzzle, where keys #120 and #125 are sweeped, but nobody knows, if those keys are really broken, or if the author just moved those funds. And if you have any kind of reward, then by using multisig, you can start with a single key, and then move those coins by key, to combine the same rewards into bigger coins. Which means, if Alice and Bob sent funds to some different keys, with the same attached TapScript, then they could move them to a multisig, and a TapScript. And that move may be more attractive to the puzzle solver, because having single coin is cheaper to move, than having thousands of small deposits (not to mention address reuse, which is a bad practice, and should be avoided). Recursive Covenants + Trustless peg-in/peg-out for layer 2s If you have more than one person, behind some coin, then it may be possible, that all of them will be online. In that case, there is no reason to use expensive TapScript path, and reveal the whole covenant on-chain. The group, which wants to be detached, can just propose a withdrawal transaction, and collect all signatures from all parties, and then it will look the same, as if everything would be owned by a single user. To sum up: I cannot see a reason, why not to use multisig. If you are alone, then it gives you a chance to experiment with TapScript, without trapping your coins in unspendable paths. If there are at least two people (for example: Alice tells Bob that she will pay for Password Recovery), then, 2-of-2 multisig is applicable. If there are more than two people, then N-of-N multisig is applicable in a general case. And then, for example if Bob cannot provide the password, Alice can say: "well, you tried cracking it for 10 years, and you failed, it is now useless information for me, so I sweep my funds, you don't have to work longer on that". And if Bob agrees, then it is at least possible for Alice to get her funds back. But if it is behind TapScript-only, then it may be unspendable forever. Also, there are obvious mistakes possible, for example wrong endianness, and then, key-path can be used to fix those cases, instead of losing coins forever.
|
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 22, 2024, 05:10:02 PM |
|
Password Recovery When it comes to any puzzles, there is for example this puzzle: https://bitcointalk.org/index.php?topic=5469657.0And then, people may think, that SHA-1 was used, to create them, and make TapScripts, unspendable by key: 1) OP_SHA1 <3045ae6fc8422f64ed579528d38120eae12196d5> OP_EQUAL 2) OP_SHA1 <bd71344799d5c7fcdc45b59fa3b9ab8f6a948bc5> OP_EQUAL 3) OP_SHA1 <c49d360886e704936a6678e1139d26b7819f7e90> OP_EQUAL 4) OP_SHA1 <a335926aa319a27a1d00896a6773a4827acdac73> OP_EQUAL 5) OP_SHA1 <d09e8800291cb85396cc6717393284aaa0da64ba> OP_EQUAL Imagine, how the person solving that would feel, if it would turn out, that those coins are unspendable, because of the wrong endianness. So, instead of using unspendable key-path, it can be just "multisig behind all interested parties". It is possible to start with a single key, just like the creator of the famous puzzle, where keys #120 and #125 are sweeped, but nobody knows, if those keys are really broken, or if the author just moved those funds. And if you have any kind of reward, then by using multisig, you can start with a single key, and then move those coins by key, to combine the same rewards into bigger coins. Which means, if Alice and Bob sent funds to some different keys, with the same attached TapScript, then they could move them to a multisig, and a TapScript. And that move may be more attractive to the puzzle solver, because having single coin is cheaper to move, than having thousands of small deposits (not to mention address reuse, which is a bad practice, and should be avoided). Recursive Covenants + Trustless peg-in/peg-out for layer 2s If you have more than one person, behind some coin, then it may be possible, that all of them will be online. In that case, there is no reason to use expensive TapScript path, and reveal the whole covenant on-chain. The group, which wants to be detached, can just propose a withdrawal transaction, and collect all signatures from all parties, and then it will look the same, as if everything would be owned by a single user. To sum up: I cannot see a reason, why not to use multisig. If you are alone, then it gives you a chance to experiment with TapScript, without trapping your coins in unspendable paths. If there are at least two people (for example: Alice tells Bob that she will pay for Password Recovery), then, 2-of-2 multisig is applicable. If there are more than two people, then N-of-N multisig is applicable in a general case. And then, for example if Bob cannot provide the password, Alice can say: "well, you tried cracking it for 10 years, and you failed, it is now useless information for me, so I sweep my funds, you don't have to work longer on that". And if Bob agrees, then it is at least possible for Alice to get her funds back. But if it is behind TapScript-only, then it may be unspendable forever. Also, there are obvious mistakes possible, for example wrong endianness, and then, key-path can be used to fix those cases, instead of losing coins forever. So, instead of using unspendable key-path, it can be just "multisig behind all interested parties".
Totally agree! I think the rule of thumb is: use a multisig if you know the interested parties ahead of time, otherwise use NUMS. For the example of the puzzle/hash cracking, one may have to spend a significant portion of time/compute to crack the hash, so if they original challenge holder can just transfer away the funds at will, it may be a disincentive to commit resources to the problem. In the case of the layer 2, I would push back, however. To be secure, the multisig should be controlled by the owners of layer 2 wrapped BTC so they can reclaim the BTC on Layer 1 back whenever they like. This is impossible if the layer 2 BTC is transferrable. Consider the following scenario: 3 bitcoin holders each bridge 10 BTC to layer 2, locking a total of 30 BTC in a multisig (lets call the set of keys in the multisig K), minting a total 30 l2BTC on the layer 2. Since the K should proportionally represent owners of l2BTC, they should each control a key in the multisig. The 3 original users then purchase NFTs on the L2 with their l2BTC on an L2-DEX, spending all 30 BTC. Now the original set K does not represent the token holders and is instead controlled by a group which owns no l2BTC.
|
founder of QED find me on twitter @cmpeq
|
|
|
cmpeq (OP)
Copper Member
Jr. Member
Offline
Activity: 33
Merit: 169
|
|
January 30, 2024, 10:39:09 AM |
|
Just released BitIDE 0.7.0 which includes bug fixes and support for Liquid BTC + a new docker image which includes a local Elements 23.2.1 regtest testnet. To upgrade to the latest version of BitIDE, run: docker pull qedprotocol/bitide:latest docker run -p 1337:1337 -it --rm qedprotocol/bitide:latest
To start a Liquid/Elements regtest + install the Liquid compatible version of BitIDE, run: docker pull qedprotocol/bitide-liquid:latest docker run -p 1337:1337 -it --rm qedprotocol/bitide-liquid:latest
You can also change the vm mode in the web version of BitIDE by selecting "Liquid" in the new IDE Settings tab: Currently supported Elements/Liquid only op codes: - OP_ADD64
- OP_SUB64
- OP_DIV64
- OP_MUL64
- OP_LESSTHAN64
- OP_GREATERTHAN64
- OP_LESSTHANOREQUAL64
- OP_GREATERTHANOREQUAL64
- OP_NEG64
- OP_SCRIPTNUMTOLE64
- OP_LE64TOSCRIPTNUM
- OP_LE32TOLE64
- OP_OR
- OP_XOR
- OP_AND
- OP_CAT
More will be added soon!
|
founder of QED find me on twitter @cmpeq
|
|
|
|