@ -10,17 +10,36 @@
# include <bitcoin/tx.h>
# include <ccan/err/err.h>
# include <ccan/str/hex/hex.h>
# include <channeld/full_channel.h>
# include <common/amount.h>
# include <common/derive_basepoints.h>
# include <common/initial_commit_tx.h>
# include <common/htlc_wire.h>
# include <common/key_derive.h>
# include <common/keyset.h>
# include <common/status.h>
# include <common/type_to_string.h>
# include <inttypes.h>
# include <stdarg.h>
# include <stdio.h>
static bool verbose = false ;
void status_fmt ( enum log_level level , const char * fmt , . . . )
{
if ( verbose ) {
va_list ap ;
va_start ( ap , fmt ) ;
printf ( " #TRACE: " ) ;
vprintf ( fmt , ap ) ;
printf ( " \n " ) ;
va_end ( ap ) ;
}
}
void status_failed ( enum status_failreason reason , const char * fmt , . . . )
{
abort ( ) ;
}
/* Code to make a commitment tx, useful for generating test cases. */
@ -111,24 +130,25 @@ static void print_basepoints(const char *desc,
type_to_string ( NULL , struct pubkey , & per_commitment_point ) ) ;
}
struct settings {
u32 to_self_delay ;
struct amount_sat dustlimit ;
struct amount_sat reserve ;
} ;
static int parse_settings ( char * argv [ ] ,
struct settings * settings ,
const char * desc )
static int parse_config ( char * argv [ ] ,
struct channel_config * config ,
const char * desc )
{
int argnum = 0 ;
settings - > to_self_delay = atoi ( argv [ argnum ] ) ;
config - > id = 0 ;
/* FIXME: Allow overriding these on cmdline! */
config - > max_htlc_value_in_flight = AMOUNT_MSAT ( - 1ULL ) ;
config - > htlc_minimum = AMOUNT_MSAT ( 0 ) ;
config - > max_accepted_htlcs = 483 ;
config - > to_self_delay = atoi ( argv [ argnum ] ) ;
argnum + + ;
if ( ! parse_amount_sat ( & settings - > dustlimit ,
if ( ! parse_amount_sat ( & config - > dust_ limit ,
argv [ argnum ] , strlen ( argv [ argnum ] ) ) )
errx ( 1 , " Bad %s dustlimit " , desc ) ;
argnum + + ;
if ( ! parse_amount_sat ( & settings - > reserve ,
if ( ! parse_amount_sat ( & config - > channel_ reserve,
argv [ argnum ] , strlen ( argv [ argnum ] ) ) )
errx ( 1 , " Bad %s reserve " , desc ) ;
argnum + + ;
@ -145,6 +165,58 @@ static char *sig_as_hex(const struct bitcoin_signature *sig)
return tal_hexstr ( NULL , compact_sig , sizeof ( compact_sig ) ) ;
}
static int parse_htlc ( char * argv [ ] ,
struct added_htlc * * htlcs ,
enum htlc_state * * htlc_states ,
struct preimage * * preimages )
{
struct added_htlc add ;
int argnum = 0 ;
struct preimage preimage ;
add . id = tal_count ( * htlcs ) ;
if ( streq ( argv [ argnum ] , " local " ) )
tal_arr_expand ( htlc_states , SENT_ADD_ACK_REVOCATION ) ;
else if ( streq ( argv [ argnum ] , " remote " ) )
tal_arr_expand ( htlc_states , RCVD_ADD_ACK_REVOCATION ) ;
else
errx ( 1 , " Bad htlc offer: %s should be 'local' or 'remote' " ,
argv [ argnum ] ) ;
argnum + + ;
if ( ! hex_decode ( argv [ argnum ] , strlen ( argv [ argnum ] ) ,
& preimage , sizeof ( preimage ) ) )
errx ( 1 , " Bad payment-preimage %s " , argv [ argnum ] ) ;
tal_arr_expand ( preimages , preimage ) ;
sha256 ( & add . payment_hash , & preimage , sizeof ( preimage ) ) ;
argnum + + ;
if ( ! parse_amount_msat ( & add . amount ,
argv [ argnum ] , strlen ( argv [ argnum ] ) ) )
errx ( 1 , " Bad htlc amount %s " , argv [ argnum ] ) ;
argnum + + ;
add . cltv_expiry = atoi ( argv [ argnum ] ) ;
argnum + + ;
printf ( " # HTLC % " PRIu64 " : %s amount=%s preimage=%s payment_hash=%s cltv=%u \n " ,
add . id , argv [ 0 ] ,
type_to_string ( tmpctx , struct amount_msat , & add . amount ) ,
type_to_string ( tmpctx , struct preimage , & preimage ) ,
type_to_string ( tmpctx , struct sha256 , & add . payment_hash ) ,
add . cltv_expiry ) ;
tal_arr_expand ( htlcs , add ) ;
return argnum ;
}
static const struct preimage * preimage_of ( const struct sha256 * hash ,
const struct added_htlc * htlcs ,
const struct preimage * preimages )
{
for ( size_t i = 0 ; i < tal_count ( preimages ) ; i + + )
if ( sha256_eq ( hash , & htlcs [ i ] . payment_hash ) )
return preimages + i ;
abort ( ) ;
}
int main ( int argc , char * argv [ ] )
{
struct secrets local , remote ;
@ -155,26 +227,38 @@ int main(int argc, char *argv[])
struct amount_sat funding_amount ;
struct bitcoin_txid funding_txid ;
unsigned int funding_outnum ;
unsigned int feerate_per_kw ;
u32 feerate_per_kw [ NUM_SIDES ] ;
struct pubkey local_per_commit_point , remote_per_commit_point ;
struct keyset localkeys , remotekeys ;
struct bitcoin_signature local_sig , remote_sig ;
struct settings localsettings , remotesettings ;
struct channel_config localconfig , remoteconfig ;
struct amount_msat local_msat , remote_msat ;
int argnum ;
struct bitcoin_tx * local_tx , * remote_tx ;
struct bitcoin_tx * * local_txs , * * remote_txs ;
enum side fee_payer ;
char * err ;
u8 * * witness ;
const u8 * * wscripts ;
struct channel * channel ;
struct added_htlc * htlcs = tal_arr ( NULL , struct added_htlc , 0 ) ;
enum htlc_state * hstates = tal_arr ( NULL , enum htlc_state , 0 ) ;
struct preimage * preimages = tal_arr ( NULL , struct preimage , 0 ) ;
const struct htlc * * htlcmap ;
struct privkey local_htlc_privkey , remote_htlc_privkey ;
struct pubkey local_htlc_pubkey , remote_htlc_pubkey ;
setup_locale ( ) ;
secp256k1_ctx = secp256k1_context_create ( SECP256K1_CONTEXT_VERIFY |
SECP256K1_CONTEXT_SIGN ) ;
if ( argc ! = 1 + 7 + 3 * 2 + 6 * 2 )
errx ( 1 , " Usage: mkcommit <commitnum> <funding-txid> <funding-txout> <funding-amount> <feerate-per-kw> <local-msat> <fee-payer> <localsettings> <remotesettings> <remote-reserve> <localsecrets> <remotesecrets> \n "
" Where <settings> are: \n "
if ( argv [ 1 ] & & streq ( argv [ 1 ] , " -v " ) ) {
verbose = true ;
argv + + ;
argc - - ;
}
if ( argc < 1 + 7 + 3 * 2 + 6 * 2 )
errx ( 1 , " Usage: mkcommit [-v] <commitnum> <funding-txid> <funding-txout> <funding-amount> <feerate-per-kw> <local-msat> <fee-payer> <localconfig> <remoteconfig> <remote-reserve> <localsecrets> <remotesecrets> [<htlc>...] \n "
" Where <config> are: \n "
" <to-self-delay> \n "
" <dustlimit> \n "
" <reserve-sat> \n "
@ -184,7 +268,12 @@ int main(int argc, char *argv[])
" <revocation-base-secret> \n "
" <payment-base-secret> \n "
" <delayed-payment-base-secret> \n "
" <htlc-base-secret> " ) ;
" <htlc-base-secret> \n "
" Where <htlc>s are: \n "
" <offer-side> \n "
" <payment-preimage> \n "
" <amount-msat> \n "
" <cltv-expiry> \n " ) ;
argnum = 1 ;
commitnum = atol ( argv [ argnum + + ] ) ;
@ -196,7 +285,7 @@ int main(int argc, char *argv[])
if ( ! parse_amount_sat ( & funding_amount , argv [ argnum ] , strlen ( argv [ argnum ] ) ) )
errx ( 1 , " Bad funding-amount " ) ;
argnum + + ;
feerate_per_kw = atoi ( argv [ argnum + + ] ) ;
feerate_per_kw [ LOCAL ] = feerate_per_kw [ REMOTE ] = atoi ( argv [ argnum + + ] ) ;
if ( ! parse_amount_msat ( & local_msat ,
argv [ argnum ] , strlen ( argv [ argnum ] ) ) )
errx ( 1 , " Bad local-msat " ) ;
@ -209,8 +298,8 @@ int main(int argc, char *argv[])
errx ( 1 , " fee-payer must be 'local' or 'remote' " ) ;
argnum + + ;
argnum + = parse_settings ( argv + argnum , & localsettings , " local " ) ;
argnum + = parse_settings ( argv + argnum , & remotesettings , " remote " ) ;
argnum + = parse_config ( argv + argnum , & localconfig , " local " ) ;
argnum + = parse_config ( argv + argnum , & remoteconfig , " remote " ) ;
argnum + = parse_secrets ( argv + argnum , & local , & localseed , " local " ) ;
argnum + = parse_secrets ( argv + argnum , & remote , & remoteseed , " remote " ) ;
@ -218,6 +307,11 @@ int main(int argc, char *argv[])
if ( ! amount_sat_sub_msat ( & remote_msat , funding_amount , local_msat ) )
errx ( 1 , " Can't afford local_msat " ) ;
printf ( " ## HTLCs \n " ) ;
while ( argnum < argc )
argnum + = parse_htlc ( argv + argnum , & htlcs , & hstates , & preimages ) ;
printf ( " \n " ) ;
if ( ! pubkey_from_privkey ( & local . funding_privkey , & funding_localkey )
| | ! pubkey_from_secret ( & local . revocation_basepoint_secret ,
& localbase . revocation )
@ -247,6 +341,21 @@ int main(int argc, char *argv[])
& remote , & remoteseed ,
& remotebase , & funding_remotekey , commitnum ) ;
channel = new_full_channel ( NULL ,
& chainparams_for_network ( " regtest " )
- > genesis_blockhash ,
& funding_txid , funding_outnum , 1 ,
funding_amount ,
local_msat ,
feerate_per_kw ,
& localconfig , & remoteconfig ,
& localbase , & remotebase ,
& funding_localkey , & funding_remotekey ,
fee_payer ) ;
if ( ! channel_force_htlcs ( channel , htlcs , hstates , NULL , NULL , NULL , NULL ) )
errx ( 1 , " Cannot add HTLCs " ) ;
u8 * funding_wscript = bitcoin_redeem_2of2 ( NULL ,
& funding_localkey ,
& funding_remotekey ) ;
@ -255,27 +364,8 @@ int main(int argc, char *argv[])
if ( ! per_commit_point ( & localseed , & local_per_commit_point , commitnum ) )
errx ( 1 , " Bad deriving local per-commitment-point " ) ;
if ( ! derive_keyset ( & local_per_commit_point , & localbase , & remotebase ,
& localkeys ) )
errx ( 1 , " Bad deriving local keyset " ) ;
local_tx = initial_commit_tx ( NULL , & funding_txid , funding_outnum ,
funding_amount , fee_payer ,
localsettings . to_self_delay ,
& localkeys ,
feerate_per_kw ,
localsettings . dustlimit ,
local_msat ,
remote_msat ,
localsettings . reserve ,
commitnum
^ commit_number_obscurer ( & localbase . payment ,
& remotebase . payment ) ,
LOCAL , & err ) ;
if ( ! local_tx )
errx ( 1 , " Can't make local commit tx: %s " , err ) ;
local_tx - > input_amounts [ 0 ]
= tal_dup ( local_tx , struct amount_sat , & funding_amount ) ;
local_txs = channel_txs ( NULL , & htlcmap , & wscripts , channel ,
& local_per_commit_point , commitnum , LOCAL ) ;
printf ( " ## local_commitment \n "
" # input amount %s, funding_wscript %s, key %s \n " ,
@ -283,16 +373,16 @@ int main(int argc, char *argv[])
tal_hex ( NULL , funding_wscript ) ,
type_to_string ( NULL , struct pubkey , & funding_localkey ) ) ;
printf ( " # unsigned local commitment tx: %s \n " ,
tal_hex ( NULL , linearize_tx ( NULL , local_tx ) ) ) ;
tal_hex ( NULL , linearize_tx ( NULL , local_txs [ 0 ] ) ) ) ;
sign_tx_input ( local_tx , 0 , NULL , funding_wscript ,
sign_tx_input ( local_txs [ 0 ] , 0 , NULL , funding_wscript ,
& local . funding_privkey ,
& funding_localkey ,
SIGHASH_ALL ,
& local_sig ) ;
printf ( " localsig_on_local: %s \n " , sig_as_hex ( & local_sig ) ) ;
sign_tx_input ( local_tx , 0 , NULL , funding_wscript ,
sign_tx_input ( local_txs [ 0 ] , 0 , NULL , funding_wscript ,
& remote . funding_privkey ,
& funding_remotekey ,
SIGHASH_ALL ,
@ -302,36 +392,83 @@ int main(int argc, char *argv[])
witness =
bitcoin_witness_2of2 ( NULL , & local_sig , & remote_sig ,
& funding_localkey , & funding_remotekey ) ;
bitcoin_tx_input_set_witness ( local_tx , 0 , witness ) ;
printf ( " # signed local commitment: %s \n \n " ,
tal_hex ( NULL , linearize_tx ( NULL , local_tx ) ) ) ;
bitcoin_tx_input_set_witness ( local_txs [ 0 ] , 0 , witness ) ;
printf ( " # signed local commitment: %s \n " ,
tal_hex ( NULL , linearize_tx ( NULL , local_txs [ 0 ] ) ) ) ;
if ( ! derive_simple_privkey ( & local . htlc_basepoint_secret ,
& localbase . htlc ,
& local_per_commit_point ,
& local_htlc_privkey ) )
errx ( 1 , " Failure deriving local htlc privkey " ) ;
if ( ! derive_simple_key ( & localbase . htlc ,
& local_per_commit_point ,
& local_htlc_pubkey ) )
errx ( 1 , " Failure deriving local htlc pubkey " ) ;
if ( ! derive_simple_privkey ( & remote . htlc_basepoint_secret ,
& remotebase . htlc ,
& local_per_commit_point ,
& remote_htlc_privkey ) )
errx ( 1 , " Failure deriving remote htlc privkey " ) ;
if ( ! derive_simple_key ( & remotebase . htlc ,
& local_per_commit_point ,
& remote_htlc_pubkey ) )
errx ( 1 , " Failure deriving remote htlc pubkey " ) ;
for ( size_t i = 0 ; i < tal_count ( htlcmap ) ; i + + ) {
struct bitcoin_signature local_htlc_sig , remote_htlc_sig ;
struct amount_sat amt ;
if ( ! htlcmap [ i ] )
continue ;
printf ( " # Output %zu: %s HTLC % " PRIu64 " \n " ,
i , side_to_str ( htlc_owner ( htlcmap [ i ] ) ) , htlcmap [ i ] - > id ) ;
printf ( " # unsigned htlc tx for output %zu: %s \n " ,
i , tal_hex ( NULL , linearize_tx ( NULL , local_txs [ 1 + i ] ) ) ) ;
amt = amount_msat_to_sat_round_down ( htlcmap [ i ] - > amount ) ;
local_txs [ 1 + i ] - > input_amounts [ 0 ]
= tal_dup ( local_txs [ 1 + i ] , struct amount_sat , & amt ) ;
printf ( " # wscript: %s \n " , tal_hex ( NULL , wscripts [ 1 + i ] ) ) ;
sign_tx_input ( local_txs [ 1 + i ] , 0 , NULL , wscripts [ 1 + i ] ,
& local_htlc_privkey , & local_htlc_pubkey ,
SIGHASH_ALL , & local_htlc_sig ) ;
sign_tx_input ( local_txs [ 1 + i ] , 0 , NULL , wscripts [ 1 + i ] ,
& remote_htlc_privkey , & remote_htlc_pubkey ,
SIGHASH_ALL , & remote_htlc_sig ) ;
printf ( " localsig_on_local output %zu: %s \n " ,
i , sig_as_hex ( & local_htlc_sig ) ) ;
printf ( " remotesig_on_local output %zu: %s \n " ,
i , sig_as_hex ( & remote_htlc_sig ) ) ;
if ( htlc_owner ( htlcmap [ i ] ) = = LOCAL )
witness = bitcoin_witness_htlc_timeout_tx ( NULL ,
& local_htlc_sig ,
& remote_htlc_sig ,
wscripts [ 1 + i ] ) ;
else
witness = bitcoin_witness_htlc_success_tx ( NULL ,
& local_htlc_sig ,
& remote_htlc_sig ,
preimage_of ( & htlcmap [ i ] - > rhash , htlcs , preimages ) ,
wscripts [ 1 + i ] ) ;
bitcoin_tx_input_set_witness ( local_txs [ 1 + i ] , 0 , witness ) ;
printf ( " htlc tx for output %zu: %s \n " ,
i , tal_hex ( NULL , linearize_tx ( NULL , local_txs [ 1 + i ] ) ) ) ;
}
printf ( " \n " ) ;
/* Create the remote commitment tx */
if ( ! per_commit_point ( & remoteseed , & remote_per_commit_point , commitnum ) )
errx ( 1 , " Bad deriving remote per-commitment-point " ) ;
if ( ! derive_keyset ( & remote_per_commit_point , & remotebase , & localbase ,
& remotekeys ) )
errx ( 1 , " Bad deriving remote keyset " ) ;
remote_tx = initial_commit_tx ( NULL , & funding_txid , funding_outnum ,
funding_amount ,
fee_payer ,
remotesettings . to_self_delay ,
& remotekeys ,
feerate_per_kw ,
remotesettings . dustlimit ,
remote_msat ,
local_msat ,
remotesettings . reserve ,
commitnum
^ commit_number_obscurer ( & localbase . payment ,
& remotebase . payment ) ,
REMOTE , & err ) ;
if ( ! remote_tx )
errx ( 1 , " Can't make remote commit tx: %s " , err ) ;
remote_tx - > input_amounts [ 0 ]
= tal_dup ( remote_tx , struct amount_sat , & funding_amount ) ;
remote_txs = channel_txs ( NULL , & htlcmap , & wscripts , channel ,
& remote_per_commit_point , commitnum , REMOTE ) ;
remote_txs [ 0 ] - > input_amounts [ 0 ]
= tal_dup ( remote_txs [ 0 ] , struct amount_sat , & funding_amount ) ;
printf ( " ## remote_commitment \n "
" # input amount %s, funding_wscript %s, key %s \n " ,
@ -339,16 +476,16 @@ int main(int argc, char *argv[])
tal_hex ( NULL , funding_wscript ) ,
type_to_string ( NULL , struct pubkey , & funding_remotekey ) ) ;
printf ( " # unsigned remote commitment tx: %s \n " ,
tal_hex ( NULL , linearize_tx ( NULL , remote_tx ) ) ) ;
tal_hex ( NULL , linearize_tx ( NULL , remote_txs [ 0 ] ) ) ) ;
sign_tx_input ( remote_tx , 0 , NULL , funding_wscript ,
sign_tx_input ( remote_txs [ 0 ] , 0 , NULL , funding_wscript ,
& local . funding_privkey ,
& funding_localkey ,
SIGHASH_ALL ,
& local_sig ) ;
printf ( " localsig_on_remote: %s \n " , sig_as_hex ( & local_sig ) ) ;
sign_tx_input ( remote_tx , 0 , NULL , funding_wscript ,
sign_tx_input ( remote_txs [ 0 ] , 0 , NULL , funding_wscript ,
& remote . funding_privkey ,
& funding_remotekey ,
SIGHASH_ALL ,
@ -358,10 +495,75 @@ int main(int argc, char *argv[])
witness =
bitcoin_witness_2of2 ( NULL , & local_sig , & remote_sig ,
& funding_localkey , & funding_remotekey ) ;
bitcoin_tx_input_set_witness ( remote_tx , 0 , witness ) ;
bitcoin_tx_input_set_witness ( remote_txs [ 0 ] , 0 , witness ) ;
printf ( " # signed remote commitment: %s \n " ,
tal_hex ( NULL , linearize_tx ( NULL , remote_tx ) ) ) ;
tal_hex ( NULL , linearize_tx ( NULL , remote_txs [ 0 ] ) ) ) ;
if ( ! derive_simple_privkey ( & local . htlc_basepoint_secret ,
& localbase . htlc ,
& remote_per_commit_point ,
& local_htlc_privkey ) )
errx ( 1 , " Failure deriving local htlc privkey " ) ;
if ( ! derive_simple_key ( & localbase . htlc ,
& remote_per_commit_point ,
& local_htlc_pubkey ) )
errx ( 1 , " Failure deriving local htlc pubkey " ) ;
if ( ! derive_simple_privkey ( & remote . htlc_basepoint_secret ,
& remotebase . htlc ,
& remote_per_commit_point ,
& remote_htlc_privkey ) )
errx ( 1 , " Failure deriving remote htlc privkey " ) ;
if ( ! derive_simple_key ( & remotebase . htlc ,
& remote_per_commit_point ,
& remote_htlc_pubkey ) )
errx ( 1 , " Failure deriving remote htlc pubkey " ) ;
for ( size_t i = 0 ; i < tal_count ( htlcmap ) ; i + + ) {
struct bitcoin_signature local_htlc_sig , remote_htlc_sig ;
struct amount_sat amt ;
if ( ! htlcmap [ i ] )
continue ;
printf ( " # Output %zu: %s HTLC % " PRIu64 " \n " ,
i , side_to_str ( htlc_owner ( htlcmap [ i ] ) ) , htlcmap [ i ] - > id ) ;
printf ( " # unsigned htlc tx for output %zu: %s \n " ,
i , tal_hex ( NULL , linearize_tx ( NULL , remote_txs [ 1 + i ] ) ) ) ;
amt = amount_msat_to_sat_round_down ( htlcmap [ i ] - > amount ) ;
remote_txs [ 1 + i ] - > input_amounts [ 0 ]
= tal_dup ( remote_txs [ 1 + i ] , struct amount_sat , & amt ) ;
printf ( " # wscript: %s \n " , tal_hex ( NULL , wscripts [ 1 + i ] ) ) ;
sign_tx_input ( remote_txs [ 1 + i ] , 0 , NULL , wscripts [ 1 + i ] ,
& local_htlc_privkey , & local_htlc_pubkey ,
SIGHASH_ALL , & local_htlc_sig ) ;
sign_tx_input ( remote_txs [ 1 + i ] , 0 , NULL , wscripts [ 1 + i ] ,
& remote_htlc_privkey , & remote_htlc_pubkey ,
SIGHASH_ALL , & remote_htlc_sig ) ;
printf ( " localsig_on_remote output %zu: %s \n " ,
i , sig_as_hex ( & local_htlc_sig ) ) ;
printf ( " remotesig_on_remote output %zu: %s \n " ,
i , sig_as_hex ( & remote_htlc_sig ) ) ;
if ( htlc_owner ( htlcmap [ i ] ) = = REMOTE )
witness = bitcoin_witness_htlc_timeout_tx ( NULL ,
& remote_htlc_sig ,
& local_htlc_sig ,
wscripts [ 1 + i ] ) ;
else
witness = bitcoin_witness_htlc_success_tx ( NULL ,
& remote_htlc_sig ,
& local_htlc_sig ,
preimage_of ( & htlcmap [ i ] - > rhash , htlcs , preimages ) ,
wscripts [ 1 + i ] ) ;
bitcoin_tx_input_set_witness ( remote_txs [ 1 + i ] , 0 , witness ) ;
printf ( " htlc tx for output %zu: %s \n " ,
i , tal_hex ( NULL , linearize_tx ( NULL , remote_txs [ 1 + i ] ) ) ) ;
}
printf ( " \n " ) ;
return 0 ;
}