@ -38,7 +38,7 @@
/* The names of the requests we can make to our Bitcoin backend. */
static const char * methods [ ] = { " getchaininfo " , " getrawblockbyheight " ,
" sendrawtransaction " , " getutxout " ,
" getfeerate " } ;
" estimatefees " } ;
static void plugin_config_cb ( const char * buffer ,
const jsmntok_t * toks ,
@ -113,9 +113,17 @@ void bitcoind_check_commands(struct bitcoind *bitcoind)
/* Our Bitcoin backend plugin gave us a bad response. We can't recover. */
static void bitcoin_plugin_error ( struct bitcoind * bitcoind , const char * buf ,
const jsmntok_t * toks , const char * method ,
const char * reason )
const char * fmt , . . . )
{
struct plugin * p = strmap_get ( & bitcoind - > pluginsmap , method ) ;
va_list ap ;
char * reason ;
struct plugin * p ;
va_start ( ap , fmt ) ;
reason = tal_vfmt ( NULL , fmt , ap ) ;
va_end ( ap ) ;
p = strmap_get ( & bitcoind - > pluginsmap , method ) ;
fatal ( " %s error: bad response to %s (%s), response was %.*s " ,
p - > cmd , method , reason ,
toks - > end - toks - > start , buf + toks - > start ) ;
@ -133,118 +141,111 @@ static void bitcoin_plugin_send(struct bitcoind *bitcoind,
plugin_request_send ( plugin , req ) ;
}
/* `getfeerate `
/* `estimatefees `
*
* Gather feerate from our Bitcoin backend . Will set the feerate to ` null `
* if estimation failed .
*
* - ` opening ` is used for funding and also misc transactions
* - ` mutual_close ` is used for the mutual close transaction
* - ` unilateral_close ` is used for unilateral close ( commitment transactions )
* - ` delayed_to_us ` is used for resolving our output from our unilateral close
* - ` htlc_resolution ` is used for resolving onchain HTLCs
* - ` penalty ` is used for resolving revoked transactions
* - ` min ` is the minimum acceptable feerate
* - ` max ` is the maximum acceptable feerate , note that it will be multiplied by the
* config ' s ` max_fee_multiplier ` .
*
* Plugin response :
* {
* " feerate " : < fee per KB > ,
* " opening " : < sat per kVB > ,
* " mutual_close " : < sat per kVB > ,
* " unilateral_close " : < sat per kVB > ,
* " delayed_to_us " : < sat per kVB > ,
* " htlc_resolution " : < sat per kVB > ,
* " penalty " : < sat per kVB > ,
* " min_acceptable " : < sat per kVB > ,
* " max_acceptable " : < sat per kVB > ,
* }
*/
struct estimatefee_call {
struct bitcoind * bitcoind ;
size_t i ;
const u32 * blocks ;
const char * * estmode ;
void ( * cb ) ( struct bitcoind * bitcoind , const u32 satoshi_per_kw [ ] ,
void * ) ;
void * arg ;
u32 * satoshi_per_kw ;
} ;
static void do_one_estimatefee ( struct bitcoind * bitcoind ,
struct estimatefee_call * call ) ;
static void getfeerate_callback ( const char * buf , const jsmntok_t * toks ,
static void estimatefees_callback ( const char * buf , const jsmntok_t * toks ,
const jsmntok_t * idtok ,
struct estimatefee_call * call )
{
const jsmntok_t * resulttok , * feeratetok ;
u64 feerate ;
u32 * feerates = tal_arr ( call , u32 , NUM_FEERATES ) ;
resulttok = json_get_member ( buf , toks , " result " ) ;
if ( ! resulttok )
bitcoin_plugin_error ( call - > bitcoind , buf , toks ,
" getfeerate " ,
" estimatefees " ,
" bad 'result' field " ) ;
feeratetok = json_get_member ( buf , resulttok , " feerate " ) ;
for ( enum feerate f = 0 ; f < NUM_FEERATES ; f + + ) {
feeratetok = json_get_member ( buf , resulttok , feerate_name ( f ) ) ;
if ( ! feeratetok )
bitcoin_plugin_error ( call - > bitcoind , buf , toks ,
" getfeerate " ,
" bad 'feerate' field " ) ;
" estimatefees " ,
" missing '%s' field " , feerate_name ( f ) ) ;
/* FIXME: We could trawl recent blocks for median fee... */
if ( ! json_to_u64 ( buf , feeratetok , & feerate ) ) {
log_unusual ( call - > bitcoind - > log , " Unable to estimate %s/%u fee " ,
call - > estmode [ call - > i ] , call - > blocks [ call - > i ] ) ;
if ( ! json_to_u32 ( buf , feeratetok , & feerates [ f ] ) ) {
log_unusual ( call - > bitcoind - > log ,
" Unable to estimate %s fees " ,
feerate_name ( f ) ) ;
# if DEVELOPER
/* This is needed to test for failed feerate estimates
* in DEVELOPER mode */
call - > satoshi_per_kw [ call - > i ] = 0 ;
feerates [ f ] = 0 ;
# else
/* If we are in testnet mode we want to allow payments
* with the minimal fee even if the estimate didn ' t
* work out . This is less disruptive than erring out
* all the time . */
if ( chainparams - > testnet )
call - > satoshi_per_kw [ call - > i ] = FEERATE_FLOOR ;
feerates [ f ] = FEERATE_FLOOR ;
else
call - > satoshi_per_kw [ call - > i ] = 0 ;
feerates [ f ] = 0 ;
# endif
} else
/* Rate in satoshi per kw. */
call - > satoshi_per_kw [ call - > i ]
= feerate_from_style ( feerate , FEERATE_PER_KBYTE ) ;
call - > i + + ;
if ( call - > i = = tal_count ( call - > satoshi_per_kw ) ) {
call - > cb ( call - > bitcoind , call - > satoshi_per_kw , call - > arg ) ;
tal_free ( call ) ;
} else {
/* Next */
do_one_estimatefee ( call - > bitcoind , call ) ;
feerates [ f ] = feerate_from_style ( feerates [ f ] ,
FEERATE_PER_KBYTE ) ;
}
}
static void do_one_estimatefee ( struct bitcoind * bitcoind ,
struct estimatefee_call * call )
{
struct jsonrpc_request * req ;
req = jsonrpc_request_start ( bitcoind , " getfeerate " ,
bitcoind - > log , getfeerate_callback ,
call ) ;
json_add_num ( req - > stream , " blocks " , call - > blocks [ call - > i ] ) ;
json_add_string ( req - > stream , " mode " , call - > estmode [ call - > i ] ) ;
jsonrpc_request_end ( req ) ;
bitcoin_plugin_send ( bitcoind , req ) ;
call - > cb ( call - > bitcoind , feerates , call - > arg ) ;
tal_free ( call ) ;
}
void bitcoind_estimate_fees_ ( struct bitcoind * bitcoind ,
const u32 blocks [ ] , const char * estmode [ ] ,
size_t num_estimates ,
void ( * cb ) ( struct bitcoind * bitcoind ,
const u32 satoshi_per_kw [ ] , void * ) ,
void * arg )
{
struct estimatefee_call * efee = tal ( bitcoind , struct estimatefee_call ) ;
efee - > bitcoind = bitcoind ;
efee - > i = 0 ;
efee - > blocks = tal_dup_arr ( efee , u32 , blocks , num_estimates , 0 ) ;
efee - > estmode = tal_dup_arr ( efee , const char * , estmode , num_estimates ,
0 ) ;
efee - > cb = cb ;
efee - > arg = arg ;
efee - > satoshi_per_kw = tal_arr ( efee , u32 , num_estimates ) ;
do_one_estimatefee ( bitcoind , efee ) ;
struct jsonrpc_request * req ;
struct estimatefee_call * call = tal ( bitcoind , struct estimatefee_call ) ;
call - > bitcoind = bitcoind ;
call - > cb = cb ;
call - > arg = arg ;
/* No parameter needed, we always want an urgent, normal and slow
* feerate . This gives computation flexibility to the plugin . */
req = jsonrpc_request_start ( bitcoind , " estimatefees " , bitcoind - > log ,
estimatefees_callback , call ) ;
jsonrpc_request_end ( req ) ;
plugin_request_send ( strmap_get ( & bitcoind - > pluginsmap ,
" estimatefees " ) , req ) ;
}
/* `sendrawtransaction`