# include "bitcoin/pullpush.h"
# include "commit_tx.h"
# include "db.h"
# include "feechange.h"
# include "gen_version.h"
# include "htlc.h"
# include "invoice.h"
# include "lightningd.h"
# include "log.h"
# include "names.h"
# include "netaddr.h"
# include "pay.h"
# include "peer_internal.h"
# include "routing.h"
# include "secrets.h"
# include "utils.h"
# include "wallet.h"
# include <ccan/array_size/array_size.h>
# include <ccan/cast/cast.h>
# include <ccan/cppmagic/cppmagic.h>
# include <ccan/mem/mem.h>
# include <ccan/str/hex/hex.h>
# include <ccan/tal/str/str.h>
# include <inttypes.h>
# include <sqlite3.h>
# include <stdarg.h>
# include <unistd.h>
# define DB_FILE "lightning.sqlite3"
/* They don't use stdint types. */
# define PRIuSQLITE64 "llu"
struct db {
bool in_transaction ;
const char * err ;
sqlite3 * sql ;
} ;
static void close_db ( struct db * db )
{
sqlite3_close ( db - > sql ) ;
}
/* We want a string, not an 'unsigned char *' thanks! */
static const char * sqlite3_column_str ( sqlite3_stmt * stmt , int iCol )
{
return cast_signed ( const char * , sqlite3_column_text ( stmt , iCol ) ) ;
}
# define SQL_U64(var) stringify(var)" BIGINT" /* Actually, an s64 */
# define SQL_U32(var) stringify(var)" INT"
# define SQL_BOOL(var) stringify(var)" BOOLEAN"
# define SQL_BLOB(var) stringify(var)" BLOB"
# define SQL_PUBKEY(var) stringify(var)" CHAR(33)"
# define SQL_PRIVKEY(var) stringify(var)" CHAR(32)"
# define SQL_SIGNATURE(var) stringify(var)" CHAR(64)"
# define SQL_TXID(var) stringify(var)" CHAR(32)"
# define SQL_RHASH(var) stringify(var)" CHAR(32)"
# define SQL_SHA256(var) stringify(var)" CHAR(32)"
# define SQL_R(var) stringify(var)" CHAR(32)"
/* STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE == 45*/
# define SQL_STATENAME(var) stringify(var)" VARCHAR(45)"
# define SQL_INVLABEL(var) stringify(var)" VARCHAR("stringify(INVOICE_MAX_LABEL_LEN)")"
/* 8 + 4 + (8 + 32) * (64 + 1) */
# define SHACHAIN_SIZE 2612
# define SQL_SHACHAIN(var) stringify(var)" CHAR("stringify(SHACHAIN_SIZE)")"
/* FIXME: Should be fixed size. */
# define SQL_ROUTING(var) stringify(var)" BLOB"
# define SQL_FAIL(var) stringify(var)" BLOB"
# define TABLE(tablename, ...) \
" CREATE TABLE " # tablename " ( " CPPMAGIC_JOIN ( " , " , __VA_ARGS__ ) " ); "
static const char * sql_bool ( bool b )
{
/* SQL2003 says TRUE and FALSE are binary literal keywords.
* sqlite3 barfs . */
return ( b ) ? " 1 " : " 0 " ;
}
static bool PRINTF_FMT ( 3 , 4 )
db_exec ( const char * caller ,
struct lightningd_state * dstate , const char * fmt , . . . )
{
va_list ap ;
char * cmd , * errmsg ;
int err ;
if ( dstate - > db - > in_transaction & & dstate - > db - > err )
return false ;
va_start ( ap , fmt ) ;
cmd = tal_vfmt ( dstate - > db , fmt , ap ) ;
va_end ( ap ) ;
err = sqlite3_exec ( dstate - > db - > sql , cmd , NULL , NULL , & errmsg ) ;
if ( err ! = SQLITE_OK ) {
tal_free ( dstate - > db - > err ) ;
dstate - > db - > err = tal_fmt ( dstate - > db , " %s:%s:%s:%s " ,
caller , sqlite3_errstr ( err ) ,
cmd , errmsg ) ;
sqlite3_free ( errmsg ) ;
tal_free ( cmd ) ;
log_broken ( dstate - > base_log , " %s " , dstate - > db - > err ) ;
return false ;
}
tal_free ( cmd ) ;
return true ;
}
static char * sql_hex_or_null ( const tal_t * ctx , const void * buf , size_t len )
{
char * r ;
if ( ! buf )
return " NULL " ;
r = tal_arr ( ctx , char , 3 + hex_str_size ( len ) ) ;
r [ 0 ] = ' x ' ;
r [ 1 ] = ' \' ' ;
hex_encode ( buf , len , r + 2 , hex_str_size ( len ) ) ;
r [ 2 + hex_str_size ( len ) - 1 ] = ' \' ' ;
r [ 2 + hex_str_size ( len ) ] = ' \0 ' ;
return r ;
}
static void from_sql_blob ( sqlite3_stmt * stmt , int idx , void * p , size_t n )
{
if ( sqlite3_column_bytes ( stmt , idx ) ! = n )
fatal ( " db:wrong bytes %i not %zu " ,
sqlite3_column_bytes ( stmt , idx ) , n ) ;
memcpy ( p , sqlite3_column_blob ( stmt , idx ) , n ) ;
}
static u8 * tal_sql_blob ( const tal_t * ctx , sqlite3_stmt * stmt , int idx )
{
u8 * p ;
if ( sqlite3_column_type ( stmt , idx ) = = SQLITE_NULL )
return NULL ;
p = tal_arr ( ctx , u8 , sqlite3_column_bytes ( stmt , idx ) ) ;
from_sql_blob ( stmt , idx , p , tal_count ( p ) ) ;
return p ;
}
static void pubkey_from_sql ( sqlite3_stmt * stmt , int idx , struct pubkey * pk )
{
if ( ! pubkey_from_der ( sqlite3_column_blob ( stmt , idx ) ,
sqlite3_column_bytes ( stmt , idx ) , pk ) )
fatal ( " db:bad pubkey length %i " ,
sqlite3_column_bytes ( stmt , idx ) ) ;
}
static void sha256_from_sql ( sqlite3_stmt * stmt , int idx , struct sha256 * sha )
{
from_sql_blob ( stmt , idx , sha , sizeof ( * sha ) ) ;
}
static void sig_from_sql ( sqlite3_stmt * stmt , int idx ,
secp256k1_ecdsa_signature * sig )
{
u8 compact [ 64 ] ;
from_sql_blob ( stmt , idx , compact , sizeof ( compact ) ) ;
if ( secp256k1_ecdsa_signature_parse_compact ( secp256k1_ctx , sig ,
compact ) ! = 1 )
fatal ( " db:bad signature blob " ) ;
}
static char * sig_to_sql ( const tal_t * ctx ,
const secp256k1_ecdsa_signature * sig )
{
u8 compact [ 64 ] ;
if ( ! sig )
return sql_hex_or_null ( ctx , NULL , 0 ) ;
secp256k1_ecdsa_signature_serialize_compact ( secp256k1_ctx , compact ,
sig ) ;
return sql_hex_or_null ( ctx , compact , sizeof ( compact ) ) ;
}
static void db_load_wallet ( struct lightningd_state * dstate )
{
int err ;
sqlite3_stmt * stmt ;
err = sqlite3_prepare_v2 ( dstate - > db - > sql , " SELECT * FROM wallet; " , - 1 ,
& stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " db_load_wallet:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( dstate - > db - > sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct privkey privkey ;
if ( err ! = SQLITE_ROW )
fatal ( " db_load_wallet:step gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 1 )
fatal ( " db_load_wallet:step gave %i cols, not 1 " ,
sqlite3_column_count ( stmt ) ) ;
from_sql_blob ( stmt , 0 , & privkey , sizeof ( privkey ) ) ;
if ( ! restore_wallet_address ( dstate , & privkey ) )
fatal ( " db_load_wallet:bad privkey " ) ;
}
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " db_load_wallet:finalize gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
}
void db_add_wallet_privkey ( struct lightningd_state * dstate ,
const struct privkey * privkey )
{
char * ctx = tal_tmpctx ( dstate ) ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
if ( ! db_exec ( __func__ , dstate ,
" INSERT INTO wallet VALUES (x'%s'); " ,
tal_hexstr ( ctx , privkey , sizeof ( * privkey ) ) ) )
fatal ( " db_add_wallet_privkey failed " ) ;
tal_free ( ctx ) ;
}
static void load_peer_secrets ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
const char * select ;
bool secrets_set = false ;
select = tal_fmt ( ctx ,
" SELECT * FROM peer_secrets WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_secrets:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_secrets:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( secrets_set )
fatal ( " load_peer_secrets: two secrets for '%s' " ,
select ) ;
peer_set_secrets_from_db ( peer ,
sqlite3_column_blob ( stmt , 1 ) ,
sqlite3_column_bytes ( stmt , 1 ) ,
sqlite3_column_blob ( stmt , 2 ) ,
sqlite3_column_bytes ( stmt , 2 ) ,
sqlite3_column_blob ( stmt , 3 ) ,
sqlite3_column_bytes ( stmt , 3 ) ) ;
secrets_set = true ;
}
if ( ! secrets_set )
fatal ( " load_peer_secrets: no secrets for '%s' " , select ) ;
tal_free ( ctx ) ;
}
static void load_peer_anchor ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
const char * select ;
bool anchor_set = false ;
select = tal_fmt ( ctx ,
" SELECT * FROM anchors WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_anchor:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_anchor:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( anchor_set )
fatal ( " load_peer_anchor: two anchors for '%s' " ,
select ) ;
from_sql_blob ( stmt , 1 ,
& peer - > anchor . txid , sizeof ( peer - > anchor . txid ) ) ;
peer - > anchor . index = sqlite3_column_int64 ( stmt , 2 ) ;
peer - > anchor . satoshis = sqlite3_column_int64 ( stmt , 3 ) ;
peer - > anchor . ours = sqlite3_column_int ( stmt , 6 ) ;
peer_watch_anchor ( peer , sqlite3_column_int ( stmt , 4 ) ) ;
peer - > anchor . min_depth = sqlite3_column_int ( stmt , 5 ) ;
anchor_set = true ;
}
if ( ! anchor_set )
fatal ( " load_peer_anchor: no anchor for '%s' " , select ) ;
tal_free ( ctx ) ;
}
static void load_peer_anchor_input ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
const char * select ;
bool anchor_input_set = false ;
select = tal_fmt ( ctx ,
" SELECT * FROM anchor_inputs WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_anchor_input:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_anchor_input:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( anchor_input_set )
fatal ( " load_peer_anchor_input: two inputs for '%s' " ,
select ) ;
peer - > anchor . input = tal ( peer , struct anchor_input ) ;
from_sql_blob ( stmt , 1 ,
& peer - > anchor . input - > txid ,
sizeof ( peer - > anchor . input - > txid ) ) ;
peer - > anchor . input - > index = sqlite3_column_int ( stmt , 2 ) ;
peer - > anchor . input - > in_amount = sqlite3_column_int64 ( stmt , 3 ) ;
peer - > anchor . input - > out_amount = sqlite3_column_int64 ( stmt , 4 ) ;
pubkey_from_sql ( stmt , 5 , & peer - > anchor . input - > walletkey ) ;
anchor_input_set = true ;
}
if ( ! anchor_input_set )
fatal ( " load_peer_anchor_input: no inputs for '%s' " , select ) ;
tal_free ( ctx ) ;
}
static void load_peer_visible_state ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
const char * select ;
bool visible_set = false ;
select = tal_fmt ( ctx ,
" SELECT * FROM their_visible_state WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_visible_state:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_visible_state:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 8 )
fatal ( " load_peer_visible_state:step gave %i cols, not 8 " ,
sqlite3_column_count ( stmt ) ) ;
if ( visible_set )
fatal ( " load_peer_visible_state: two states for %s " , select ) ;
visible_set = true ;
peer - > remote . offer_anchor = sqlite3_column_int ( stmt , 1 ) ;
pubkey_from_sql ( stmt , 2 , & peer - > remote . commitkey ) ;
pubkey_from_sql ( stmt , 3 , & peer - > remote . finalkey ) ;
peer - > remote . locktime . locktime = sqlite3_column_int ( stmt , 4 ) ;
peer - > remote . mindepth = sqlite3_column_int ( stmt , 5 ) ;
peer - > remote . commit_fee_rate = sqlite3_column_int64 ( stmt , 6 ) ;
sha256_from_sql ( stmt , 7 , & peer - > remote . next_revocation_hash ) ;
log_debug ( peer - > log , " %s:next_revocation_hash=%s " ,
__func__ ,
tal_hexstr ( ctx , & peer - > remote . next_revocation_hash ,
sizeof ( peer - > remote . next_revocation_hash ) ) ) ;
/* Now we can fill in anchor witnessscript. */
peer - > anchor . witnessscript
= bitcoin_redeem_2of2 ( peer ,
& peer - > local . commitkey ,
& peer - > remote . commitkey ) ;
}
if ( ! visible_set )
fatal ( " load_peer_visible_state: no result '%s' " , select ) ;
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_visible_state:finalize gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
tal_free ( ctx ) ;
}
static void load_peer_commit_info ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
const char * select ;
select = tal_fmt ( ctx ,
" SELECT * FROM commit_info WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_commit_info:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct commit_info * * cip , * ci ;
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_commit_info:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
/* peer "SQL_PUBKEY", side TEXT, commit_num INT, revocation_hash "SQL_SHA256", sig "SQL_SIGNATURE", xmit_order INT, prev_revocation_hash "SQL_SHA256", */
if ( sqlite3_column_count ( stmt ) ! = 7 )
fatal ( " load_peer_commit_info:step gave %i cols, not 7 " ,
sqlite3_column_count ( stmt ) ) ;
if ( streq ( sqlite3_column_str ( stmt , 1 ) , " LOCAL " ) )
cip = & peer - > local . commit ;
else {
if ( ! streq ( sqlite3_column_str ( stmt , 1 ) , " REMOTE " ) )
fatal ( " load_peer_commit_info:bad side %s " ,
sqlite3_column_str ( stmt , 1 ) ) ;
cip = & peer - > remote . commit ;
/* This is a hack where we temporarily store their
* previous revocation hash before we get their
* revocation . */
if ( sqlite3_column_type ( stmt , 6 ) ! = SQLITE_NULL ) {
peer - > their_prev_revocation_hash
= tal ( peer , struct sha256 ) ;
sha256_from_sql ( stmt , 6 ,
peer - > their_prev_revocation_hash ) ;
}
}
/* Do we already have this one? */
if ( * cip )
fatal ( " load_peer_commit_info:duplicate side %s " ,
sqlite3_column_str ( stmt , 1 ) ) ;
* cip = ci = new_commit_info ( peer , sqlite3_column_int64 ( stmt , 2 ) ) ;
sha256_from_sql ( stmt , 3 , & ci - > revocation_hash ) ;
ci - > order = sqlite3_column_int64 ( stmt , 4 ) ;
if ( sqlite3_column_type ( stmt , 5 ) = = SQLITE_NULL )
ci - > sig = NULL ;
else {
ci - > sig = tal ( ci , secp256k1_ecdsa_signature ) ;
sig_from_sql ( stmt , 5 , ci - > sig ) ;
}
/* Set once we have updated HTLCs. */
ci - > cstate = NULL ;
ci - > tx = NULL ;
}
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_commit_info:finalize gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
tal_free ( ctx ) ;
if ( ! peer - > local . commit )
fatal ( " load_peer_commit_info:no local commit info found " ) ;
if ( ! peer - > remote . commit )
fatal ( " load_peer_commit_info:no remote commit info found " ) ;
}
/* Because their HTLCs are not ordered wrt to ours, we can go negative
* and do normally - impossible things in intermediate states . So we
* mangle cstate balances manually . */
static void apply_htlc ( struct channel_state * cstate , const struct htlc * htlc ,
enum side side )
{
const char * sidestr = side_to_str ( side ) ;
if ( ! htlc_has ( htlc , HTLC_FLAG ( side , HTLC_F_WAS_COMMITTED ) ) )
return ;
log_debug ( htlc - > peer - > log , " %s committed " , sidestr ) ;
force_add_htlc ( cstate , htlc ) ;
if ( ! htlc_has ( htlc , HTLC_FLAG ( side , HTLC_F_COMMITTED ) ) ) {
log_debug ( htlc - > peer - > log , " %s %s " ,
sidestr , htlc - > r ? " resolved " : " failed " ) ;
if ( htlc - > r )
force_fulfill_htlc ( cstate , htlc ) ;
else
force_fail_htlc ( cstate , htlc ) ;
}
}
/* As we load the HTLCs, we apply them to get the final channel_state.
* We also get the last used htlc id .
* This is slow , but sure . */
static void load_peer_htlcs ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
const char * select ;
bool to_them_only , to_us_only ;
select = tal_fmt ( ctx ,
" SELECT * FROM htlcs WHERE peer = x'%s' ORDER BY id; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_htlcs:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
peer - > local . commit - > cstate = initial_cstate ( peer - > local . commit ,
peer - > anchor . satoshis ,
peer - > local . commit_fee_rate ,
peer - > local . offer_anchor ?
LOCAL : REMOTE ) ;
peer - > remote . commit - > cstate = initial_cstate ( peer - > remote . commit ,
peer - > anchor . satoshis ,
peer - > remote . commit_fee_rate ,
peer - > local . offer_anchor ?
LOCAL : REMOTE ) ;
/* We rebuild cstate by running *every* HTLC through. */
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct htlc * htlc ;
struct sha256 rhash ;
enum htlc_state hstate ;
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_htlcs:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 11 )
fatal ( " load_peer_htlcs:step gave %i cols, not 11 " ,
sqlite3_column_count ( stmt ) ) ;
sha256_from_sql ( stmt , 5 , & rhash ) ;
hstate = htlc_state_from_name ( sqlite3_column_str ( stmt , 2 ) ) ;
if ( hstate = = HTLC_STATE_INVALID )
fatal ( " load_peer_htlcs:invalid state %s " ,
sqlite3_column_str ( stmt , 2 ) ) ;
htlc = peer_new_htlc ( peer ,
sqlite3_column_int64 ( stmt , 1 ) ,
sqlite3_column_int64 ( stmt , 3 ) ,
& rhash ,
sqlite3_column_int64 ( stmt , 4 ) ,
sqlite3_column_blob ( stmt , 7 ) ,
sqlite3_column_bytes ( stmt , 7 ) ,
NULL ,
hstate ) ;
if ( sqlite3_column_type ( stmt , 6 ) ! = SQLITE_NULL ) {
htlc - > r = tal ( htlc , struct preimage ) ;
from_sql_blob ( stmt , 6 , htlc - > r , sizeof ( * htlc - > r ) ) ;
}
if ( sqlite3_column_type ( stmt , 10 ) ! = SQLITE_NULL ) {
htlc - > fail = tal_sql_blob ( htlc , stmt , 10 ) ;
}
if ( htlc - > r & & htlc - > fail )
fatal ( " %s HTLC % " PRIu64 " has failed and fulfilled? " ,
htlc_owner ( htlc ) = = LOCAL ? " local " : " remote " ,
htlc - > id ) ;
log_debug ( peer - > log , " Loaded %s HTLC % " PRIu64 " (%s) " ,
htlc_owner ( htlc ) = = LOCAL ? " local " : " remote " ,
htlc - > id , htlc_state_name ( htlc - > state ) ) ;
if ( htlc_owner ( htlc ) = = LOCAL
& & htlc - > id > = peer - > htlc_id_counter )
peer - > htlc_id_counter = htlc - > id + 1 ;
/* Update cstate with this HTLC. */
apply_htlc ( peer - > local . commit - > cstate , htlc , LOCAL ) ;
apply_htlc ( peer - > remote . commit - > cstate , htlc , REMOTE ) ;
}
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_htlcs:finalize gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
/* Now set any in-progress fee changes. */
select = tal_fmt ( ctx ,
" SELECT * FROM feechanges WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_htlcs:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
enum feechange_state feechange_state ;
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_htlcs:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 3 )
fatal ( " load_peer_htlcs:step gave %i cols, not 3 " ,
sqlite3_column_count ( stmt ) ) ;
feechange_state
= feechange_state_from_name ( sqlite3_column_str ( stmt , 1 ) ) ;
if ( feechange_state = = FEECHANGE_STATE_INVALID )
fatal ( " load_peer_htlcs:invalid feechange state %s " ,
sqlite3_column_str ( stmt , 1 ) ) ;
if ( peer - > feechanges [ feechange_state ] )
fatal ( " load_peer_htlcs: second feechange in state %s " ,
sqlite3_column_str ( stmt , 1 ) ) ;
peer - > feechanges [ feechange_state ]
= new_feechange ( peer , sqlite3_column_int64 ( stmt , 2 ) ,
feechange_state ) ;
}
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_htlcs:finalize gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( ! balance_after_force ( peer - > local . commit - > cstate )
| | ! balance_after_force ( peer - > remote . commit - > cstate ) )
fatal ( " load_peer_htlcs:channel didn't balance " ) ;
/* Update commit->tx and commit->map */
peer - > local . commit - > tx = create_commit_tx ( peer - > local . commit ,
peer ,
& peer - > local . commit - > revocation_hash ,
peer - > local . commit - > cstate ,
LOCAL , & to_them_only ) ;
bitcoin_txid ( peer - > local . commit - > tx , & peer - > local . commit - > txid ) ;
peer - > remote . commit - > tx = create_commit_tx ( peer - > remote . commit ,
peer ,
& peer - > remote . commit - > revocation_hash ,
peer - > remote . commit - > cstate ,
REMOTE , & to_us_only ) ;
bitcoin_txid ( peer - > remote . commit - > tx , & peer - > remote . commit - > txid ) ;
peer - > remote . staging_cstate = copy_cstate ( peer , peer - > remote . commit - > cstate ) ;
peer - > local . staging_cstate = copy_cstate ( peer , peer - > local . commit - > cstate ) ;
log_debug ( peer - > log , " Local staging: pay %u/%u fee %u/%u htlcs %u/%u " ,
peer - > local . staging_cstate - > side [ LOCAL ] . pay_msat ,
peer - > local . staging_cstate - > side [ REMOTE ] . pay_msat ,
peer - > local . staging_cstate - > side [ LOCAL ] . fee_msat ,
peer - > local . staging_cstate - > side [ REMOTE ] . fee_msat ,
peer - > local . staging_cstate - > side [ LOCAL ] . num_htlcs ,
peer - > local . staging_cstate - > side [ REMOTE ] . num_htlcs ) ;
log_debug ( peer - > log , " Remote staging: pay %u/%u fee %u/%u htlcs %u/%u " ,
peer - > remote . staging_cstate - > side [ LOCAL ] . pay_msat ,
peer - > remote . staging_cstate - > side [ REMOTE ] . pay_msat ,
peer - > remote . staging_cstate - > side [ LOCAL ] . fee_msat ,
peer - > remote . staging_cstate - > side [ REMOTE ] . fee_msat ,
peer - > remote . staging_cstate - > side [ LOCAL ] . num_htlcs ,
peer - > remote . staging_cstate - > side [ REMOTE ] . num_htlcs ) ;
tal_free ( ctx ) ;
}
/* FIXME: A real database person would do this in a single clause along
* with loading the htlcs in the first place ! */
static void connect_htlc_src ( struct lightningd_state * dstate )
{
sqlite3 * sql = dstate - > db - > sql ;
int err ;
sqlite3_stmt * stmt ;
char * ctx = tal_tmpctx ( dstate ) ;
const char * select ;
select = tal_fmt ( ctx ,
" SELECT peer,id,state,src_peer,src_id FROM htlcs WHERE src_peer IS NOT NULL AND state <> 'RCVD_REMOVE_ACK_REVOCATION' AND state <> 'SENT_REMOVE_ACK_REVOCATION'; " ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " connect_htlc_src:%s gave %s:%s " ,
select , sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct pubkey id ;
struct peer * peer ;
struct htlc * htlc ;
enum htlc_state s ;
if ( err ! = SQLITE_ROW )
fatal ( " connect_htlc_src:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
pubkey_from_sql ( stmt , 0 , & id ) ;
peer = find_peer ( dstate , & id ) ;
if ( ! peer )
continue ;
s = htlc_state_from_name ( sqlite3_column_str ( stmt , 2 ) ) ;
if ( s = = HTLC_STATE_INVALID )
fatal ( " connect_htlc_src:unknown state %s " ,
sqlite3_column_str ( stmt , 2 ) ) ;
htlc = htlc_get ( & peer - > htlcs , sqlite3_column_int64 ( stmt , 1 ) ,
htlc_state_owner ( s ) ) ;
if ( ! htlc )
fatal ( " connect_htlc_src:unknown htlc % " PRIuSQLITE64 " state %s " ,
sqlite3_column_int64 ( stmt , 1 ) ,
sqlite3_column_str ( stmt , 2 ) ) ;
pubkey_from_sql ( stmt , 4 , & id ) ;
peer = find_peer ( dstate , & id ) ;
if ( ! peer )
fatal ( " connect_htlc_src:unknown src peer %s " ,
tal_hexstr ( dstate , & id , sizeof ( id ) ) ) ;
/* Source must be a HTLC they offered. */
htlc - > src = htlc_get ( & peer - > htlcs ,
sqlite3_column_int64 ( stmt , 4 ) ,
REMOTE ) ;
if ( ! htlc - > src )
fatal ( " connect_htlc_src:unknown src htlc " ) ;
}
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_htlcs:finalize gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
tal_free ( ctx ) ;
}
static const char * linearize_shachain ( const tal_t * ctx ,
const struct shachain * shachain )
{
size_t i ;
u8 * p = tal_arr ( ctx , u8 , 0 ) ;
const char * str ;
push_le64 ( shachain - > min_index , push , & p ) ;
push_le32 ( shachain - > num_valid , push , & p ) ;
for ( i = 0 ; i < shachain - > num_valid ; i + + ) {
push_le64 ( shachain - > known [ i ] . index , push , & p ) ;
push ( & shachain - > known [ i ] . hash , sizeof ( shachain - > known [ i ] . hash ) ,
& p ) ;
}
for ( i = shachain - > num_valid ; i < ARRAY_SIZE ( shachain - > known ) ; i + + ) {
static u8 zeroes [ sizeof ( shachain - > known [ 0 ] . hash ) ] ;
push_le64 ( 0 , push , & p ) ;
push ( zeroes , sizeof ( zeroes ) , & p ) ;
}
assert ( tal_count ( p ) = = SHACHAIN_SIZE ) ;
str = tal_hex ( ctx , p ) ;
tal_free ( p ) ;
return str ;
}
static bool delinearize_shachain ( struct shachain * shachain ,
const void * data , size_t len )
{
size_t i ;
const u8 * p = data ;
shachain - > min_index = pull_le64 ( & p , & len ) ;
shachain - > num_valid = pull_le32 ( & p , & len ) ;
for ( i = 0 ; i < ARRAY_SIZE ( shachain - > known ) ; i + + ) {
shachain - > known [ i ] . index = pull_le64 ( & p , & len ) ;
pull ( & p , & len , & shachain - > known [ i ] . hash ,
sizeof ( shachain - > known [ i ] . hash ) ) ;
}
return p & & len = = 0 ;
}
static void load_peer_shachain ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
bool shachain_found = false ;
const char * select ;
select = tal_fmt ( ctx ,
" SELECT * FROM shachain WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_shachain:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
const char * hexstr ;
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_shachain:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
/* shachain (peer "SQL_PUBKEY", shachain BINARY(%zu) */
if ( sqlite3_column_count ( stmt ) ! = 2 )
fatal ( " load_peer_shachain:step gave %i cols, not 2 " ,
sqlite3_column_count ( stmt ) ) ;
if ( shachain_found )
fatal ( " load_peer_shachain:multiple shachains? " ) ;
hexstr = tal_hexstr ( ctx , sqlite3_column_blob ( stmt , 1 ) ,
sqlite3_column_bytes ( stmt , 1 ) ) ;
if ( ! delinearize_shachain ( & peer - > their_preimages ,
sqlite3_column_blob ( stmt , 1 ) ,
sqlite3_column_bytes ( stmt , 1 ) ) )
fatal ( " load_peer_shachain:invalid shachain %s " ,
hexstr ) ;
shachain_found = true ;
}
if ( ! shachain_found )
fatal ( " load_peer_shachain:no shachain " ) ;
tal_free ( ctx ) ;
}
/* We may not have one, and that's OK. */
static void load_peer_closing ( struct peer * peer )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = peer - > dstate - > db - > sql ;
char * ctx = tal_tmpctx ( peer ) ;
bool closing_found = false ;
const char * select ;
select = tal_fmt ( ctx ,
" SELECT * FROM closing WHERE peer = x'%s'; " ,
pubkey_to_hexstr ( ctx , peer - > id ) ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_closing:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_closing:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 9 )
fatal ( " load_peer_closing:step gave %i cols, not 9 " ,
sqlite3_column_count ( stmt ) ) ;
if ( closing_found )
fatal ( " load_peer_closing:multiple closing? " ) ;
peer - > closing . our_fee = sqlite3_column_int64 ( stmt , 1 ) ;
peer - > closing . their_fee = sqlite3_column_int64 ( stmt , 2 ) ;
if ( sqlite3_column_type ( stmt , 3 ) = = SQLITE_NULL )
peer - > closing . their_sig = NULL ;
else {
peer - > closing . their_sig = tal ( peer ,
secp256k1_ecdsa_signature ) ;
sig_from_sql ( stmt , 3 , peer - > closing . their_sig ) ;
}
peer - > closing . our_script = tal_sql_blob ( peer , stmt , 4 ) ;
peer - > closing . their_script = tal_sql_blob ( peer , stmt , 5 ) ;
peer - > closing . shutdown_order = sqlite3_column_int64 ( stmt , 6 ) ;
peer - > closing . closing_order = sqlite3_column_int64 ( stmt , 7 ) ;
peer - > closing . sigs_in = sqlite3_column_int64 ( stmt , 8 ) ;
closing_found = true ;
}
tal_free ( ctx ) ;
}
/* FIXME: much of this is redundant. */
static void restore_peer_local_visible_state ( struct peer * peer )
{
assert ( peer - > local . offer_anchor = = ! peer - > remote . offer_anchor ) ;
/* peer->local.commitkey and peer->local.finalkey set by
* peer_set_secrets_from_db ( ) . */
memcheck ( & peer - > local . commitkey , sizeof ( peer - > local . commitkey ) ) ;
memcheck ( & peer - > local . finalkey , sizeof ( peer - > local . finalkey ) ) ;
/* These set in new_peer */
memcheck ( & peer - > local . locktime , sizeof ( peer - > local . locktime ) ) ;
memcheck ( & peer - > local . mindepth , sizeof ( peer - > local . mindepth ) ) ;
/* This set in db_load_peers */
memcheck ( & peer - > local . commit_fee_rate ,
sizeof ( peer - > local . commit_fee_rate ) ) ;
peer_get_revocation_hash ( peer ,
peer - > local . commit - > commit_num + 1 ,
& peer - > local . next_revocation_hash ) ;
if ( state_is_normal ( peer - > state ) )
peer - > nc = add_connection ( peer - > dstate - > rstate ,
& peer - > dstate - > id , peer - > id ,
peer - > dstate - > config . fee_base ,
peer - > dstate - > config . fee_per_satoshi ,
peer - > dstate - > config . min_htlc_expiry ,
peer - > dstate - > config . min_htlc_expiry ) ;
peer - > their_commitsigs = peer - > local . commit - > commit_num + 1 ;
/* If they created anchor, they didn't send a sig for first commit */
if ( ! peer - > anchor . ours )
peer - > their_commitsigs - - ;
if ( peer - > local . commit - > order + 1 > peer - > order_counter )
peer - > order_counter = peer - > local . commit - > order + 1 ;
if ( peer - > remote . commit - > order + 1 > peer - > order_counter )
peer - > order_counter = peer - > remote . commit - > order + 1 ;
if ( peer - > closing . closing_order + 1 > peer - > order_counter )
peer - > order_counter = peer - > closing . closing_order + 1 ;
if ( peer - > closing . shutdown_order + 1 > peer - > order_counter )
peer - > order_counter = peer - > closing . shutdown_order + 1 ;
}
static void db_load_peers ( struct lightningd_state * dstate )
{
int err ;
sqlite3_stmt * stmt ;
struct peer * peer ;
err = sqlite3_prepare_v2 ( dstate - > db - > sql , " SELECT * FROM peers; " , - 1 ,
& stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " db_load_peers:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( dstate - > db - > sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
enum state state ;
struct log * l ;
struct pubkey id ;
const char * idstr ;
if ( err ! = SQLITE_ROW )
fatal ( " db_load_peers:step gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 4 )
fatal ( " db_load_peers:step gave %i cols, not 4 " ,
sqlite3_column_count ( stmt ) ) ;
state = name_to_state ( sqlite3_column_str ( stmt , 1 ) ) ;
if ( state = = STATE_MAX )
fatal ( " db_load_peers:unknown state %s " ,
sqlite3_column_str ( stmt , 1 ) ) ;
pubkey_from_sql ( stmt , 0 , & id ) ;
idstr = pubkey_to_hexstr ( dstate , & id ) ;
l = new_log ( dstate , dstate - > log_book , " %s: " , idstr ) ;
tal_free ( idstr ) ;
peer = new_peer ( dstate , l , state , sqlite3_column_int ( stmt , 2 ) ) ;
peer - > htlc_id_counter = 0 ;
peer - > id = tal_dup ( peer , struct pubkey , & id ) ;
peer - > local . commit_fee_rate = sqlite3_column_int64 ( stmt , 3 ) ;
peer - > order_counter = 1 ;
log_debug ( peer - > log , " %s:%s " ,
__func__ , state_name ( peer - > state ) ) ;
}
err = sqlite3_finalize ( stmt ) ;
if ( err ! = SQLITE_OK )
fatal ( " db_load_peers:finalize gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
list_for_each ( & dstate - > peers , peer , list ) {
load_peer_secrets ( peer ) ;
load_peer_closing ( peer ) ;
peer - > anchor . min_depth = 0 ;
if ( peer - > state > = STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE
& & ! state_is_error ( peer - > state ) ) {
load_peer_anchor ( peer ) ;
load_peer_visible_state ( peer ) ;
load_peer_shachain ( peer ) ;
load_peer_commit_info ( peer ) ;
load_peer_htlcs ( peer ) ;
restore_peer_local_visible_state ( peer ) ;
}
if ( peer - > local . offer_anchor )
load_peer_anchor_input ( peer ) ;
}
connect_htlc_src ( dstate ) ;
}
static const char * pubkeys_to_hex ( const tal_t * ctx , const struct pubkey * ids )
{
u8 * ders = tal_arr ( ctx , u8 , PUBKEY_DER_LEN * tal_count ( ids ) ) ;
size_t i ;
for ( i = 0 ; i < tal_count ( ids ) ; i + + )
pubkey_to_der ( ders + i * PUBKEY_DER_LEN , & ids [ i ] ) ;
return tal_hex ( ctx , ders ) ;
}
static struct pubkey * pubkeys_from_arr ( const tal_t * ctx ,
const void * blob , size_t len )
{
struct pubkey * ids ;
size_t i ;
if ( len % PUBKEY_DER_LEN )
fatal ( " ids array bad length %zu " , len ) ;
ids = tal_arr ( ctx , struct pubkey , len / PUBKEY_DER_LEN ) ;
for ( i = 0 ; i < tal_count ( ids ) ; i + + ) {
if ( ! pubkey_from_der ( blob , PUBKEY_DER_LEN , & ids [ i ] ) )
fatal ( " ids array invalid %zu " , i ) ;
blob = ( const u8 * ) blob + PUBKEY_DER_LEN ;
}
return ids ;
}
static void db_load_pay ( struct lightningd_state * dstate )
{
int err ;
sqlite3_stmt * stmt ;
char * ctx = tal_tmpctx ( dstate ) ;
err = sqlite3_prepare_v2 ( dstate - > db - > sql , " SELECT * FROM pay; " , - 1 ,
& stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " db_load_pay:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( dstate - > db - > sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct sha256 rhash ;
struct htlc * htlc ;
struct pubkey * peer_id ;
u64 htlc_id , msatoshi ;
struct pubkey * ids ;
struct preimage * r ;
void * fail ;
if ( err ! = SQLITE_ROW )
fatal ( " db_load_pay:step gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 7 )
fatal ( " db_load_pay:step gave %i cols, not 7 " ,
sqlite3_column_count ( stmt ) ) ;
sha256_from_sql ( stmt , 0 , & rhash ) ;
msatoshi = sqlite3_column_int64 ( stmt , 1 ) ;
ids = pubkeys_from_arr ( ctx ,
sqlite3_column_blob ( stmt , 2 ) ,
sqlite3_column_bytes ( stmt , 2 ) ) ;
if ( sqlite3_column_type ( stmt , 3 ) = = SQLITE_NULL )
peer_id = NULL ;
else {
peer_id = tal ( ctx , struct pubkey ) ;
pubkey_from_sql ( stmt , 3 , peer_id ) ;
}
htlc_id = sqlite3_column_int64 ( stmt , 4 ) ;
if ( sqlite3_column_type ( stmt , 5 ) = = SQLITE_NULL )
r = NULL ;
else {
r = tal ( ctx , struct preimage ) ;
from_sql_blob ( stmt , 5 , r , sizeof ( * r ) ) ;
}
fail = tal_sql_blob ( ctx , stmt , 6 ) ;
/* Exactly one of these must be set. */
if ( ! fail + ! peer_id + ! r ! = 2 )
fatal ( " db_load_pay: not exactly one set: "
" fail=%p peer_id=%p r=%p " ,
fail , peer_id , r ) ;
if ( peer_id ) {
struct peer * peer = find_peer ( dstate , peer_id ) ;
if ( ! peer )
fatal ( " db_load_pay: unknown peer " ) ;
htlc = htlc_get ( & peer - > htlcs , htlc_id , LOCAL ) ;
if ( ! htlc )
fatal ( " db_load_pay: unknown htlc " ) ;
} else
htlc = NULL ;
if ( ! pay_add ( dstate , & rhash , msatoshi , ids , htlc , fail , r ) )
fatal ( " db_load_pay: could not add pay " ) ;
}
tal_free ( ctx ) ;
}
static void db_load_invoice ( struct lightningd_state * dstate )
{
int err ;
sqlite3_stmt * stmt ;
char * ctx = tal_tmpctx ( dstate ) ;
err = sqlite3_prepare_v2 ( dstate - > db - > sql , " SELECT * FROM invoice; " , - 1 ,
& stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " db_load_invoice:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( dstate - > db - > sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct preimage r ;
u64 msatoshi , paid_num ;
const char * label ;
if ( err ! = SQLITE_ROW )
fatal ( " db_load_invoice:step gave %s:%s " ,
sqlite3_errstr ( err ) ,
sqlite3_errmsg ( dstate - > db - > sql ) ) ;
if ( sqlite3_column_count ( stmt ) ! = 4 )
fatal ( " db_load_invoice:step gave %i cols, not 4 " ,
sqlite3_column_count ( stmt ) ) ;
from_sql_blob ( stmt , 0 , & r , sizeof ( r ) ) ;
msatoshi = sqlite3_column_int64 ( stmt , 1 ) ;
label = ( const char * ) sqlite3_column_text ( stmt , 2 ) ;
paid_num = sqlite3_column_int64 ( stmt , 3 ) ;
invoice_add ( dstate - > invoices , & r , msatoshi , label , paid_num ) ;
}
tal_free ( ctx ) ;
}
static void db_load_addresses ( struct lightningd_state * dstate )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = dstate - > db - > sql ;
char * ctx = tal_tmpctx ( dstate ) ;
const char * select ;
select = tal_fmt ( ctx , " SELECT * FROM peer_address; " ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " load_peer_addresses:prepare gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
struct peer_address * addr ;
if ( err ! = SQLITE_ROW )
fatal ( " load_peer_addresses:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
addr = tal ( dstate , struct peer_address ) ;
pubkey_from_sql ( stmt , 0 , & addr - > id ) ;
if ( ! netaddr_from_blob ( sqlite3_column_blob ( stmt , 1 ) ,
sqlite3_column_bytes ( stmt , 1 ) ,
& addr - > addr ) )
fatal ( " load_peer_addresses: unparsable addresses for '%s' " ,
select ) ;
list_add_tail ( & dstate - > addresses , & addr - > list ) ;
log_debug ( dstate - > base_log , " load_peer_addresses:%s " ,
pubkey_to_hexstr ( ctx , & addr - > id ) ) ;
}
tal_free ( ctx ) ;
}
static void db_check_version ( struct lightningd_state * dstate )
{
int err ;
sqlite3_stmt * stmt ;
sqlite3 * sql = dstate - > db - > sql ;
char * ctx = tal_tmpctx ( dstate ) ;
const char * select ;
select = tal_fmt ( ctx , " SELECT * FROM version; " ) ;
err = sqlite3_prepare_v2 ( sql , select , - 1 , & stmt , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " DATABASE NEEDS UPDATE. Can't access VERSION: %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
while ( ( err = sqlite3_step ( stmt ) ) ! = SQLITE_DONE ) {
const char * ver ;
if ( err ! = SQLITE_ROW )
fatal ( " db_check_version:step gave %s:%s " ,
sqlite3_errstr ( err ) , sqlite3_errmsg ( sql ) ) ;
ver = sqlite3_column_str ( stmt , 0 ) ;
if ( ! streq ( ver , VERSION ) ) {
if ( dstate - > config . db_version_ignore )
log_unusual ( dstate - > base_log ,
" DATABASE NEEDS UPDATE. "
" Version %s does not match %s " ,
ver , VERSION ) ;
else
fatal ( " DATABASE NEEDS UPDATE. "
" Version %s does not match %s " ,
ver , VERSION ) ;
}
}
tal_free ( ctx ) ;
}
static void db_load ( struct lightningd_state * dstate )
{
db_check_version ( dstate ) ;
db_load_wallet ( dstate ) ;
db_load_addresses ( dstate ) ;
db_load_peers ( dstate ) ;
db_load_pay ( dstate ) ;
db_load_invoice ( dstate ) ;
}
void db_init ( struct lightningd_state * dstate )
{
int err ;
bool created = false ;
if ( SQLITE_VERSION_NUMBER ! = sqlite3_libversion_number ( ) )
fatal ( " SQLITE version mistmatch: compiled %u, now %u " ,
SQLITE_VERSION_NUMBER , sqlite3_libversion_number ( ) ) ;
dstate - > db = tal ( dstate , struct db ) ;
err = sqlite3_open_v2 ( DB_FILE , & dstate - > db - > sql ,
SQLITE_OPEN_READWRITE , NULL ) ;
if ( err ! = SQLITE_OK ) {
log_unusual ( dstate - > base_log ,
" Error opening %s (%s), trying to create " ,
DB_FILE , sqlite3_errstr ( err ) ) ;
err = sqlite3_open_v2 ( DB_FILE , & dstate - > db - > sql ,
SQLITE_OPEN_READWRITE
| SQLITE_OPEN_CREATE , NULL ) ;
if ( err ! = SQLITE_OK )
fatal ( " failed creating %s: %s " ,
DB_FILE , sqlite3_errstr ( err ) ) ;
created = true ;
}
tal_add_destructor ( dstate - > db , close_db ) ;
dstate - > db - > in_transaction = false ;
dstate - > db - > err = NULL ;
if ( ! created ) {
db_load ( dstate ) ;
return ;
}
/* Set up tables. */
dstate - > db - > in_transaction = true ;
db_exec ( __func__ , dstate , " BEGIN IMMEDIATE; " ) ;
db_exec ( __func__ , dstate ,
TABLE ( wallet ,
SQL_PRIVKEY ( privkey ) )
TABLE ( pay ,
SQL_RHASH ( rhash ) , SQL_U64 ( msatoshi ) ,
SQL_BLOB ( ids ) , SQL_PUBKEY ( htlc_peer ) ,
SQL_U64 ( htlc_id ) , SQL_R ( r ) , SQL_FAIL ( fail ) ,
" PRIMARY KEY(rhash) " )
TABLE ( invoice ,
SQL_R ( r ) , SQL_U64 ( msatoshi ) , SQL_INVLABEL ( label ) ,
SQL_U64 ( paid_num ) ,
" PRIMARY KEY(label) " )
TABLE ( anchor_inputs ,
SQL_PUBKEY ( peer ) ,
SQL_TXID ( txid ) , SQL_U32 ( idx ) ,
SQL_U64 ( in_amount ) , SQL_U64 ( out_amount ) ,
SQL_PUBKEY ( walletkey ) )
TABLE ( anchors ,
SQL_PUBKEY ( peer ) ,
SQL_TXID ( txid ) , SQL_U32 ( idx ) , SQL_U64 ( amount ) ,
SQL_U32 ( ok_depth ) , SQL_U32 ( min_depth ) ,
SQL_BOOL ( ours ) )
/* FIXME: state in key is overkill: just need side */
TABLE ( htlcs ,
SQL_PUBKEY ( peer ) , SQL_U64 ( id ) ,
SQL_STATENAME ( state ) , SQL_U64 ( msatoshi ) ,
SQL_U32 ( expiry ) , SQL_RHASH ( rhash ) , SQL_R ( r ) ,
SQL_ROUTING ( routing ) , SQL_PUBKEY ( src_peer ) ,
SQL_U64 ( src_id ) , SQL_BLOB ( fail ) ,
" PRIMARY KEY(peer, id, state) " )
TABLE ( feechanges ,
SQL_PUBKEY ( peer ) , SQL_STATENAME ( state ) ,
SQL_U32 ( fee_rate ) ,
" PRIMARY KEY(peer,state) " )
TABLE ( commit_info ,
SQL_PUBKEY ( peer ) , SQL_U32 ( side ) ,
SQL_U64 ( commit_num ) , SQL_SHA256 ( revocation_hash ) ,
SQL_U64 ( xmit_order ) , SQL_SIGNATURE ( sig ) ,
SQL_SHA256 ( prev_revocation_hash ) ,
" PRIMARY KEY(peer, side) " )
TABLE ( shachain ,
SQL_PUBKEY ( peer ) , SQL_SHACHAIN ( shachain ) ,
" PRIMARY KEY(peer) " )
TABLE ( their_visible_state ,
SQL_PUBKEY ( peer ) , SQL_BOOL ( offered_anchor ) ,
SQL_PUBKEY ( commitkey ) , SQL_PUBKEY ( finalkey ) ,
SQL_U32 ( locktime ) , SQL_U32 ( mindepth ) ,
SQL_U32 ( commit_fee_rate ) ,
SQL_SHA256 ( next_revocation_hash ) ,
" PRIMARY KEY(peer) " )
TABLE ( their_commitments ,
SQL_PUBKEY ( peer ) , SQL_SHA256 ( txid ) ,
SQL_U64 ( commit_num ) ,
" PRIMARY KEY(peer, txid) " )
TABLE ( peer_secrets ,
SQL_PUBKEY ( peer ) , SQL_PRIVKEY ( commitkey ) ,
SQL_PRIVKEY ( finalkey ) ,
SQL_SHA256 ( revocation_seed ) ,
" PRIMARY KEY(peer) " )
TABLE ( peer_address ,
SQL_PUBKEY ( peer ) , SQL_BLOB ( addr ) ,
" PRIMARY KEY(peer) " )
TABLE ( closing ,
SQL_PUBKEY ( peer ) , SQL_U64 ( our_fee ) ,
SQL_U64 ( their_fee ) , SQL_SIGNATURE ( their_sig ) ,
SQL_BLOB ( our_script ) , SQL_BLOB ( their_script ) ,
SQL_U64 ( shutdown_order ) , SQL_U64 ( closing_order ) ,
SQL_U64 ( sigs_in ) ,
" PRIMARY KEY(peer) " )
TABLE ( peers ,
SQL_PUBKEY ( peer ) , SQL_STATENAME ( state ) ,
SQL_BOOL ( offered_anchor ) , SQL_U32 ( our_feerate ) ,
" PRIMARY KEY(peer) " )
TABLE ( version , " version VARCHAR(100) " ) ) ;
db_exec ( __func__ , dstate , " INSERT INTO version VALUES (' " VERSION " '); " ) ;
db_exec ( __func__ , dstate , " COMMIT; " ) ;
dstate - > db - > in_transaction = false ;
if ( dstate - > db - > err ) {
unlink ( DB_FILE ) ;
fatal ( " %s " , dstate - > db - > err ) ;
}
}
void db_set_anchor ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid ;
assert ( peer - > dstate - > db - > in_transaction ) ;
peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO anchors VALUES (x'%s', x'%s', %u, % " PRIu64 " , %i, %u, %s); " ,
peerid ,
tal_hexstr ( ctx , & peer - > anchor . txid , sizeof ( peer - > anchor . txid ) ) ,
peer - > anchor . index ,
peer - > anchor . satoshis ,
peer - > anchor . ok_depth ,
peer - > anchor . min_depth ,
sql_bool ( peer - > anchor . ours ) ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO commit_info VALUES(x'%s', '%s', 0, x'%s', % " PRIi64 " , %s, NULL); " ,
peerid ,
side_to_str ( LOCAL ) ,
tal_hexstr ( ctx , & peer - > local . commit - > revocation_hash ,
sizeof ( peer - > local . commit - > revocation_hash ) ) ,
peer - > local . commit - > order ,
sig_to_sql ( ctx , peer - > local . commit - > sig ) ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO commit_info VALUES(x'%s', '%s', 0, x'%s', % " PRIi64 " , %s, NULL); " ,
peerid ,
side_to_str ( REMOTE ) ,
tal_hexstr ( ctx , & peer - > remote . commit - > revocation_hash ,
sizeof ( peer - > remote . commit - > revocation_hash ) ) ,
peer - > remote . commit - > order ,
sig_to_sql ( ctx , peer - > remote . commit - > sig ) ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO shachain VALUES (x'%s', x'%s'); " ,
peerid ,
linearize_shachain ( ctx , & peer - > their_preimages ) ) ;
tal_free ( ctx ) ;
}
void db_set_visible_state ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO their_visible_state VALUES (x'%s', %s, x'%s', x'%s', %u, %u, % " PRIu64 " , x'%s'); " ,
peerid ,
sql_bool ( peer - > remote . offer_anchor ) ,
pubkey_to_hexstr ( ctx , & peer - > remote . commitkey ) ,
pubkey_to_hexstr ( ctx , & peer - > remote . finalkey ) ,
peer - > remote . locktime . locktime ,
peer - > remote . mindepth ,
peer - > remote . commit_fee_rate ,
tal_hexstr ( ctx , & peer - > remote . next_revocation_hash ,
sizeof ( peer - > remote . next_revocation_hash ) ) ) ;
tal_free ( ctx ) ;
}
void db_update_next_revocation_hash ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s):%s " , __func__ , peerid ,
tal_hexstr ( ctx , & peer - > remote . next_revocation_hash ,
sizeof ( peer - > remote . next_revocation_hash ) ) ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE their_visible_state SET next_revocation_hash=x'%s' WHERE peer=x'%s'; " ,
tal_hexstr ( ctx , & peer - > remote . next_revocation_hash ,
sizeof ( peer - > remote . next_revocation_hash ) ) ,
peerid ) ;
tal_free ( ctx ) ;
}
void db_create_peer ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO peers VALUES (x'%s', '%s', %s, % " PRIi64 " ); " ,
peerid ,
state_name ( peer - > state ) ,
sql_bool ( peer - > local . offer_anchor ) ,
peer - > local . commit_fee_rate ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO peer_secrets VALUES (x'%s', %s); " ,
peerid , peer_secrets_for_db ( ctx , peer ) ) ;
if ( peer - > local . offer_anchor )
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO anchor_inputs VALUES "
" (x'%s', x'%s', %u, % " PRIi64 " , % " PRIi64 " , x'%s'); " ,
peerid ,
tal_hexstr ( ctx , & peer - > anchor . input - > txid ,
sizeof ( peer - > anchor . input - > txid ) ) ,
peer - > anchor . input - > index ,
peer - > anchor . input - > in_amount ,
peer - > anchor . input - > out_amount ,
pubkey_to_hexstr ( ctx , & peer - > anchor . input - > walletkey ) ) ;
tal_free ( ctx ) ;
}
void db_start_transaction ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( ! peer - > dstate - > db - > in_transaction ) ;
peer - > dstate - > db - > in_transaction = true ;
peer - > dstate - > db - > err = tal_free ( peer - > dstate - > db - > err ) ;
db_exec ( __func__ , peer - > dstate , " BEGIN IMMEDIATE; " ) ;
tal_free ( ctx ) ;
}
void db_abort_transaction ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
peer - > dstate - > db - > in_transaction = false ;
db_exec ( __func__ , peer - > dstate , " ROLLBACK; " ) ;
tal_free ( ctx ) ;
}
const char * db_commit_transaction ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
if ( ! db_exec ( __func__ , peer - > dstate , " COMMIT; " ) )
db_abort_transaction ( peer ) ;
else
peer - > dstate - > db - > in_transaction = false ;
tal_free ( ctx ) ;
return peer - > dstate - > db - > err ;
}
void db_new_htlc ( struct peer * peer , const struct htlc * htlc )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
if ( htlc - > src ) {
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO htlcs VALUES "
" (x'%s', % " PRIu64 " , '%s', % " PRIu64 " , %u, x'%s', NULL, x'%s', x'%s', % " PRIu64 " , NULL); " ,
pubkey_to_hexstr ( ctx , peer - > id ) ,
htlc - > id ,
htlc_state_name ( htlc - > state ) ,
htlc - > msatoshi ,
abs_locktime_to_blocks ( & htlc - > expiry ) ,
tal_hexstr ( ctx , & htlc - > rhash , sizeof ( htlc - > rhash ) ) ,
tal_hex ( ctx , htlc - > routing ) ,
peerid ,
htlc - > src - > id ) ;
} else {
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO htlcs VALUES "
" (x'%s', % " PRIu64 " , '%s', % " PRIu64 " , %u, x'%s', NULL, x'%s', NULL, NULL, NULL); " ,
peerid ,
htlc - > id ,
htlc_state_name ( htlc - > state ) ,
htlc - > msatoshi ,
abs_locktime_to_blocks ( & htlc - > expiry ) ,
tal_hexstr ( ctx , & htlc - > rhash , sizeof ( htlc - > rhash ) ) ,
tal_hex ( ctx , htlc - > routing ) ) ;
}
tal_free ( ctx ) ;
}
void db_new_feechange ( struct peer * peer , const struct feechange * feechange )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO feechanges VALUES "
" (x'%s', '%s', % " PRIu64 " ); " ,
peerid ,
feechange_state_name ( feechange - > state ) ,
feechange - > fee_rate ) ;
tal_free ( ctx ) ;
}
void db_update_htlc_state ( struct peer * peer , const struct htlc * htlc ,
enum htlc_state oldstate )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s): % " PRIu64 " %s->%s " , __func__ , peerid ,
htlc - > id , htlc_state_name ( oldstate ) ,
htlc_state_name ( htlc - > state ) ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE htlcs SET state='%s' WHERE peer=x'%s' AND id=% " PRIu64 " AND state='%s'; " ,
htlc_state_name ( htlc - > state ) , peerid ,
htlc - > id , htlc_state_name ( oldstate ) ) ;
tal_free ( ctx ) ;
}
void db_update_feechange_state ( struct peer * peer ,
const struct feechange * f ,
enum feechange_state oldstate )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s): %s->%s " , __func__ , peerid ,
feechange_state_name ( oldstate ) ,
feechange_state_name ( f - > state ) ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE feechanges SET state='%s' WHERE peer=x'%s' AND state='%s'; " ,
feechange_state_name ( f - > state ) , peerid ,
feechange_state_name ( oldstate ) ) ;
tal_free ( ctx ) ;
}
void db_remove_feechange ( struct peer * peer , const struct feechange * feechange ,
enum feechange_state oldstate )
{
const char * ctx = tal ( peer , char ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" DELETE FROM feechanges WHERE peer=x'%s' AND state='%s'; " ,
peerid , feechange_state_name ( oldstate ) ) ;
tal_free ( ctx ) ;
}
void db_update_state ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE peers SET state='%s' WHERE peer=x'%s'; " ,
state_name ( peer - > state ) , peerid ) ;
tal_free ( ctx ) ;
}
void db_htlc_fulfilled ( struct peer * peer , const struct htlc * htlc )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE htlcs SET r=x'%s' WHERE peer=x'%s' AND id=% " PRIu64 " AND state='%s'; " ,
tal_hexstr ( ctx , htlc - > r , sizeof ( * htlc - > r ) ) ,
peerid ,
htlc - > id ,
htlc_state_name ( htlc - > state ) ) ;
tal_free ( ctx ) ;
}
void db_htlc_failed ( struct peer * peer , const struct htlc * htlc )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE htlcs SET fail=x'%s' WHERE peer=x'%s' AND id=% " PRIu64 " AND state='%s'; " ,
tal_hexstr ( ctx , htlc - > fail , sizeof ( * htlc - > fail ) ) ,
peerid ,
htlc - > id ,
htlc_state_name ( htlc - > state ) ) ;
tal_free ( ctx ) ;
}
void db_new_commit_info ( struct peer * peer , enum side side ,
const struct sha256 * prev_rhash )
{
struct commit_info * ci ;
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
if ( side = = LOCAL ) {
ci = peer - > local . commit ;
} else {
ci = peer - > remote . commit ;
}
db_exec ( __func__ , peer - > dstate , " UPDATE commit_info SET commit_num=% " PRIu64 " , revocation_hash=x'%s', sig=%s, xmit_order=% " PRIi64 " , prev_revocation_hash=%s WHERE peer=x'%s' AND side='%s'; " ,
ci - > commit_num ,
tal_hexstr ( ctx , & ci - > revocation_hash ,
sizeof ( ci - > revocation_hash ) ) ,
sig_to_sql ( ctx , ci - > sig ) ,
ci - > order ,
sql_hex_or_null ( ctx , prev_rhash , sizeof ( * prev_rhash ) ) ,
peerid , side_to_str ( side ) ) ;
tal_free ( ctx ) ;
}
/* FIXME: Is this strictly necessary? */
void db_remove_their_prev_revocation_hash ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate , " UPDATE commit_info SET prev_revocation_hash=NULL WHERE peer=x'%s' AND side='REMOTE' and prev_revocation_hash IS NOT NULL; " ,
peerid ) ;
tal_free ( ctx ) ;
}
void db_save_shachain ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate , " UPDATE shachain SET shachain=x'%s' WHERE peer=x'%s'; " ,
linearize_shachain ( ctx , & peer - > their_preimages ) ,
peerid ) ;
tal_free ( ctx ) ;
}
void db_add_commit_map ( struct peer * peer ,
const struct sha256_double * txid , u64 commit_num )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s),commit_num=% " PRIu64 , __func__ , peerid ,
commit_num ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO their_commitments VALUES (x'%s', x'%s', % " PRIu64 " ); " ,
peerid ,
tal_hexstr ( ctx , txid , sizeof ( * txid ) ) ,
commit_num ) ;
tal_free ( ctx ) ;
}
/* FIXME: Clean out old ones! */
bool db_add_peer_address ( struct lightningd_state * dstate ,
const struct peer_address * addr )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
bool ok ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
assert ( ! dstate - > db - > in_transaction ) ;
ok = db_exec ( __func__ , dstate ,
" INSERT OR REPLACE INTO peer_address VALUES (x'%s', x'%s'); " ,
pubkey_to_hexstr ( ctx , & addr - > id ) ,
netaddr_to_hex ( ctx , & addr - > addr ) ) ;
tal_free ( ctx ) ;
return ok ;
}
void db_forget_peer ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
size_t i ;
const char * const tables [ ] = { " anchors " , " htlcs " , " commit_info " , " shachain " , " their_visible_state " , " their_commitments " , " peer_secrets " , " closing " , " peers " } ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > state = = STATE_CLOSED ) ;
db_start_transaction ( peer ) ;
for ( i = 0 ; i < ARRAY_SIZE ( tables ) ; i + + ) {
db_exec ( __func__ , peer - > dstate ,
" DELETE from %s WHERE peer=x'%s'; " ,
tables [ i ] , peerid ) ;
}
if ( db_commit_transaction ( peer ) ! = NULL )
fatal ( " %s:db_commi_transaction failed " , __func__ ) ;
tal_free ( ctx ) ;
}
void db_begin_shutdown ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" INSERT INTO closing VALUES (x'%s', 0, 0, NULL, NULL, NULL, 0, 0, 0); " ,
peerid ) ;
tal_free ( ctx ) ;
}
void db_set_our_closing_script ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate , " UPDATE closing SET our_script=x'%s',shutdown_order=% " PRIu64 " WHERE peer=x'%s'; " ,
tal_hex ( ctx , peer - > closing . our_script ) ,
peer - > closing . shutdown_order ,
peerid ) ;
tal_free ( ctx ) ;
}
void db_set_their_closing_script ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( peer - > dstate - > db - > in_transaction ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE closing SET their_script=x'%s' WHERE peer=x'%s'; " ,
tal_hex ( ctx , peer - > closing . their_script ) ,
peerid ) ;
tal_free ( ctx ) ;
}
/* For first time, we are in transaction to make it atomic with peer->state
* update . Later calls are not . */
/* FIXME: make caller wrap in transaction. */
void db_update_our_closing ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
db_exec ( __func__ , peer - > dstate ,
" UPDATE closing SET our_fee=% " PRIu64 " , closing_order=% " PRIi64 " WHERE peer=x'%s'; " ,
peer - > closing . our_fee ,
peer - > closing . closing_order ,
peerid ) ;
tal_free ( ctx ) ;
}
bool db_update_their_closing ( struct peer * peer )
{
const char * ctx = tal_tmpctx ( peer ) ;
bool ok ;
const char * peerid = pubkey_to_hexstr ( ctx , peer - > id ) ;
log_debug ( peer - > log , " %s(%s) " , __func__ , peerid ) ;
assert ( ! peer - > dstate - > db - > in_transaction ) ;
ok = db_exec ( __func__ , peer - > dstate ,
" UPDATE closing SET their_fee=% " PRIu64 " , their_sig=%s, sigs_in=%u WHERE peer=x'%s'; " ,
peer - > closing . their_fee ,
sig_to_sql ( ctx , peer - > closing . their_sig ) ,
peer - > closing . sigs_in ,
peerid ) ;
tal_free ( ctx ) ;
return ok ;
}
bool db_new_pay_command ( struct lightningd_state * dstate ,
const struct sha256 * rhash ,
const struct pubkey * ids ,
u64 msatoshi ,
const struct htlc * htlc )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
bool ok ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
log_add_struct ( dstate - > base_log , " (%s) " , struct sha256 , rhash ) ;
assert ( ! dstate - > db - > in_transaction ) ;
ok = db_exec ( __func__ , dstate ,
" INSERT INTO pay VALUES (x'%s', % " PRIu64 " , x'%s', x'%s', % " PRIu64 " , NULL, NULL); " ,
tal_hexstr ( ctx , rhash , sizeof ( * rhash ) ) ,
msatoshi ,
pubkeys_to_hex ( ctx , ids ) ,
pubkey_to_hexstr ( ctx , htlc - > peer - > id ) ,
htlc - > id ) ;
tal_free ( ctx ) ;
return ok ;
}
bool db_replace_pay_command ( struct lightningd_state * dstate ,
const struct sha256 * rhash ,
const struct pubkey * ids ,
u64 msatoshi ,
const struct htlc * htlc )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
bool ok ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
log_add_struct ( dstate - > base_log , " (%s) " , struct sha256 , rhash ) ;
assert ( ! dstate - > db - > in_transaction ) ;
ok = db_exec ( __func__ , dstate ,
" UPDATE pay SET msatoshi=% " PRIu64 " , ids=x'%s', htlc_peer=x'%s', htlc_id=% " PRIu64 " , r=NULL, fail=NULL WHERE rhash=x'%s'; " ,
msatoshi ,
pubkeys_to_hex ( ctx , ids ) ,
pubkey_to_hexstr ( ctx , htlc - > peer - > id ) ,
htlc - > id ,
tal_hexstr ( ctx , rhash , sizeof ( * rhash ) ) ) ;
tal_free ( ctx ) ;
return ok ;
}
void db_complete_pay_command ( struct lightningd_state * dstate ,
const struct htlc * htlc )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
log_add_struct ( dstate - > base_log , " (%s) " , struct sha256 , & htlc - > rhash ) ;
assert ( dstate - > db - > in_transaction ) ;
if ( htlc - > r )
db_exec ( __func__ , dstate ,
" UPDATE pay SET r=x'%s', htlc_peer=NULL WHERE rhash=x'%s'; " ,
tal_hexstr ( ctx , htlc - > r , sizeof ( * htlc - > r ) ) ,
tal_hexstr ( ctx , & htlc - > rhash , sizeof ( htlc - > rhash ) ) ) ;
else
db_exec ( __func__ , dstate ,
" UPDATE pay SET fail=x'%s', htlc_peer=NULL WHERE rhash=x'%s'; " ,
tal_hex ( ctx , htlc - > fail ) ,
tal_hexstr ( ctx , & htlc - > rhash , sizeof ( htlc - > rhash ) ) ) ;
tal_free ( ctx ) ;
}
bool db_new_invoice ( struct lightningd_state * dstate ,
u64 msatoshi ,
const char * label ,
const struct preimage * r )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
bool ok ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
assert ( ! dstate - > db - > in_transaction ) ;
/* Insert label as hex; suspect injection attacks. */
ok = db_exec ( __func__ , dstate ,
" INSERT INTO invoice VALUES (x'%s', % " PRIu64 " , x'%s', %s); " ,
tal_hexstr ( ctx , r , sizeof ( * r ) ) ,
msatoshi ,
tal_hexstr ( ctx , label , strlen ( label ) ) ,
sql_bool ( false ) ) ;
tal_free ( ctx ) ;
return ok ;
}
void db_resolve_invoice ( struct lightningd_state * dstate ,
const char * label , u64 paid_num )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
assert ( dstate - > db - > in_transaction ) ;
db_exec ( __func__ , dstate , " UPDATE invoice SET paid_num=% " PRIu64 " WHERE label=x'%s'; " ,
paid_num , tal_hexstr ( ctx , label , strlen ( label ) ) ) ;
tal_free ( ctx ) ;
}
bool db_remove_invoice ( struct lightningd_state * dstate ,
const char * label )
{
const tal_t * ctx = tal_tmpctx ( dstate ) ;
bool ok ;
log_debug ( dstate - > base_log , " %s " , __func__ ) ;
assert ( ! dstate - > db - > in_transaction ) ;
ok = db_exec ( __func__ , dstate , " DELETE FROM invoice WHERE label=x'%s'; " ,
tal_hexstr ( ctx , label , strlen ( label ) ) ) ;
tal_free ( ctx ) ;
return ok ;
}