I haven’t played the whole HTLC thing through, but was starting easy: try to create a redeem script, and the condition shall be, that a hash is checked with „equal verify“. Only play on testnet/regtest! My example below is on unixoide systems, at the command line with bitcoin in regtest mode. I have done this with "bitcoin_cli -version": v0.15.1 Attention, there has been changes in v0.16.
To begin, for the ScriptSig I simply ignore signatures, and just put the secret on the stack, followed by an OP_TRUE to fulfill the IF STATEMENT later on.
For the RedeemScript the following logic is used:
# OP_IF # a9 14 <hash_lock> 87 # OP_ELSE # 76 a9 14 <pubkey_hash> 88 ac # OP_ENDIF
Which ends up in a pseudo serialized way a bit like this:
# 63 a914<hash_lock>88 67 76a914<pubkey_hash>88ac 68
And in my case into this redeem script: 63a9148103b0df9ad75e2b774f43d6e7e71eeaa2c73efb876776a9146a81e587585e58b07dce293a089894a0f8a61b8488ac68
The secret shall be:
# 426974636f696e5f72756c657321 # = ascii hex(Bitcoin_rules!) # SHA256(4269...7321) = bc6cee57412cfe8c26cbef4676d3af3182e2897ba482a8ce05ee407aebe76699 # RIPEMD160(SHA256(4269...7321) = 8103b0df9ad75e2b774f43d6e7e71eeaa2c73efb
And here are all the variables I used to have:
b_cli="bitcoin-cli -regtest" RedeemScriptHash=361801286b4be137f6a468ff8a34cfceb071763c RedeemScriptAddress=2MxBFEWKRPBy96BCxmuZuXkz5CfivDg8e1a Spend_TX_Value=9.99995000 Src_Address=mqE7Xm8vXYMx2T7qkCk5ggYuxwo8PHGT7k Src_PrivKey=cT2KDnyWU7UoFdwVBgv682HAAPAVzpiHZ9YY54YRgFvUmXFr6L4n Src_PubKey=02dae48354460f84dde299dbf35504056ae6cc500e2ef32b805cda1fdb1924a420 Src_PubKeyScript=76a9146a81e587585e58b07dce293a089894a0f8a61b8488ac Tgt_Address=mtad6HurkyVUtZUWvWHuF2DQ6nQ7bodz19 Tgt_PubKeyScript=76a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac UTXO_ScriptPK=a914361801286b4be137f6a468ff8a34cfceb071763c87 UTXO_TXID=6a8764163bc493073c3f05f9ad37cb9fdfb8136d19263c8e4ae38d8e00cdf16b UTXO_VOUT=0
I then created a funding transaction of 10 BTC to the redeem script address with this command, and generate a block:
$b_cli sendtoaddress $RedeemScriptAddress 10 $b_cli generate 1
CREATING TX
$b_cli createrawtransaction '''[{\"txid\":\"'$UTXO_TXID'\",\"vout\":'$UTXO_VOUT'}]''' '''{\"'$Tgt_Address'\":'$Spend_TX_Value'}'''
02000000016bf1cd008e8de34a8e3c26196d13b8df9fcb37adf9053f3c0793c43b1664876a0000000000ffffffff0178b69a3b000000001976a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac00000000
(gosh! these escape sequences drove me mad in the shell script ...)
SIGNING TX
$b_cli signrawtransaction $RAW_TX '''[{"txid": "'$UTXO_TXID'","vout": '$UTXO_VOUT',"scriptPubKey": "'$UTXO_ScriptPK'","redeemScript": "'$RedeemScript'"}]''' '''["'$Src_PrivKey'"]''' { "hex": "02000000016bf1cd008e8de34a8e3c26196d13b8df9fcb37adf9053f3c0793c43b1664876a00000000343363a9148103b0df9ad75e2b774f43d6e7e71eeaa2c73efb876776a9146a81e587585e58b07dce293a089894a0f8a61b8488ac68ffffffff0178b69a3b000000001976a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac00000000", "complete": false, "errors": [ { "txid": "6a8764163bc493073c3f05f9ad37cb9fdfb8136d19263c8e4ae38d8e00cdf16b", "vout": 0, "witness": [ ], "scriptSig": "3363a9148103b0df9ad75e2b774f43d6e7e71eeaa2c73efb876776a9146a81e587585e58b07dce293a089894a0f8a61b8488ac68", "sequence": 4294967295, "error": "Invalid OP_IF construction" } ] } BITCOIND Signed_TX:
02000000016bf1cd008e8de34a8e3c26196d13b8df9fcb37adf9053f3c0793c43b1664876a00000000343363a9148103b0df9ad75e2b774f43d6e7e71eeaa2c73efb876776a9146a81e587585e58b07dce293a089894a0f8a61b8488ac68ffffffff0178b69a3b000000001976a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac00000000
Note that bitcoin_cli returned an error with an invalid OP_IF statement
The returned BITCOIND Signed_TX can be decomposed this way:
Version: 02000000 V_INs: 01 TX_ID: 6bf1cd008e8de34a8e3c26196d13b8df9fcb37adf9053f3c0793c43b1664876a TX_Outpoint: 00000000 Len subscript: 34 Len script: 33 OP_IF: 63 a914 8103b0df9ad75e2b774f43d6e7e71eeaa2c73efb87 OP_ELSE: 67 76a914 6a81e587585e58b07dce293a089894a0f8a61b84 88ac OP_ENDIF: 68 Sequence: ffffffff TX_OUT …: 0178b69a3b000000001976a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac LockTime: 00000000
Now fiddling with the length values, and bringing in the secret, I end up with:
PREPARING SigScript
02000000016bf1cd008e8de34a8e3c26196d13b8df9fcb37adf9053f3c0793c43b1664876a00000000440E426974636f696e5f72756c657321513363a9148103b0df9ad75e2b774f43d6e7e71eeaa2c73efb876776a9146a81e587585e58b07dce293a089894a0f8a61b8488ac68ffffffff0178b69a3b000000001976a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac00000000
Version: 02000000 V_INs: 01 TX_ID: 6bf1cd008e8de34a8e3c26196d13b8df9fcb37adf9053f3c0793c43b1664876a TX_Outpoint: 00000000 Len subscript: 44 The secret: 0E426974636f696e5f72756c657321 = ascii hex(Bitcoin_rules!) OP_TRUE: 51 Len script: 33 OP_IF: 63 a914 8103b0df9ad75e2b774f43d6e7e71eeaa2c73efb87 OP_ELSE: 67 76a914 6a81e587585e58b07dce293a089894a0f8a61b84 88ac OP_ENDIF: 68 Sequence: ffffffff TX_OUT …: 0178b69a3b000000001976a9148f4b44f4975751d7cf6a797e0818c353afbd3bb388ac LockTime: 00000000
SENDING TX
$b_cli sendrawtransaction $to_send_TX
afa97d910badda64e8e2498d822387f8aa75c1efad7eb78caa06e67a0103bb0f
bitcoin-cli -regtest getrawmempool
[ "afa97d910badda64e8e2498d822387f8aa75c1efad7eb78caa06e67a0103bb0f" ]
bitcoin-cli -regtest generate 1
[ "5a5ecf0f67074eff7ce10d633fee99256f1094657354ab5e832d5412157782b0" ]
And then verify results with:
$b_cli listunspent | grep $RedeemScriptAddress $b_cli getreceivedbyaddress $Tgt_Address
Hint: The biggest „issue“ is to create the final tx before sending it. There you need to play with the length of the parts of the scriptsigs. Therefor I created some universally usable procedures to convert between hex and decimal in my .profile:
d2h() { echo "obase=16;$1" | bc } h2d() { echo "ibase=16;$1" | bc } len() { printf "$1" | wc -c } lenx() { my_len=$( len $1) d2h "$my_len / 2" }
I hope this helps to see, how a manually constructed smart contract can be realized at the command line step by step. I used two important references, especially the answer sections:
How to redeem a basic Tx?
How does the ECDSA verification algorithm work during transaction?