Bitcoin Script debugging utilities.
This is a set of tools used to debug or construct scripts for use in Bitcoin.
btcdeb depends on the following libraries:
- libssl
Ubuntu/debian users can do apt-get install libssl-dev
(with sudo
prepended if necessary).
Mac users most likely have libssl already (let me know if not).
On linux or mac, grab the source code and do:
$ ./autogen.sh
$ ./configure
$ make
If any of those give an error, please file an issue and I'll take a look. It could be a dependency that I forgot about.
You can compile btcdeb tools into JavaScript using emscripten.
After installing the SDK, compile btcdeb tools with the following commands:
$ make clean
$ emconfigure ./configure
$ emmake make
$ for i in btcdeb btcc mastify merklebranch; do mv $i $i.bc && emcc -O2 $i.bc libbitcoin.a -o $i.js; done
and then instead of doing ./btcdeb
you do node btcdeb.js
(or mastify.js
, etc).
The last part is done because emscripten's emcc
expects the input bytecode file to have the .bc
extension, whereas the makefile generates files with no extension.
Note: most things work, but the console in btcdeb does not. You can work around this by doing echo -n -e "step\n\n\n"
(with sufficient \n
s).
The btcdeb
command can step through a Bitcoin Script and show stack content and operations on a per op level (note that the example below will fail on the OP_CHECKSIG part; see "Signature checking" below).
$ btcdeb '[OP_DUP OP_HASH160 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 OP_EQUALVERIFY OP_CHECKSIG]' 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a2aa5e8f21810220131fad73787989d7fbbdbbd8420674f56bdf61fed5dc2653c826a4789c68501101 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
valid script
5 op script loaded. type `help` for usage information
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
OP_DUP | 03b05bdbdf395e495a61add92442071e32703518b8fca3fc34149db4b56c93be42
OP_HASH160 | 3045022100c7d8e302908fdc601b125c2734de63ed3bf54353e13a835313c2a...
897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 |
OP_EQUALVERIFY |
OP_CHECKSIG |
#0001 OP_DUP
btcdeb>
In order to run an OP_CHECKSIG command, the debugger needs to know about the transaction being checked, since it creates the signature hash from the transaction content. You can pass the transaction to btcdeb
when you run it, using the --tx=[amount1[,amount2[,...]]]:[hexdata]
, where [amountN]
is the amount of the inputs of the transaction, and [hexdata]
is the hexadecimal representation of the entire transaction (not just the transaction ID).
Alternatively, you can pass both the transaction (using --tx=
) and the input transaction (using --txin=
). In this case, if you do not provide any other parameters (script/stack data), btcdeb
will automatically figure out the script and stack content for verifying the input specified by the txin
hex. You also do not need to include the amounts when passing the txin
explicitly.
$ btcdeb --tx=010000000001019086ce64fce1bb086395faf6fac37c73f32ba4ea89330432bf8ee8035e9315aa0100000000ffffffff021353b9030000000017a914c3f413d0918853a8e23766678d2e3c2e5c8138bb8725e4973100000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d040047304402207f874ef00f11dcc9a621acad9354f3fca1bf90c43878f607b7e2d358088487e7022052a01b47b8eef5e1c96a6affdc3dac46fdc11b60612464dc8c5921a852090d2701483045022100c56ab2abb17fdf565417228763bc9f2940a6465042fd62fbd9f4c7406345d7f702201cb1a56b45181f8347713627b325ec5df48fc1aee6bdaf937cbb804d7409b10c016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000 \
--txin=0100000000010170a6ee35199eae2d8ea659561374fa704f8fd95188ff5931157e4598dd0c44020100000000ffffffff0280f0fa02000000001976a914eec426a744f7a3b2ffd346925ac832e248834dd788ac4013543500000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220054c0b331a31496d9123aeabe8415b8d2f877f1cf67709120af4eb1e09de59e002206cdf84e733e23be531aff202f868d200773e22aa0037033a74fc6752df2fd19601483045022100b54fa12828d13b58cb654dd910b9e8b36d471d644d8f66516577990ca099ee19022048ea2ac78f964d1b823af70c13c5607a29b14bb2348022190b3c280f51ec5df2016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000
btcdeb -- type `./btcdeb -h` for start up options
got segwit transaction:
CTransaction(hash=bf19bb6924, ver=1, vin.size=1, vout.size=2, nLockTime=0)
CTxIn(COutPoint(aa15935e03, 1), scriptSig=)
CScriptWitness(, 304402207f874ef00f11dcc9a621acad9354f3fca1bf90c43878f607b7e2d358088487e7022052a01b47b8eef5e1c96a6affdc3dac46fdc11b60612464dc8c5921a852090d2701, 3045022100c56ab2abb17fdf565417228763bc9f2940a6465042fd62fbd9f4c7406345d7f702201cb1a56b45181f8347713627b325ec5df48fc1aee6bdaf937cbb804d7409b10c01, 52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae)
CTxOut(nValue=0.62477075, scriptPubKey=a914c3f413d0918853a8e23766678d)
CTxOut(nValue=8.32037925, scriptPubKey=0020701a8d401c84fb13e6baf169d5)
got input tx #0:
CTransaction(hash=aa15935e03, ver=1, vin.size=1, vout.size=2, nLockTime=0)
CTxIn(COutPoint(02440cdd98, 1), scriptSig=)
CScriptWitness(, 30440220054c0b331a31496d9123aeabe8415b8d2f877f1cf67709120af4eb1e09de59e002206cdf84e733e23be531aff202f868d200773e22aa0037033a74fc6752df2fd19601, 3045022100b54fa12828d13b58cb654dd910b9e8b36d471d644d8f66516577990ca099ee19022048ea2ac78f964d1b823af70c13c5607a29b14bb2348022190b3c280f51ec5df201, 52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae)
CTxOut(nValue=0.50000000, scriptPubKey=76a914eec426a744f7a3b2ffd34692)
CTxOut(nValue=8.94702400, scriptPubKey=0020701a8d401c84fb13e6baf169d5)
input tx index = 0; tx input vout = 1; value = 894702400
valid script
6 op script loaded. type `help` for usage information
script | stack
-------------------------------------------------------------------+-------------------------------------------------------------------
2 | 3045022100c56ab2abb17fdf565417228763bc9f2940a6465042fd62fbd9f4c...
0375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c | 304402207f874ef00f11dcc9a621acad9354f3fca1bf90c43878f607b7e2d35...
03a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff | 0x
03c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f880 |
3 |
OP_CHECKMULTISIG |
#0001 2
btcdeb>
The btcc
command can interpret a script in its human readable form and will
return a corresponding Bitcoin Script.
$ btcc OP_DUP OP_HASH160 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 OP_EQUALVERIFY OP_CHECKSIG
76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac
The above is the script pub key for a transaction in Bitcoin in human readable format turned into its hexadecimal representation.
btcdeb
also has some stuff related to MAST (merkelized abstract syntax trees), based on the implementation by Mark Friedenbach.
There are two commands, merklebranch
and mastify
.
The former is more low-level than the latter; merklebranch
lets you give parameters for a MAST merkle tree, and it will produce the root/path/proof/etc
for that tree.
mastify
lets you convert a regular Bitcoin Script into a MAST version. It works in two modes; general mode, where it simply gives you the needed stuff to fund, and execution mode, where it gives you the needed parameters to spend a previously funded MAST-ified output.
The mode is determined by whether you passed any parameters into mastify
or not. No parameters means general mode, and one or more means execution mode.
Example:
./mastify "[
OP_IF
144
OP_CHECKSEQUENCEVERIFY
OP_DROP
020c23a5f833b3cb2a29bf81e246886e0ea098989b359c401655c96d3f1a37567a
OP_ELSE
0375ceeb0d9d99ff238f85aa5d18e318c7f0a84d3b7bec31a99df66df0bf887ee4
OP_ENDIF
OP_CHECKSIG
]"
will give you the fund information (0 parameters), and
./mastify "[
OP_IF
144
OP_CHECKSEQUENCEVERIFY
OP_DROP
020c23a5f833b3cb2a29bf81e246886e0ea098989b359c401655c96d3f1a37567a
OP_ELSE
0375ceeb0d9d99ff238f85aa5d18e318c7f0a84d3b7bec31a99df66df0bf887ee4
OP_ENDIF
OP_CHECKSIG
]" 0x 0x
will give you the spending information for the case where OP_IF returns false
(change the second 0x to 01 instead, to see the else
case).
Both merklebranch
and mastify
let you pipe the output directly into a btcdeb session; to do so, simply pass --btcdeb
to the call to merklebranch
or mastify
, and pipe that to btcdeb:
./btcdeb $(./mastify --btcdeb "[
OP_IF
144
OP_CHECKSEQUENCEVERIFY
OP_DROP
020c23a5f833b3cb2a29bf81e246886e0ea098989b359c401655c96d3f1a37567a
OP_ELSE
0375ceeb0d9d99ff238f85aa5d18e318c7f0a84d3b7bec31a99df66df0bf887ee4
OP_ENDIF
OP_CHECKSIG
]" 0x 01)