Bitcoin Forum
November 13, 2024, 06:26:55 PM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 »  All
  Print  
Author Topic: BitIDE - TapScript IDE with Local Testnet, Explorer and Custom Op Codes (P2TR)  (Read 498 times)
cmpeq (OP)
Copper Member
Jr. Member
*
Offline Offline

Activity: 33
Merit: 169


View Profile WWW
December 18, 2023, 04:15:37 PM
Last edit: January 30, 2024, 10:24:51 AM by cmpeq
Merited by ABCbits (22), BlackHatCoiner (20), n0nce (8), NotATether (5), dkbit98 (3), BTCW (3), internetional (2), DdmrDdmr (1), digaran (1), baro77 (1)
 #1




BitIDE - The Bitcoin TapScript IDE


Quick Links
>> Open BitIDE Web <<
(*NEW*) Setup Local Testnet + Block Explorer + Deploy your first TapScript

BTCitcoin Script on Steroids
Custom OpCodes for Code Reuse
Meta Programming and JavaScript Macros
Symbol/Tag Based Stack Management
Integrated Local Block Explorer + Local RegTest Testnet

Developer First
Full 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)
Code:
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)
Code:
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
Code:

===== 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 Offline

Activity: 33
Merit: 169


View Profile WWW
December 19, 2023, 01:43:07 AM
Last edit: December 19, 2023, 02:11:14 AM by cmpeq
 #2

Just forgot  Tongue, For the curious, here are the promised polyfills for OP_XOR, OP_OR and OP_AND:

OP_XOR_POLYFILL
Code:
b.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_POLYFILL
Code:
var 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_POLYFILL
Code:
var 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_NAND
Code:
var 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 Offline

Activity: 1778
Merit: 7374


Top Crypto Casino


View Profile WWW
December 19, 2023, 06:02:50 AM
Merited by garlonicon (1), cmpeq (1)
 #3

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.

███████████████████████
████▐██▄█████████████████
████▐██████▄▄▄███████████
████▐████▄█████▄▄████████
████▐█████▀▀▀▀▀███▄██████
████▐███▀████████████████
████▐█████████▄█████▌████
████▐██▌█████▀██████▌████
████▐██████████▀████▌████
█████▀███▄█████▄███▀█████
███████▀█████████▀███████
██████████▀███▀██████████

███████████████████████
.
BC.GAME
▄▄▀▀▀▀▀▀▀▄▄
▄▀▀░▄██▀░▀██▄░▀▀▄
▄▀░▐▀▄░▀░░▀░░▀░▄▀▌░▀▄
▄▀▄█▐░▀▄▀▀▀▀▀▄▀░▌█▄▀▄
▄▀░▀░░█░▄███████▄░█░░▀░▀▄
█░█░▀░█████████████░▀░█░█
█░██░▀█▀▀█▄▄█▀▀█▀░██░█
█░█▀██░█▀▀██▀▀█░██▀█░█
▀▄▀██░░░▀▀▄▌▐▄▀▀░░░██▀▄▀
▀▄▀██░░▄░▀▄█▄▀░▄░░██▀▄▀
▀▄░▀█░▄▄▄░▀░▄▄▄░█▀░▄▀
▀▄▄▀▀███▄███▀▀▄▄▀
██████▄▄▄▄▄▄▄██████
.
..CASINO....SPORTS....RACING..


▄▄████▄▄
▄███▀▀███▄
██████████
▀███▄░▄██▀
▄▄████▄▄░▀█▀▄██▀▄▄████▄▄
▄███▀▀▀████▄▄██▀▄███▀▀███▄
███████▄▄▀▀████▄▄▀▀███████
▀███▄▄███▀░░░▀▀████▄▄▄███▀
▀▀████▀▀████████▀▀████▀▀
cmpeq (OP)
Copper Member
Jr. Member
*
Offline Offline

Activity: 33
Merit: 169


View Profile WWW
December 19, 2023, 12:47:28 PM
 #4

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 Offline

Activity: 923
Merit: 2214


Pawns are the soul of chess


View Profile
December 19, 2023, 08:55:49 PM
 #5

Quote
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 Offline

Activity: 33
Merit: 169


View Profile WWW
January 06, 2024, 10:47:32 AM
 #6

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:
Code:
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:
Code:
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 Offline

Activity: 33
Merit: 169


View Profile WWW
January 09, 2024, 07:50:28 AM
 #7

Quote
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 Wink), 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 Offline

Activity: 19
Merit: 25


View Profile
January 15, 2024, 02:45:38 AM
 #8

Is BitIDE open source?
cmpeq (OP)
Copper Member
Jr. Member
*
Offline Offline

Activity: 33
Merit: 169


View Profile WWW
January 16, 2024, 12:59:25 PM
 #9

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 Offline

Activity: 19
Merit: 25


View Profile
January 16, 2024, 07:11:26 PM
 #10

Quote
Cleaning up the source and adding some tests, will be open sourced this week =)

Awesome! Thanks!
d3bt3
Jr. Member
*
Offline Offline

Activity: 51
Merit: 20


View Profile WWW
January 17, 2024, 01:29:00 PM
 #11

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 Offline

Activity: 33
Merit: 169


View Profile WWW
January 17, 2024, 04:06:33 PM
 #12

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 Offline

Activity: 33
Merit: 169


View Profile WWW
January 19, 2024, 01:51:33 AM
Merited by ABCbits (1), vjudeu (1)
 #13

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 Offline

Activity: 900
Merit: 2243



View Profile
January 19, 2024, 05:32:07 AM
 #14

Quote
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".

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
cmpeq (OP)
Copper Member
Jr. Member
*
Offline Offline

Activity: 33
Merit: 169


View Profile WWW
January 21, 2024, 01:41:03 PM
 #15

Quote
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 Wink

founder of QED
find me on twitter @cmpeq
ercewubam
Newbie
*
Offline Offline

Activity: 26
Merit: 62


View Profile
January 21, 2024, 03:23:15 PM
 #16

Quote
For situations where a multisig is appropriate
Could you give any example, where it is not?
cmpeq (OP)
Copper Member
Jr. Member
*
Offline Offline

Activity: 33
Merit: 169


View Profile WWW
January 21, 2024, 10:37:29 PM
Merited by vjudeu (1)
 #17

Quote
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:
Code:
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:
Code:
<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):
Code:
/*

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 Offline

Activity: 900
Merit: 2243



View Profile
January 22, 2024, 05:48:43 AM
 #18

Quote
Password Recovery
When it comes to any puzzles, there is for example this puzzle: https://bitcointalk.org/index.php?topic=5469657.0

And then, people may think, that SHA-1 was used, to create them, and make TapScripts, unspendable by key:
Code:
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).

Quote
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.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
cmpeq (OP)
Copper Member
Jr. Member
*
Offline Offline

Activity: 33
Merit: 169


View Profile WWW
January 22, 2024, 05:10:02 PM
 #19

Quote
Password Recovery
When it comes to any puzzles, there is for example this puzzle: https://bitcointalk.org/index.php?topic=5469657.0

And then, people may think, that SHA-1 was used, to create them, and make TapScripts, unspendable by key:
Code:
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).

Quote
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 Offline

Activity: 33
Merit: 169


View Profile WWW
January 30, 2024, 10:39:09 AM
 #20

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:
Code:
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:
Code:
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
Pages: [1] 2 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!