Nexa Script Debugger

This webapp allows you to test and debug smart contracts written for the Nexa blockchain. Please use on landscape aspect ratio devices.

This is unfinished software, so it WILL have issues! Please report issues here!

Basic Layout

The scripts that are to be run are shown in tabs near this help. The Nexa Script Machine state is shown on the right. This consists of a banner showing machine registers and status, and two large windows showing the main and alt stacks.

The main and alt stacks grow downwards. The first element on the stack is at the BOTTOM of the screen. Why? Because the stack is represented in the same direction as scripts push, so a script "1 2 3" results in a stack shown as "1 2 3", not "3 2 1". Trust me, if you do a lot of script debugging you'll thank me for this!

Each stack line comprises the index from the top, the data type, the length, the hex representation of the item, and the "natural" representation. This last representation depends on the type of the item.

In the top bar you see a few buttons. The "<<<" button reinitializes Script Machine state. The "<<" button rewinds to the beginning of the template script. The ">>" button continues execution of the current script, while the ">" button steps.

Simple Script

Cut and paste a script into the "template" tab. A clean script machine will be initialized. Try the following script. Note that the first number is a 256-bit little-endian sign magnitude number specified as a byte array. So if you read it backwards and note that the last byte 00 is the sign you may recognise it.

0x2ffcfffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff00 SETBMD
1 BIN2BIGNUM
DUP 16 LSHIFT ADD
DUP 16 LSHIFT ADD
DUP MUL DUP MUL DUP MUL DUP MUL DUP MUL DUP MUL DUP MUL DUP MUL

This script demonstrates large integer (bignum) capabilities and how all bignum operations are modulo the Bignum Modulo Divisor (BMD). Run this python equivalent and match the printouts with the top of the stack (occasionally -- every step does not match) as the script executes:

BMD = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
tmp = 1 + (1<<16)
print(tmp)
tmp = tmp + (tmp<<16)
print(tmp)
for i in range(0,8):
   tmp = (tmp*tmp)%BMD
   print(tmp)

Nexa Machine State Setup

Interesting scripts can access information within the current transaction and in the outpoints being spent. To set up some state data get the hex dump of two transactions, one of which spends an output of the other. The two transactions should be separated by whitespace. Cut and paste both of these transactions into this window.

Here is an example for you to try:

000600bdc7b2943e225ec0347b9298c69a0934ab3c0cdf0d0daa8d7eedb7fcafac702564222102f1d201c14136c0e2ce731417e69fcf2839f218927bc2825e41a8ed6ad1802e2f4010ad22c6e26eb9c9bdff0c1fcd29b10e3e096d218d5b926560b1cd8d7de0b1bddbbf02bfa46a340a4917a79fcd5d89b5a960780a344264e0210dba66d90fdcfcfeffffffd03f440100000000007ccc8d93ace3d4b095dd447bc8ef57d8ea73b452cb8c83648a27c3e7b3ff5180642221024c536315861395d785e2a939be8d0a56f8c073f6fe381805d3562fcd5f45d14c40c6ff37c5a580c06e4a891abe41ff3c0cef9707c6986c1fd197005ec6508b61a193a81613e8044cf267b6985cb027eda2725980546ace6426289152c0838939dafefffffff1da9a3b0000000000b777053590d2ad796f4e23974ccd908edd24285abfd4971da1d560f5583a87b5642221035e959fac60e788e837b3e63ff8755dd814643954f3e14367403d8c1c80741474404be55d60cd6b25a149958c7f35ae504b8a8aac762b90fe1863b3d59eb6e70f2343cfc481142e138c121cdd618773c0f50e33171e0212aeebc1310ddbcb749308feffffff4c9c0d000000000000b360b07cc0e38bf8dbe892e6ad0b69e978c9b59d68b4a6acdc50a51c10a9f7fe642221028289ec94736df58d1ba51d53d52928bd6c02b502862f394e5e149024a947071e40ae8cea6673c8f4775edc7ffc5a083897ea45897326e4e9e13799a288f51aa0dd82a78269852ef9fda48219f60e6fedba1917d612b15d1017441f92e20354f2abfeffffff0017640700000000001f7928edd6de2605b223349fe138e05faa76047edbaf37b4863ef55e445151ff642221036b74361a868cde5e4869968793cc51a0510d899922c3cc6073664d7ac9ccbbd0406352c653dda78c67a25119ca0a392ced57622609f4cf573f3a130ef389adf065bf3f1cc5dbb23e52d1db9219dfedceb688e1a75d4237a4d21d862a3053078657feffffff2bd7dc010000000000db171df4477eeaad05319158cd6c8fa9a18f9be8985e04d9db0f6d3d005ecdff64222102ade93f3ad265d66dcfd42c7ae3c80898f902b231629fdbe9dcfcc35483bca7404099797dc2ec315876f3491dd266b1d27daace1fd398e20e89d1c1cbae7059b33c6a8245a251d86c95edd44571e3a179c729525a935b947aceb712d3cea5a9d567feffffff7badb903000000000201864c51000000000017005114c010e311349b28b1ab2aaa6102c94e6486081fa101780296490000000017005114ef8b65ed29fb260379e772db69d816b7956dcb24c1030000
00010097d2862938b4b5a1cc3d043896e14daaa756b2deea1738852a1891937c86e5d064222103238b71f552908f0998d7d0cc3fdc07aeac5fb70108c59e949cfb67aac6a12ff040aa1682ced417d38aa730c73d3149e1cc7e7196dbf293226db3061ca41b60d473299fa95cb1cd7188c0c72da8353326df7e4f0d792ec150235d7521e0fc03478efeffffff78029649000000000201fd07010000000000170051146777dfa4983d59a7c431243d53881f51861fd07801a0f99449000000001700511452cfae8f7277ffea0e483712bd2150b94c802286c2030000

After pasting, the debugger will automatically do the following steps:

  • Based on the two transactions determine which input/output you are interested in
  • Discover the relevant scripts
  • Load the script, prevouts, and transaction state into the Nexa Script Machine (other prevouts get empty data)
  • Execute all push-only scripts (constraint and satisfier), and pause at the beginning of the template script

So you should see the "Constraint" and "Satisfier" tabs filled with 1 data push each, and the "Template" tab filled with 2 instructions: "FROMALTSTACK CHECKSIGVERIFY". This is the standard "Pay-to-script-template" Nexa transaction. It is similar to the "pay-to-public-key-hash" format of Bitcoin/Bitcoin Cash, except that the constraint script supplies the pubkey and the satisfier script supplies the signature.

Now use the ">" button to step through execution of this code, until the script succeeds.

You can use the "<<" button to restart the template script execution. Or you can use the "<<<" button to rewind to the very beginning and watch the constraint and satisfier scripts execute as well (since they may ONLY push data onto the alt and main stacks respectively the debugger by default automatically executes these for you).

Debug different scripts

With the 2 transactions still loaded, write a simple script and paste it into the template script buffer.

For example:
FROMALTSTACK 1 DROP CHECKSIGVERIFY

You can see template script change. Note that your instruction pointer will not change. Depending on how different the new script is, you may need to reset the machine. Step through this script and in the last instruction you will see a failure in the "Nexa Machine Status":

Signature must be zero for failed CHECK(MULTI)SIG operation(39)

What happened here? Well, you changed the script, and therefore the transaction. But the transaction's signature was unchanged (the first push in the satisfier script), so the signature failed.

Numerical Example

    1
    2
    3
    0x02
    0
Try pasting the above example into the template script and stepping through it. You can see that the 0x02 produces a machine error "data larger than necessary". This is not a minimally encoded number, so the script fails at that point. Because this is a debugger though, you can continue as if the error never happened.

Linking

You can launch this debugger via a link. If you are debugging a script template, most of the data is available in the transaction. So you can just specify the transaction hex and which input to debug: Try /tx/000100010200000000000000000000000000000000000000000000000000000000003207036c7575015153ffffffffe80300000000000001008403000000000000015100000000?idx=0

Note the warning that appears when the debugger sets itself up. This warning is because some information is missing, so the debugger hopes that your scripts won't use that data. If your script template DOES access the missing data -- outpoint data or constraint script public arguments, then you will need to specify additional parameters to this URL as follows: /tx/000100010200000000000000000000000000000000000000000000000000000000003207036c7575015153ffffffffe80300000000000001008403000000000000015100000000?idx=0&utxo=01e8030000000000002b00147d4861012039dab2c9f78120a4a50d2c85db9af214da1745e9b549bd0bfa1a569971c77eba30cd5a4b

Examples

This spend simply adds 3 numbers and verifies they equal 5. One number is provided by the satisfier, hidden constraints and public constraints each. Try pasting a script with different numbers into the constraint or satisfier, restart the script machine to the beginning (<<<) and step thru to see it fail.
Nexa Machine status:
script:
position:
BMD:
Main Stack
Alt Stack