Bitcoin Script Debugger
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
build-aux
compat
compiler
config
crypto
debugger
kerl
policy
primitives
script
secp256k1
support
test
.gitignore
.travis.yml
LICENSE
Makefile.am
README.md
amount.h
arith_uint256.cpp
arith_uint256.h
autogen.sh
base58.cpp
base58.h
bech32.cpp
bech32.h
btcc.cpp
btcdeb.cpp
cliargs.h
compat.h
configure.ac
ecide.cpp
hash.cpp
hash.h
instance.cpp
instance.h
mastify.cpp
merkle.cpp
merkle.h
merklebranch.cpp
prevector.h
pubkey.cpp
pubkey.h
serialize.h
span.h
streams.h
tinyformat.h
uint256.cpp
uint256.h
utilstrencodings.cpp
utilstrencodings.h
value.cpp
value.h

README.md

btcdeb

Bitcoin Script debugging utilities.

This is a set of tools used to debug or construct scripts for use in Bitcoin.

Build Status

Preparation

Mac users need the macOS command line tools:

xcode-select --install

And Homebrew.

Dependencies

btcdeb depends on the following:

  • libtool
  • libssl
  • autoconf

Ubuntu/debian users can do: apt-get install libtool libssl-dev autoconf (with sudo prepended if necessary)

Mac users can do: brew install libtool

Installation

On linux or mac, grab the source code and do:

$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

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.

Emscripten

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 \ns).

Script debugger

The btcdeb command can step through a Bitcoin Script and show stack content and operations on a per op level.

btcdeb> help
step     Execute one instruction and iterate in the script.
rewind   Go back in time one instruction.
stack    Print stack content.
altstack Print altstack content.
vfexec   Print vfexec content.
exec     Execute command.
tf       Transform a value using a given function.
print    Print script.
help     Show help information.

(note this example 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>

Signature checking

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>

Script compiler

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.

MAST stuff

btcdeb also has some stuff related to MAST (merkelized abstract syntax trees), based on the implementation by Mark Friedenbach, in the mbv-taileval branch.

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)