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?