I currently started implementing Scripts in my Bitcoin client code. As I can't find too much data on interesting unit tests for many different Script opcodes, I decided to put this topic up for anyone interesting in collaborating on this.

However, there's no guarantee that each TxOut is spendable, so, only the ones that have corresponding TxIn scripts spending the TxOuts should be used. Luckily, if it's a non-std TxOut script, there's usually a non-std TxIn script to spend it, so they should both be in that list. Since TxHashes are listed you can do a search for matching scripts...

That is the complete debugging state at every step of a 2-of-2 and 2-of-3 (with addr-verify but no OP_CHECKMULTISIG) and another 2-of-3 that does addr-verify and uses OP_CHECKMULTISIG. Not only do they make good unit tests, but the debugging states are great for seeing how these scripts actually work.

Keep in mind, those multi-sig txs are not the "standard" multi-sig types that will be in the upcoming client releases, but they will stress your script processor, and they are correct since they were accepted by the Satoshi client on the Testnet.

Hmm, are those dumps from the multi-sig complete, or abbreviated? Since you seem to be calling checksig on "30460221 047cf315", which would make one of them a public key. Aren't those supposed to be longer?

Hmm, are those dumps from the multi-sig complete, or abbreviated? Since you seem to be calling checksig on "30460221 047cf315", which would make one of them a public key. Aren't those supposed to be longer?

Sorry, they are abbreviated to make it readable, and they are unique so there is no ambiguity. The debugging states were only intended to be examined by eye, to make sure that the script processor was doing the right thing. If you want to run those tests yourself, you can grab the TxHash from the top of the debugging output, and search for it in the full list of Testnet scripts.

In each of the testnet scripts, I included the raw script (in hex) and the full raw tx (in hex). From that, you should have just about everything you could possibly need to run those scripts through your scripting engine.

What language are you writing in? Anybody want to volunteer to write a Satoshi-bitcoin unit tester in C++ that parses ThePiachu's format? Or do you already have code that runs them? Committing a gazillion Script unit test cases to src/test/scriptTests/ sounds like a very good idea to me.

How often do you get the chance to work on a potentially world-changing project?

For now, I'm not creating any files, just writing the tests by hand in my source file. Probably could write them down in a txt file and upload them somewhere (like either a directory in Bitcoin github, or some new repository).

I'm writing my code in Go and I guess at some point I might create some website that can run the Bitcoin Script from a text input. For now though I need to finish writing the code for a few last OPs.

Should we also write unit tests for operations that will generate errors?

I just pulled out the three transactions I referenced in my first post, and put them into a form that you should be able to copy them right into your tests. Since all of them contain signature-checks, you will need the full serialized transaction -- which I have included. If you don't want the scripts separately, you can just concatenate the scripts: <TxIn | TxOut>

Note that all of these scripts are non-standard. They are actually designed to allow for 20-byte public keys hashes to be used as input instead of 65-byte public keys. As such, they are very complicated because the script has to verify that the public keys match 2 of the hashes in the TxOut script.

Also, be careful with you Hash160 calls. As I learned from testing my own scripting engine, OP_0 is interpretted as [] (empty string), which means it can be hashed and has zero length. Those are both important for passing those script tests.