core-lightning/wallet/test/run-wallet.c
Rusty Russell a2c6ec6c9b lightningd: use tal_link for log_book.
BackgroundL Each log has a log_book: many logs can share the same one,
as each one can have a separate prefix.

Testing tickled a bug at the end of this series, where subd was
logging to the peer's log_book on shutdown, but the peer was already
freed.  We've already had issues with logging while lightningd is
shutting down.

There are times when reference counting really is the right answer,
this seems to be one of them: the 'struct log' share the 'struct
log_book' and the last 'struct log' cleans it up.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2018-02-19 02:56:51 +00:00

1163 lines
58 KiB
C

#include <lightningd/log.h>
static void wallet_fatal(const char *fmt, ...);
#define fatal wallet_fatal
#include "test_utils.h"
static void db_log_(struct log *log, enum log_level level, const char *fmt, ...)
{
}
#define log_ db_log_
#include "wallet/wallet.c"
#include "lightningd/htlc_end.c"
#include "lightningd/peer_control.c"
#include "lightningd/channel.c"
#include "wallet/db.c"
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <ccan/structeq/structeq.h>
#include <common/memleak.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
bool deprecated_apis = true;
/* AUTOGENERATED MOCKS START */
/* Generated stub for bip32_pubkey */
bool bip32_pubkey(const struct ext_key *bip32_base UNNEEDED,
struct pubkey *pubkey UNNEEDED, u32 index UNNEEDED)
{ fprintf(stderr, "bip32_pubkey called!\n"); abort(); }
/* Generated stub for bitcoind_gettxout */
void bitcoind_gettxout(struct bitcoind *bitcoind UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED, const u32 outnum UNNEEDED,
void (*cb)(struct bitcoind *bitcoind UNNEEDED,
const struct bitcoin_tx_output *txout UNNEEDED,
void *arg) UNNEEDED,
void *arg UNNEEDED)
{ fprintf(stderr, "bitcoind_gettxout called!\n"); abort(); }
/* Generated stub for broadcast_tx */
void broadcast_tx(struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED,
void (*failed)(struct channel *channel UNNEEDED,
int exitstatus UNNEEDED,
const char *err))
{ fprintf(stderr, "broadcast_tx called!\n"); abort(); }
/* Generated stub for build_utxos */
const struct utxo **build_utxos(const tal_t *ctx UNNEEDED,
struct lightningd *ld UNNEEDED, u64 satoshi_out UNNEEDED,
u32 feerate_per_kw UNNEEDED, u64 dust_limit UNNEEDED,
size_t outputscriptlen UNNEEDED,
u64 *change_satoshis UNNEEDED, u32 *change_keyindex UNNEEDED)
{ fprintf(stderr, "build_utxos called!\n"); abort(); }
/* Generated stub for channel_wire_type_name */
const char *channel_wire_type_name(int e UNNEEDED)
{ fprintf(stderr, "channel_wire_type_name called!\n"); abort(); }
/* Generated stub for closing_wire_type_name */
const char *closing_wire_type_name(int e UNNEEDED)
{ fprintf(stderr, "closing_wire_type_name called!\n"); abort(); }
/* Generated stub for command_fail */
void command_fail(struct command *cmd UNNEEDED, const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail called!\n"); abort(); }
/* Generated stub for command_still_pending */
void command_still_pending(struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_still_pending called!\n"); abort(); }
/* Generated stub for command_success */
void command_success(struct command *cmd UNNEEDED, struct json_result *response UNNEEDED)
{ fprintf(stderr, "command_success called!\n"); abort(); }
/* Generated stub for derive_basepoints */
bool derive_basepoints(const struct privkey *seed UNNEEDED,
struct pubkey *funding_pubkey UNNEEDED,
struct basepoints *basepoints UNNEEDED,
struct secrets *secrets UNNEEDED,
struct sha256 *shaseed UNNEEDED)
{ fprintf(stderr, "derive_basepoints called!\n"); abort(); }
/* Generated stub for extract_channel_id */
bool extract_channel_id(const u8 *in_pkt UNNEEDED, struct channel_id *channel_id UNNEEDED)
{ fprintf(stderr, "extract_channel_id called!\n"); abort(); }
/* Generated stub for find_htlc_out_by_ripemd */
struct htlc_out *find_htlc_out_by_ripemd(const struct channel *channel UNNEEDED,
const struct ripemd160 *ripemd160 UNNEEDED)
{ fprintf(stderr, "find_htlc_out_by_ripemd called!\n"); abort(); }
/* Generated stub for find_txwatch */
struct txwatch *find_txwatch(struct chain_topology *topo UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
const struct channel *channel UNNEEDED)
{ fprintf(stderr, "find_txwatch called!\n"); abort(); }
/* Generated stub for fromwire_channel_got_funding_locked */
bool fromwire_channel_got_funding_locked(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED)
{ fprintf(stderr, "fromwire_channel_got_funding_locked called!\n"); abort(); }
/* Generated stub for fromwire_channel_got_shutdown */
bool fromwire_channel_got_shutdown(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, u8 **scriptpubkey UNNEEDED)
{ fprintf(stderr, "fromwire_channel_got_shutdown called!\n"); abort(); }
/* Generated stub for fromwire_channel_shutdown_complete */
bool fromwire_channel_shutdown_complete(const void *p UNNEEDED, size_t *plen UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED)
{ fprintf(stderr, "fromwire_channel_shutdown_complete called!\n"); abort(); }
/* Generated stub for fromwire_closing_complete */
bool fromwire_closing_complete(const void *p UNNEEDED, size_t *plen UNNEEDED, u64 *gossip_index UNNEEDED)
{ fprintf(stderr, "fromwire_closing_complete called!\n"); abort(); }
/* Generated stub for fromwire_closing_received_signature */
bool fromwire_closing_received_signature(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_tx **tx UNNEEDED)
{ fprintf(stderr, "fromwire_closing_received_signature called!\n"); abort(); }
/* Generated stub for fromwire_gossipctl_release_peer_reply */
bool fromwire_gossipctl_release_peer_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct wireaddr *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED)
{ fprintf(stderr, "fromwire_gossipctl_release_peer_reply called!\n"); abort(); }
/* Generated stub for fromwire_gossipctl_release_peer_replyfail */
bool fromwire_gossipctl_release_peer_replyfail(const void *p UNNEEDED, size_t *plen UNNEEDED)
{ fprintf(stderr, "fromwire_gossipctl_release_peer_replyfail called!\n"); abort(); }
/* Generated stub for fromwire_gossip_getpeers_reply */
bool fromwire_gossip_getpeers_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey **id UNNEEDED, struct wireaddr **addr UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_getpeers_reply called!\n"); abort(); }
/* Generated stub for fromwire_gossip_peer_already_connected */
bool fromwire_gossip_peer_already_connected(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_peer_already_connected called!\n"); abort(); }
/* Generated stub for fromwire_gossip_peer_connected */
bool fromwire_gossip_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_peer_connected called!\n"); abort(); }
/* Generated stub for fromwire_gossip_peer_connection_failed */
bool fromwire_gossip_peer_connection_failed(const void *p UNNEEDED, size_t *plen UNNEEDED, struct pubkey *id UNNEEDED, u32 *timeout UNNEEDED, u32 *attempts UNNEEDED, bool *addr_unknown UNNEEDED)
{ fprintf(stderr, "fromwire_gossip_peer_connection_failed called!\n"); abort(); }
/* Generated stub for fromwire_hsm_client_hsmfd_reply */
bool fromwire_hsm_client_hsmfd_reply(const void *p UNNEEDED, size_t *plen UNNEEDED)
{ fprintf(stderr, "fromwire_hsm_client_hsmfd_reply called!\n"); abort(); }
/* Generated stub for fromwire_hsm_sign_funding_reply */
bool fromwire_hsm_sign_funding_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_tx **tx UNNEEDED)
{ fprintf(stderr, "fromwire_hsm_sign_funding_reply called!\n"); abort(); }
/* Generated stub for fromwire_onchain_add_utxo */
bool fromwire_onchain_add_utxo(const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_txid *prev_out_tx UNNEEDED, u32 *prev_out_index UNNEEDED, struct pubkey *per_commit_point UNNEEDED, u64 *value UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_add_utxo called!\n"); abort(); }
/* Generated stub for fromwire_onchain_broadcast_tx */
bool fromwire_onchain_broadcast_tx(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_tx **tx UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_broadcast_tx called!\n"); abort(); }
/* Generated stub for fromwire_onchain_extracted_preimage */
bool fromwire_onchain_extracted_preimage(const void *p UNNEEDED, size_t *plen UNNEEDED, struct preimage *preimage UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_extracted_preimage called!\n"); abort(); }
/* Generated stub for fromwire_onchain_htlc_timeout */
bool fromwire_onchain_htlc_timeout(const void *p UNNEEDED, size_t *plen UNNEEDED, struct htlc_stub *htlc UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_htlc_timeout called!\n"); abort(); }
/* Generated stub for fromwire_onchain_init_reply */
bool fromwire_onchain_init_reply(const void *p UNNEEDED, size_t *plen UNNEEDED, u8 *state UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_init_reply called!\n"); abort(); }
/* Generated stub for fromwire_onchain_missing_htlc_output */
bool fromwire_onchain_missing_htlc_output(const void *p UNNEEDED, size_t *plen UNNEEDED, struct htlc_stub *htlc UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_missing_htlc_output called!\n"); abort(); }
/* Generated stub for fromwire_onchain_unwatch_tx */
bool fromwire_onchain_unwatch_tx(const void *p UNNEEDED, size_t *plen UNNEEDED, struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "fromwire_onchain_unwatch_tx called!\n"); abort(); }
/* Generated stub for fromwire_opening_fundee_reply */
bool fromwire_opening_fundee_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct channel_config *their_config UNNEEDED, struct bitcoin_tx **first_commit UNNEEDED, secp256k1_ecdsa_signature *first_commit_sig UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, struct pubkey *revocation_basepoint UNNEEDED, struct pubkey *payment_basepoint UNNEEDED, struct pubkey *htlc_basepoint UNNEEDED, struct pubkey *delayed_payment_basepoint UNNEEDED, struct pubkey *their_per_commit_point UNNEEDED, struct pubkey *remote_fundingkey UNNEEDED, struct bitcoin_txid *funding_txid UNNEEDED, u16 *funding_txout UNNEEDED, u64 *funding_satoshis UNNEEDED, u64 *push_msat UNNEEDED, u8 *channel_flags UNNEEDED, u32 *feerate_per_kw UNNEEDED, u8 **funding_signed_msg UNNEEDED)
{ fprintf(stderr, "fromwire_opening_fundee_reply called!\n"); abort(); }
/* Generated stub for fromwire_opening_funder_reply */
bool fromwire_opening_funder_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct channel_config *their_config UNNEEDED, struct bitcoin_tx **first_commit UNNEEDED, secp256k1_ecdsa_signature *first_commit_sig UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, struct pubkey *revocation_basepoint UNNEEDED, struct pubkey *payment_basepoint UNNEEDED, struct pubkey *htlc_basepoint UNNEEDED, struct pubkey *delayed_payment_basepoint UNNEEDED, struct pubkey *their_per_commit_point UNNEEDED, u32 *minimum_depth UNNEEDED, struct pubkey *remote_fundingkey UNNEEDED, struct bitcoin_txid *funding_txid UNNEEDED, u32 *feerate_per_kw UNNEEDED)
{ fprintf(stderr, "fromwire_opening_funder_reply called!\n"); abort(); }
/* Generated stub for fromwire_opening_negotiation_failed */
bool fromwire_opening_negotiation_failed(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u64 *gossip_index UNNEEDED, wirestring **msg UNNEEDED)
{ fprintf(stderr, "fromwire_opening_negotiation_failed called!\n"); abort(); }
/* Generated stub for funding_tx */
struct bitcoin_tx *funding_tx(const tal_t *ctx UNNEEDED,
u16 *outnum UNNEEDED,
const struct utxo **utxomap UNNEEDED,
u64 funding_satoshis UNNEEDED,
const struct pubkey *local_fundingkey UNNEEDED,
const struct pubkey *remote_fundingkey UNNEEDED,
u64 change_satoshis UNNEEDED,
const struct pubkey *changekey UNNEEDED,
const struct ext_key *bip32_base UNNEEDED)
{ fprintf(stderr, "funding_tx called!\n"); abort(); }
/* Generated stub for get_block_height */
u32 get_block_height(const struct chain_topology *topo UNNEEDED)
{ fprintf(stderr, "get_block_height called!\n"); abort(); }
/* Generated stub for get_chainparams */
struct chainparams *get_chainparams(const struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "get_chainparams called!\n"); abort(); }
/* Generated stub for get_feerate */
u32 get_feerate(const struct chain_topology *topo UNNEEDED, enum feerate feerate UNNEEDED)
{ fprintf(stderr, "get_feerate called!\n"); abort(); }
/* Generated stub for get_supported_global_features */
u8 *get_supported_global_features(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "get_supported_global_features called!\n"); abort(); }
/* Generated stub for get_supported_local_features */
u8 *get_supported_local_features(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "get_supported_local_features called!\n"); abort(); }
/* Generated stub for hsm_sync_read */
u8 *hsm_sync_read(const tal_t *ctx UNNEEDED, struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "hsm_sync_read called!\n"); abort(); }
/* Generated stub for invoices_create */
const struct invoice *invoices_create(struct invoices *invoices UNNEEDED,
u64 *msatoshi TAKES UNNEEDED,
const char *label TAKES UNNEEDED,
u64 expiry UNNEEDED)
{ fprintf(stderr, "invoices_create called!\n"); abort(); }
/* Generated stub for invoices_delete */
bool invoices_delete(struct invoices *invoices UNNEEDED,
const struct invoice *invoice UNNEEDED)
{ fprintf(stderr, "invoices_delete called!\n"); abort(); }
/* Generated stub for invoices_find_by_label */
const struct invoice *invoices_find_by_label(struct invoices *invoices UNNEEDED,
const char *label UNNEEDED)
{ fprintf(stderr, "invoices_find_by_label called!\n"); abort(); }
/* Generated stub for invoices_find_unpaid */
const struct invoice *invoices_find_unpaid(struct invoices *invoices UNNEEDED,
const struct sha256 *rhash UNNEEDED)
{ fprintf(stderr, "invoices_find_unpaid called!\n"); abort(); }
/* Generated stub for invoices_iterate */
const struct invoice *invoices_iterate(struct invoices *invoices UNNEEDED,
const struct invoice *invoice UNNEEDED)
{ fprintf(stderr, "invoices_iterate called!\n"); abort(); }
/* Generated stub for invoices_load */
bool invoices_load(struct invoices *invoices UNNEEDED)
{ fprintf(stderr, "invoices_load called!\n"); abort(); }
/* Generated stub for invoices_new */
struct invoices *invoices_new(const tal_t *ctx UNNEEDED,
struct db *db UNNEEDED,
struct log *log UNNEEDED,
struct timers *timers UNNEEDED)
{ fprintf(stderr, "invoices_new called!\n"); abort(); }
/* Generated stub for invoices_resolve */
void invoices_resolve(struct invoices *invoices UNNEEDED,
const struct invoice *invoice UNNEEDED,
u64 msatoshi_received UNNEEDED)
{ fprintf(stderr, "invoices_resolve called!\n"); abort(); }
/* Generated stub for invoices_waitany */
void invoices_waitany(const tal_t *ctx UNNEEDED,
struct invoices *invoices UNNEEDED,
u64 lastpay_index UNNEEDED,
void (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED,
void *cbarg UNNEEDED)
{ fprintf(stderr, "invoices_waitany called!\n"); abort(); }
/* Generated stub for invoices_waitone */
void invoices_waitone(const tal_t *ctx UNNEEDED,
struct invoices *invoices UNNEEDED,
struct invoice const *invoice UNNEEDED,
void (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED,
void *cbarg UNNEEDED)
{ fprintf(stderr, "invoices_waitone called!\n"); abort(); }
/* Generated stub for json_add_bool */
void json_add_bool(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED,
bool value UNNEEDED)
{ fprintf(stderr, "json_add_bool called!\n"); abort(); }
/* Generated stub for json_add_hex */
void json_add_hex(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED,
const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "json_add_hex called!\n"); abort(); }
/* Generated stub for json_add_log */
void json_add_log(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED,
const struct log_book *lr UNNEEDED, enum log_level minlevel UNNEEDED)
{ fprintf(stderr, "json_add_log called!\n"); abort(); }
/* Generated stub for json_add_num */
void json_add_num(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED,
unsigned int value UNNEEDED)
{ fprintf(stderr, "json_add_num called!\n"); abort(); }
/* Generated stub for json_add_pubkey */
void json_add_pubkey(struct json_result *response UNNEEDED,
const char *fieldname UNNEEDED,
const struct pubkey *key UNNEEDED)
{ fprintf(stderr, "json_add_pubkey called!\n"); abort(); }
/* Generated stub for json_add_short_channel_id */
void json_add_short_channel_id(struct json_result *response UNNEEDED,
const char *fieldname UNNEEDED,
const struct short_channel_id *id UNNEEDED)
{ fprintf(stderr, "json_add_short_channel_id called!\n"); abort(); }
/* Generated stub for json_add_string */
void json_add_string(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED, const char *value UNNEEDED)
{ fprintf(stderr, "json_add_string called!\n"); abort(); }
/* Generated stub for json_add_txid */
void json_add_txid(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "json_add_txid called!\n"); abort(); }
/* Generated stub for json_add_u64 */
void json_add_u64(struct json_result *result UNNEEDED, const char *fieldname UNNEEDED,
uint64_t value UNNEEDED)
{ fprintf(stderr, "json_add_u64 called!\n"); abort(); }
/* Generated stub for json_array_end */
void json_array_end(struct json_result *ptr UNNEEDED)
{ fprintf(stderr, "json_array_end called!\n"); abort(); }
/* Generated stub for json_array_start */
void json_array_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_array_start called!\n"); abort(); }
/* Generated stub for json_get_params */
bool json_get_params(struct command *cmd UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t param[] UNNEEDED, ...)
{ fprintf(stderr, "json_get_params called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_result *ptr UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for json_tok_bool */
bool json_tok_bool(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, bool *b UNNEEDED)
{ fprintf(stderr, "json_tok_bool called!\n"); abort(); }
/* Generated stub for json_tok_loglevel */
bool json_tok_loglevel(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
enum log_level *level UNNEEDED)
{ fprintf(stderr, "json_tok_loglevel called!\n"); abort(); }
/* Generated stub for json_tok_number */
bool json_tok_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
unsigned int *num UNNEEDED)
{ fprintf(stderr, "json_tok_number called!\n"); abort(); }
/* Generated stub for json_tok_pubkey */
bool json_tok_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
{ fprintf(stderr, "json_tok_pubkey called!\n"); abort(); }
/* Generated stub for json_tok_short_channel_id */
bool json_tok_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "json_tok_short_channel_id called!\n"); abort(); }
/* Generated stub for json_tok_u64 */
bool json_tok_u64(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint64_t *num UNNEEDED)
{ fprintf(stderr, "json_tok_u64 called!\n"); abort(); }
/* Generated stub for locate_tx */
struct txlocator *locate_tx(const void *ctx UNNEEDED, const struct chain_topology *topo UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "locate_tx called!\n"); abort(); }
/* Generated stub for log_add */
void log_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "log_add called!\n"); abort(); }
/* Generated stub for log_io */
void log_io(struct log *log UNNEEDED, enum log_level dir UNNEEDED, const char *comment UNNEEDED,
const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "log_io called!\n"); abort(); }
/* Generated stub for logv_add */
void logv_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, va_list ap UNNEEDED)
{ fprintf(stderr, "logv_add called!\n"); abort(); }
/* Generated stub for new_channel_subd */
struct subd *new_channel_subd(struct lightningd *ld UNNEEDED,
const char *name UNNEEDED,
struct channel *channel UNNEEDED,
const char *(*msgname)(int msgtype) UNNEEDED,
unsigned int (*msgcb)(struct subd * UNNEEDED, const u8 * UNNEEDED,
const int *fds) UNNEEDED,
...)
{ fprintf(stderr, "new_channel_subd called!\n"); abort(); }
/* Generated stub for new_json_result */
struct json_result *new_json_result(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "new_json_result called!\n"); abort(); }
/* Generated stub for null_response */
struct json_result *null_response(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "null_response called!\n"); abort(); }
/* Generated stub for onchain_failed_our_htlc */
void onchain_failed_our_htlc(const struct channel *channel UNNEEDED,
const struct htlc_stub *htlc UNNEEDED,
const char *why UNNEEDED)
{ fprintf(stderr, "onchain_failed_our_htlc called!\n"); abort(); }
/* Generated stub for onchain_fulfilled_htlc */
void onchain_fulfilled_htlc(struct channel *channel UNNEEDED,
const struct preimage *preimage UNNEEDED)
{ fprintf(stderr, "onchain_fulfilled_htlc called!\n"); abort(); }
/* Generated stub for onchain_wire_type_name */
const char *onchain_wire_type_name(int e UNNEEDED)
{ fprintf(stderr, "onchain_wire_type_name called!\n"); abort(); }
/* Generated stub for opening_wire_type_name */
const char *opening_wire_type_name(int e UNNEEDED)
{ fprintf(stderr, "opening_wire_type_name called!\n"); abort(); }
/* Generated stub for peer_got_commitsig */
void peer_got_commitsig(struct channel *channel UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "peer_got_commitsig called!\n"); abort(); }
/* Generated stub for peer_got_revoke */
void peer_got_revoke(struct channel *channel UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "peer_got_revoke called!\n"); abort(); }
/* Generated stub for peer_htlcs */
void peer_htlcs(const tal_t *ctx UNNEEDED,
const struct channel *channel UNNEEDED,
struct added_htlc **htlcs UNNEEDED,
enum htlc_state **htlc_states UNNEEDED,
struct fulfilled_htlc **fulfilled_htlcs UNNEEDED,
enum side **fulfilled_sides UNNEEDED,
const struct failed_htlc ***failed_htlcs UNNEEDED,
enum side **failed_sides UNNEEDED)
{ fprintf(stderr, "peer_htlcs called!\n"); abort(); }
/* Generated stub for peer_sending_commitsig */
void peer_sending_commitsig(struct channel *channel UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "peer_sending_commitsig called!\n"); abort(); }
/* Generated stub for sanitize_error */
char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED,
struct channel_id *channel_id UNNEEDED)
{ fprintf(stderr, "sanitize_error called!\n"); abort(); }
/* Generated stub for subd_release_channel */
void subd_release_channel(struct subd *owner UNNEEDED, struct channel *channel UNNEEDED)
{ fprintf(stderr, "subd_release_channel called!\n"); abort(); }
/* Generated stub for subd_req_ */
void subd_req_(const tal_t *ctx UNNEEDED,
struct subd *sd UNNEEDED,
const u8 *msg_out UNNEEDED,
int fd_out UNNEEDED, size_t num_fds_in UNNEEDED,
void (*replycb)(struct subd * UNNEEDED, const u8 * UNNEEDED, const int * UNNEEDED, void *) UNNEEDED,
void *replycb_data UNNEEDED)
{ fprintf(stderr, "subd_req_ called!\n"); abort(); }
/* Generated stub for subd_send_fd */
void subd_send_fd(struct subd *sd UNNEEDED, int fd UNNEEDED)
{ fprintf(stderr, "subd_send_fd called!\n"); abort(); }
/* Generated stub for subd_send_msg */
void subd_send_msg(struct subd *sd UNNEEDED, const u8 *msg_out UNNEEDED)
{ fprintf(stderr, "subd_send_msg called!\n"); abort(); }
/* Generated stub for towire_channel_dev_reenable_commit */
u8 *towire_channel_dev_reenable_commit(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_channel_dev_reenable_commit called!\n"); abort(); }
/* Generated stub for towire_channel_funding_announce_depth */
u8 *towire_channel_funding_announce_depth(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_channel_funding_announce_depth called!\n"); abort(); }
/* Generated stub for towire_channel_funding_locked */
u8 *towire_channel_funding_locked(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED)
{ fprintf(stderr, "towire_channel_funding_locked called!\n"); abort(); }
/* Generated stub for towire_channel_init */
u8 *towire_channel_init(const tal_t *ctx UNNEEDED, const struct bitcoin_blkid *chain_hash UNNEEDED, const struct bitcoin_txid *funding_txid UNNEEDED, u16 funding_txout UNNEEDED, u64 funding_satoshi UNNEEDED, const struct channel_config *our_config UNNEEDED, const struct channel_config *their_config UNNEEDED, const u32 feerate_per_kw[2] UNNEEDED, u32 feerate_min UNNEEDED, u32 feerate_max UNNEEDED, const secp256k1_ecdsa_signature *first_commit_sig UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct pubkey *remote_fundingkey UNNEEDED, const struct pubkey *remote_revocation_basepoint UNNEEDED, const struct pubkey *remote_payment_basepoint UNNEEDED, const struct pubkey *remote_htlc_basepoint UNNEEDED, const struct pubkey *remote_delayed_payment_basepoint UNNEEDED, const struct pubkey *remote_per_commit UNNEEDED, const struct pubkey *old_remote_per_commit UNNEEDED, enum side funder UNNEEDED, u32 fee_base UNNEEDED, u32 fee_proportional UNNEEDED, u64 local_msatoshi UNNEEDED, const struct privkey *seed UNNEEDED, const struct pubkey *local_node_id UNNEEDED, const struct pubkey *remote_node_id UNNEEDED, u32 commit_msec UNNEEDED, u16 cltv_delta UNNEEDED, bool last_was_revoke UNNEEDED, const struct changed_htlc *last_sent_commit UNNEEDED, u64 next_index_local UNNEEDED, u64 next_index_remote UNNEEDED, u64 revocations_received UNNEEDED, u64 next_htlc_id UNNEEDED, const struct added_htlc *htlcs UNNEEDED, const enum htlc_state *htlc_states UNNEEDED, const struct fulfilled_htlc *fulfilled UNNEEDED, const enum side *fulfilled_sides UNNEEDED, const struct failed_htlc **failed UNNEEDED, const enum side *failed_sides UNNEEDED, bool local_funding_locked UNNEEDED, bool remote_funding_locked UNNEEDED, const struct short_channel_id *funding_short_id UNNEEDED, bool reestablish UNNEEDED, const u8 *shutdown_scriptpubkey UNNEEDED, bool remote_shutdown_received UNNEEDED, u8 flags UNNEEDED, const u8 *init_peer_pkt UNNEEDED)
{ fprintf(stderr, "towire_channel_init called!\n"); abort(); }
/* Generated stub for towire_channel_send_shutdown */
u8 *towire_channel_send_shutdown(const tal_t *ctx UNNEEDED, const u8 *scriptpubkey UNNEEDED)
{ fprintf(stderr, "towire_channel_send_shutdown called!\n"); abort(); }
/* Generated stub for towire_closing_init */
u8 *towire_closing_init(const tal_t *ctx UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct privkey *seed UNNEEDED, const struct bitcoin_txid *funding_txid UNNEEDED, u16 funding_txout UNNEEDED, u64 funding_satoshi UNNEEDED, const struct pubkey *remote_fundingkey UNNEEDED, enum side funder UNNEEDED, u64 local_msatoshi UNNEEDED, u64 remote_msatoshi UNNEEDED, u64 our_dust_limit UNNEEDED, u64 min_fee_satoshi UNNEEDED, u64 fee_limit_satoshi UNNEEDED, u64 initial_fee_satoshi UNNEEDED, const u8 *local_scriptpubkey UNNEEDED, const u8 *remote_scriptpubkey UNNEEDED, bool reconnected UNNEEDED, u64 next_index_local UNNEEDED, u64 next_index_remote UNNEEDED, u64 revocations_received UNNEEDED, bool deprecated_api UNNEEDED)
{ fprintf(stderr, "towire_closing_init called!\n"); abort(); }
/* Generated stub for towire_closing_received_signature_reply */
u8 *towire_closing_received_signature_reply(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_closing_received_signature_reply called!\n"); abort(); }
/* Generated stub for towire_error */
u8 *towire_error(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, const u8 *data UNNEEDED)
{ fprintf(stderr, "towire_error called!\n"); abort(); }
/* Generated stub for towire_errorfmt */
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "towire_errorfmt called!\n"); abort(); }
/* Generated stub for towire_gossipctl_hand_back_peer */
u8 *towire_gossipctl_hand_back_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "towire_gossipctl_hand_back_peer called!\n"); abort(); }
/* Generated stub for towire_gossipctl_peer_addrhint */
u8 *towire_gossipctl_peer_addrhint(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED, const struct wireaddr *addr UNNEEDED)
{ fprintf(stderr, "towire_gossipctl_peer_addrhint called!\n"); abort(); }
/* Generated stub for towire_gossipctl_reach_peer */
u8 *towire_gossipctl_reach_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED)
{ fprintf(stderr, "towire_gossipctl_reach_peer called!\n"); abort(); }
/* Generated stub for towire_gossipctl_release_peer */
u8 *towire_gossipctl_release_peer(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED)
{ fprintf(stderr, "towire_gossipctl_release_peer called!\n"); abort(); }
/* Generated stub for towire_gossip_disable_channel */
u8 *towire_gossip_disable_channel(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED, u8 direction UNNEEDED, bool active UNNEEDED)
{ fprintf(stderr, "towire_gossip_disable_channel called!\n"); abort(); }
/* Generated stub for towire_gossip_getpeers_request */
u8 *towire_gossip_getpeers_request(const tal_t *ctx UNNEEDED, const struct pubkey *id UNNEEDED)
{ fprintf(stderr, "towire_gossip_getpeers_request called!\n"); abort(); }
/* Generated stub for towire_hsm_client_hsmfd */
u8 *towire_hsm_client_hsmfd(const tal_t *ctx UNNEEDED, const struct pubkey *pubkey UNNEEDED, u64 capabilities UNNEEDED)
{ fprintf(stderr, "towire_hsm_client_hsmfd called!\n"); abort(); }
/* Generated stub for towire_hsm_sign_funding */
u8 *towire_hsm_sign_funding(const tal_t *ctx UNNEEDED, u64 satoshi_out UNNEEDED, u64 change_out UNNEEDED, u32 change_keyindex UNNEEDED, const struct pubkey *our_pubkey UNNEEDED, const struct pubkey *their_pubkey UNNEEDED, const struct utxo **inputs UNNEEDED)
{ fprintf(stderr, "towire_hsm_sign_funding called!\n"); abort(); }
/* Generated stub for towire_onchain_depth */
u8 *towire_onchain_depth(const tal_t *ctx UNNEEDED, const struct bitcoin_txid *txid UNNEEDED, u32 depth UNNEEDED)
{ fprintf(stderr, "towire_onchain_depth called!\n"); abort(); }
/* Generated stub for towire_onchain_htlc */
u8 *towire_onchain_htlc(const tal_t *ctx UNNEEDED, const struct htlc_stub *htlc UNNEEDED, bool tell_if_missing UNNEEDED, bool tell_immediately UNNEEDED)
{ fprintf(stderr, "towire_onchain_htlc called!\n"); abort(); }
/* Generated stub for towire_onchain_init */
u8 *towire_onchain_init(const tal_t *ctx UNNEEDED, const struct privkey *seed UNNEEDED, const struct shachain *shachain UNNEEDED, u64 funding_amount_satoshi UNNEEDED, const struct pubkey *old_remote_per_commitment_point UNNEEDED, const struct pubkey *remote_per_commitment_point UNNEEDED, u32 local_to_self_delay UNNEEDED, u32 remote_to_self_delay UNNEEDED, u32 feerate_per_kw UNNEEDED, u64 local_dust_limit_satoshi UNNEEDED, const struct pubkey *remote_revocation_basepoint UNNEEDED, const struct bitcoin_txid *our_broadcast_txid UNNEEDED, const u8 *local_scriptpubkey UNNEEDED, const u8 *remote_scriptpubkey UNNEEDED, const struct pubkey *ourwallet_pubkey UNNEEDED, enum side funder UNNEEDED, const struct pubkey *remote_payment_basepoint UNNEEDED, const struct pubkey *remote_htlc_basepoint UNNEEDED, const struct pubkey *remote_delayed_payment_basepoint UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, u32 tx_blockheight UNNEEDED, u32 reasonable_depth UNNEEDED, const secp256k1_ecdsa_signature *htlc_signature UNNEEDED, u64 num_htlcs UNNEEDED)
{ fprintf(stderr, "towire_onchain_init called!\n"); abort(); }
/* Generated stub for towire_onchain_known_preimage */
u8 *towire_onchain_known_preimage(const tal_t *ctx UNNEEDED, const struct preimage *preimage UNNEEDED)
{ fprintf(stderr, "towire_onchain_known_preimage called!\n"); abort(); }
/* Generated stub for towire_onchain_spent */
u8 *towire_onchain_spent(const tal_t *ctx UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, u32 input_num UNNEEDED, u32 blockheight UNNEEDED)
{ fprintf(stderr, "towire_onchain_spent called!\n"); abort(); }
/* Generated stub for towire_opening_fundee */
u8 *towire_opening_fundee(const tal_t *ctx UNNEEDED, u32 minimum_depth UNNEEDED, u32 min_feerate UNNEEDED, u32 max_feerate UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "towire_opening_fundee called!\n"); abort(); }
/* Generated stub for towire_opening_funder */
u8 *towire_opening_funder(const tal_t *ctx UNNEEDED, u64 funding_satoshis UNNEEDED, u64 push_msat UNNEEDED, u32 feerate_per_kw UNNEEDED, u32 max_minimum_depth UNNEEDED, u64 change_satoshis UNNEEDED, u32 change_keyindex UNNEEDED, u8 channel_flags UNNEEDED, const struct utxo **inputs UNNEEDED, const struct ext_key *bip32 UNNEEDED)
{ fprintf(stderr, "towire_opening_funder called!\n"); abort(); }
/* Generated stub for towire_opening_init */
u8 *towire_opening_init(const tal_t *ctx UNNEEDED, u32 network_index UNNEEDED, const struct channel_config *our_config UNNEEDED, u32 max_to_self_delay UNNEEDED, u64 min_effective_htlc_capacity_msat UNNEEDED, const struct crypto_state *crypto_state UNNEEDED, u64 gossip_index UNNEEDED, const struct privkey *seed UNNEEDED)
{ fprintf(stderr, "towire_opening_init called!\n"); abort(); }
/* Generated stub for txfilter_add_scriptpubkey */
void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, u8 *script UNNEEDED)
{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); }
/* Generated stub for unsupported_features */
bool unsupported_features(const u8 *gfeatures UNNEEDED, const u8 *lfeatures UNNEEDED)
{ fprintf(stderr, "unsupported_features called!\n"); abort(); }
/* Generated stub for update_per_commit_point */
void update_per_commit_point(struct channel *channel UNNEEDED,
const struct pubkey *per_commitment_point UNNEEDED)
{ fprintf(stderr, "update_per_commit_point called!\n"); abort(); }
/* Generated stub for watch_tx_ */
struct txwatch *watch_tx_(const tal_t *ctx UNNEEDED,
struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_tx *tx UNNEEDED,
enum watch_result (*cb)(struct channel *channel UNNEEDED,
const struct bitcoin_tx * UNNEEDED,
unsigned int depth UNNEEDED,
void *) UNNEEDED,
void *cbdata UNNEEDED)
{ fprintf(stderr, "watch_tx_ called!\n"); abort(); }
/* Generated stub for watch_txid_ */
struct txwatch *watch_txid_(const tal_t *ctx UNNEEDED,
struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
enum watch_result (*cb)(struct channel *channel UNNEEDED,
const struct bitcoin_tx * UNNEEDED,
unsigned int depth UNNEEDED,
void *) UNNEEDED,
void *cbdata UNNEEDED)
{ fprintf(stderr, "watch_txid_ called!\n"); abort(); }
/* Generated stub for watch_txo_ */
struct txowatch *watch_txo_(const tal_t *ctx UNNEEDED,
struct chain_topology *topo UNNEEDED,
struct channel *channel UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED,
unsigned int output UNNEEDED,
enum watch_result (*cb)(struct channel *channel UNNEEDED,
const struct bitcoin_tx *tx UNNEEDED,
size_t input_num UNNEEDED,
const struct block *block UNNEEDED,
void *) UNNEEDED,
void *cbdata UNNEEDED)
{ fprintf(stderr, "watch_txo_ called!\n"); abort(); }
/* Generated stub for wire_sync_write */
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
{ fprintf(stderr, "wire_sync_write called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
#if DEVELOPER
bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "dev_disconnect_permanent called!\n"); abort(); }
#endif
static char *wallet_err;
static void wallet_fatal(const char *fmt, ...)
{
va_list ap;
/* Fail hard if we're complaining about not being in transaction */
assert(!strstarts(fmt, "No longer in transaction"));
/* Fail hard if we're complaining about not being in transaction */
assert(!strstarts(fmt, "No longer in transaction"));
va_start(ap, fmt);
wallet_err = tal_vfmt(NULL, fmt, ap);
va_end(ap);
}
#define transaction_wrap(db, ...) \
(db_begin_transaction(db), __VA_ARGS__, db_commit_transaction(db), wallet_err == NULL)
enum log_level get_log_level(struct log_book *lr UNNEEDED)
{
return LOG_DBG;
}
struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const char *fmt UNNEEDED, ...)
{
return NULL;
}
struct log_book *new_log_book(size_t max_mem UNNEEDED,
enum log_level printlevel UNNEEDED)
{
return NULL;
}
void set_log_outfn_(struct log_book *lr UNNEEDED,
void (*print)(const char *prefix UNNEEDED,
enum log_level level UNNEEDED,
bool continued UNNEEDED,
const struct timeabs *time UNNEEDED,
const char *str UNNEEDED,
const u8 *io UNNEEDED,
void *arg) UNNEEDED,
void *arg UNNEEDED)
{
}
const char *log_prefix(const struct log *log UNNEEDED)
{
return "";
}
/**
* mempat -- Set the memory to a pattern
*
* Used mainly to check that we don't mix fields while
* serializing/unserializing.
*/
static void mempat(void *dst, size_t len)
{
static int n = 0;
u8 *p = (u8*)dst;
for(int i=0 ; i < len; ++i)
p[i] = n % 251; /* Prime */
}
static struct wallet *create_test_wallet(struct lightningd *ld, const tal_t *ctx)
{
char filename[] = "/tmp/ldb-XXXXXX";
int fd = mkstemp(filename);
struct wallet *w = tal(ctx, struct wallet);
CHECK_MSG(fd != -1, "Unable to generate temp filename");
close(fd);
w->db = db_open(w, filename);
ltmp = tal_tmpctx(ctx);
list_head_init(&w->unstored_payments);
w->ld = ld;
CHECK_MSG(w->db, "Failed opening the db");
db_migrate(w->db, w->log);
CHECK_MSG(!wallet_err, "DB migration failed");
w->max_channel_dbid = 0;
return w;
}
static bool test_wallet_outputs(void)
{
char filename[] = "/tmp/ldb-XXXXXX";
struct utxo u;
int fd = mkstemp(filename);
CHECK_MSG(fd != -1, "Unable to generate temp filename");
close(fd);
struct wallet *w = tal(NULL, struct wallet);
struct pubkey pk;
u64 fee_estimate, change_satoshis;
const struct utxo **utxos;
w->db = db_open(w, filename);
CHECK_MSG(w->db, "Failed opening the db");
db_migrate(w->db, NULL);
CHECK_MSG(!wallet_err, "DB migration failed");
memset(&u, 0, sizeof(u));
u.amount = 1;
pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk);
db_begin_transaction(w->db);
/* Should work, it's the first time we add it */
CHECK_MSG(wallet_add_utxo(w, &u, p2sh_wpkh),
"wallet_add_utxo failed on first add");
/* Should fail, we already have that UTXO */
CHECK_MSG(!wallet_add_utxo(w, &u, p2sh_wpkh),
"wallet_add_utxo succeeded on second add");
/* Attempt to save an UTXO with close_info set */
memset(&u.txid, 1, sizeof(u.txid));
u.close_info = tal(w, struct unilateral_close_info);
u.close_info->channel_id = 42;
u.close_info->peer_id = pk;
u.close_info->commitment_point = pk;
CHECK_MSG(wallet_add_utxo(w, &u, p2sh_wpkh),
"wallet_add_utxo with close_info");
/* Now select them */
utxos = wallet_select_coins(w, w, 2, 0, 21, &fee_estimate, &change_satoshis);
CHECK(utxos && tal_count(utxos) == 2);
u = *utxos[1];
CHECK(u.close_info->channel_id == 42 &&
pubkey_eq(&u.close_info->commitment_point, &pk) &&
pubkey_eq(&u.close_info->peer_id, &pk));
/* Now un-reserve them for the tests below */
tal_free(utxos);
/* Attempt to reserve the utxo */
CHECK_MSG(wallet_update_output_status(w, &u.txid, u.outnum,
output_state_available,
output_state_reserved),
"could not reserve available output");
/* Reserving twice should fail */
CHECK_MSG(!wallet_update_output_status(w, &u.txid, u.outnum,
output_state_available,
output_state_reserved),
"could reserve already reserved output");
/* Un-reserving should work */
CHECK_MSG(wallet_update_output_status(w, &u.txid, u.outnum,
output_state_reserved,
output_state_available),
"could not unreserve reserved output");
/* Switching from any to something else */
CHECK_MSG(wallet_update_output_status(w, &u.txid, u.outnum,
output_state_any,
output_state_spent),
"could not change output state ignoring oldstate");
db_commit_transaction(w->db);
tal_free(w);
return true;
}
static bool test_shachain_crud(void)
{
struct wallet_shachain a, b;
char filename[] = "/tmp/ldb-XXXXXX";
int fd = mkstemp(filename);
struct wallet *w = tal(NULL, struct wallet);
struct sha256 seed, hash;
uint64_t index = UINT64_MAX >> (64 - SHACHAIN_BITS);
w->db = db_open(w, filename);
CHECK_MSG(w->db, "Failed opening the db");
db_migrate(w->db, NULL);
CHECK_MSG(!wallet_err, "DB migration failed");
CHECK_MSG(fd != -1, "Unable to generate temp filename");
close(fd);
memset(&seed, 'A', sizeof(seed));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
w->db = db_open(w, filename);
db_begin_transaction(w->db);
CHECK_MSG(!wallet_err, "db_begin_transaction failed");
wallet_shachain_init(w, &a);
CHECK(!wallet_err);
CHECK(a.id == 1);
CHECK(a.chain.num_valid == 0);
CHECK(shachain_next_index(&a.chain) == index);
for (int i=0; i<100; i++) {
shachain_from_seed(&seed, index, &hash);
CHECK(wallet_shachain_add_hash(w, &a, index, &hash));
index--;
}
CHECK(wallet_shachain_load(w, a.id, &b));
CHECK_MSG(memcmp(&a, &b, sizeof(a)) == 0, "Loading from database doesn't match");
db_commit_transaction(w->db);
CHECK(!wallet_err);
tal_free(w);
return true;
}
static bool bitcoin_tx_eq(const struct bitcoin_tx *tx1,
const struct bitcoin_tx *tx2)
{
u8 *lin1, *lin2;
bool eq;
lin1 = linearize_tx(NULL, tx1);
lin2 = linearize_tx(lin1, tx2);
eq = memeq(lin1, tal_len(lin1), lin2, tal_len(lin2));
tal_free(lin1);
return eq;
}
static bool channelseq(struct channel *c1, struct channel *c2)
{
struct peer *p1 = c1->peer, *p2 = c2->peer;
struct channel_info *ci1 = c1->channel_info, *ci2 = c2->channel_info;
struct changed_htlc *lc1 = c1->last_sent_commit, *lc2 = c2->last_sent_commit;
CHECK(c1->dbid == c2->dbid);
CHECK(c1->first_blocknum == c2->first_blocknum);
CHECK(c1->peer->dbid == c2->peer->dbid);
CHECK(c1->peer == c2->peer);
CHECK(c1->their_shachain.id == c2->their_shachain.id);
CHECK_MSG(pubkey_eq(&p1->id, &p2->id), "NodeIDs do not match");
CHECK((c1->scid == NULL && c2->scid == NULL) || short_channel_id_eq(c1->scid, c2->scid));
CHECK((c1->our_msatoshi == NULL) == (c2->our_msatoshi == NULL));
if (c1->our_msatoshi)
CHECK(*c1->our_msatoshi == *c2->our_msatoshi);
CHECK((c1->remote_shutdown_scriptpubkey == NULL && c2->remote_shutdown_scriptpubkey == NULL) || memeq(
c1->remote_shutdown_scriptpubkey,
tal_len(c1->remote_shutdown_scriptpubkey),
c2->remote_shutdown_scriptpubkey,
tal_len(c2->remote_shutdown_scriptpubkey)));
CHECK((c1->funding_txid == NULL && c2->funding_txid == NULL) || memeq(
c1->funding_txid,
sizeof(struct sha256_double),
c2->funding_txid,
sizeof(struct sha256_double)));
CHECK((ci1 != NULL) == (ci2 != NULL));
if(ci1) {
CHECK(pubkey_eq(&ci1->remote_fundingkey, &ci2->remote_fundingkey));
CHECK(pubkey_eq(&ci1->theirbase.revocation, &ci2->theirbase.revocation));
CHECK(pubkey_eq(&ci1->theirbase.payment, &ci2->theirbase.payment));
CHECK(pubkey_eq(&ci1->theirbase.delayed_payment, &ci2->theirbase.delayed_payment));
CHECK(pubkey_eq(&ci1->remote_per_commit, &ci2->remote_per_commit));
CHECK(pubkey_eq(&ci1->old_remote_per_commit, &ci2->old_remote_per_commit));
CHECK(ci1->their_config.id != 0 && ci1->their_config.id == ci2->their_config.id);
}
CHECK(c1->our_config.id != 0 && c1->our_config.id == c2->our_config.id);
CHECK((lc1 != NULL) == (lc2 != NULL));
if(lc1) {
CHECK(lc1->newstate == lc2->newstate);
CHECK(lc1->id == lc2->id);
}
CHECK((c1->last_tx != NULL) == (c2->last_tx != NULL));
if(c1->last_tx) {
CHECK(bitcoin_tx_eq(c1->last_tx, c2->last_tx));
}
CHECK((c1->last_sig != NULL) == (c2->last_sig != NULL));
if(c1->last_sig) {
CHECK(memeq(c1->last_sig, sizeof(*c1->last_sig),
c2->last_sig, sizeof(*c2->last_sig)));
}
if (c1->remote_shutdown_scriptpubkey) {
CHECK(c2->remote_shutdown_scriptpubkey);
CHECK(c1->local_shutdown_idx == c2->local_shutdown_idx);
}
CHECK(c1->last_was_revoke == c2->last_was_revoke);
return true;
}
static struct channel *wallet_channel_load(struct wallet *w, const u64 dbid)
{
struct peer *peer;
struct channel *channel;
/* We expect only one peer, but reuse same code */
if (!wallet_channels_load_active(w, w))
return NULL;
peer = list_top(&w->ld->peers, struct peer, list);
CHECK(peer);
/* We load lots of identical dbid channels: use last one */
channel = list_tail(&peer->channels, struct channel, list);
assert(channel->dbid == dbid);
return channel;
}
static bool test_channel_crud(struct lightningd *ld, const tal_t *ctx)
{
struct wallet *w = create_test_wallet(ld, ctx);
struct channel c1, *c2 = tal(w, struct channel);
struct peer *p;
struct channel_info ci;
struct bitcoin_txid *hash = tal(w, struct bitcoin_txid);
struct pubkey pk;
struct changed_htlc last_commit;
secp256k1_ecdsa_signature *sig = tal(w, secp256k1_ecdsa_signature);
u64 msat = 12345;
u8 *scriptpubkey = tal_arr(ctx, u8, 100);
memset(&c1, 0, sizeof(c1));
memset(c2, 0, sizeof(*c2));
memset(&ci, 3, sizeof(ci));
mempat(hash, sizeof(*hash));
mempat(sig, sizeof(*sig));
mempat(&last_commit, sizeof(last_commit));
pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk);
ci.feerate_per_kw[LOCAL] = ci.feerate_per_kw[REMOTE] = 31337;
mempat(scriptpubkey, tal_len(scriptpubkey));
c1.first_blocknum = 1;
p = new_peer(ld, 0, &pk, NULL);
c1.peer = p;
c1.dbid = wallet_get_channel_dbid(w);
c1.our_msatoshi = NULL;
c1.last_tx = NULL;
c1.state = CHANNELD_NORMAL;
memset(&ci.their_config, 0, sizeof(struct channel_config));
ci.remote_fundingkey = pk;
ci.theirbase.revocation = pk;
ci.theirbase.payment = pk;
ci.theirbase.htlc = pk;
ci.theirbase.delayed_payment = pk;
ci.remote_per_commit = pk;
ci.old_remote_per_commit = pk;
db_begin_transaction(w->db);
CHECK(!wallet_err);
wallet_channel_insert(w, &c1);
/* Variant 1: insert with null for scid, funding_tx_id, channel_info, last_tx */
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Load from DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v1)");
tal_free(c2);
/* We just inserted them into an empty DB so this must be 1 */
CHECK(c1.dbid == 1);
CHECK(c1.peer->dbid == 1);
CHECK(c1.their_shachain.id == 1);
/* Variant 2: update with scid set */
c1.scid = talz(w, struct short_channel_id);
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v2)");
tal_free(c2);
/* Updates should not result in new ids */
CHECK(c1.dbid == 1);
CHECK(c1.peer->dbid == 1);
CHECK(c1.their_shachain.id == 1);
/* Variant 3: update with our_satoshi set */
c1.our_msatoshi = &msat;
c1.last_was_revoke = !c1.last_was_revoke;
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v3)");
tal_free(c2);
/* Variant 4: update with funding_tx_id */
c1.funding_txid = hash;
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v4)");
tal_free(c2);
/* Variant 5: update with channel_info */
c1.channel_info = &ci;
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v5)");
tal_free(c2);
/* Variant 6: update with last_commit_sent */
c1.last_sent_commit = &last_commit;
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v6)");
tal_free(c2);
/* Variant 7: update with last_tx (taken from BOLT #3) */
c1.last_tx = bitcoin_tx_from_hex(w, "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220", strlen("02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220"));
c1.last_sig = sig;
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v7)");
tal_free(c2);
/* Variant 8: update and add remote_shutdown_scriptpubkey */
c1.remote_shutdown_scriptpubkey = scriptpubkey;
c1.local_shutdown_idx = 1337;
wallet_channel_save(w, &c1);
CHECK_MSG(!wallet_err, tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(c2 = wallet_channel_load(w, c1.dbid), tal_fmt(w, "Load from DB"));
CHECK_MSG(!wallet_err,
tal_fmt(w, "Insert into DB: %s", wallet_err));
CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v8)");
tal_free(c2);
db_commit_transaction(w->db);
CHECK(!wallet_err);
tal_free(w);
/* Normally freed by destroy_channel, but we don't call that */
tal_free(p);
return true;
}
static bool test_channel_config_crud(struct lightningd *ld, const tal_t *ctx)
{
struct channel_config *cc1 = talz(ctx, struct channel_config),
*cc2 = talz(ctx, struct channel_config);
struct wallet *w = create_test_wallet(ld, ctx);
CHECK(w);
cc1->dust_limit_satoshis = 1;
cc1->max_htlc_value_in_flight_msat = 2;
cc1->channel_reserve_satoshis = 3;
cc1->htlc_minimum_msat = 4;
cc1->to_self_delay = 5;
cc1->max_accepted_htlcs = 6;
CHECK(transaction_wrap(w->db, wallet_channel_config_insert(w, cc1)));
CHECK_MSG(
cc1->id == 1,
tal_fmt(ctx, "channel_config->id != 1; got %" PRIu64, cc1->id));
CHECK(transaction_wrap(w->db, wallet_channel_config_save(w, cc1)));
CHECK(transaction_wrap(w->db, wallet_channel_config_load(w, cc1->id, cc2)));
CHECK(memeq(cc1, sizeof(*cc1), cc2, sizeof(*cc2)));
return true;
}
static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx)
{
struct htlc_in in, *hin;
struct htlc_out out, *hout;
struct preimage payment_key;
struct channel *chan = tal(ctx, struct channel);
struct peer *peer = talz(ctx, struct peer);
struct wallet *w = create_test_wallet(ld, ctx);
struct htlc_in_map *htlcs_in = tal(ctx, struct htlc_in_map);
struct htlc_out_map *htlcs_out = tal(ctx, struct htlc_out_map);
/* Make sure we have our references correct */
CHECK(transaction_wrap(w->db,
db_exec(__func__, w->db, "INSERT INTO channels (id) VALUES (1);")));
chan->dbid = 1;
chan->peer = peer;
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
memset(&in.payment_hash, 'A', sizeof(struct sha256));
memset(&out.payment_hash, 'A', sizeof(struct sha256));
memset(&payment_key, 'B', sizeof(payment_key));
in.key.id = 42;
in.key.channel = chan;
in.msatoshi = 42;
out.in = &in;
out.key.id = 1337;
out.key.channel = chan;
out.msatoshi = 41;
/* Store the htlc_in */
CHECK_MSG(transaction_wrap(w->db, wallet_htlc_save_in(w, chan, &in)),
tal_fmt(ctx, "Save htlc_in failed: %s", wallet_err));
CHECK_MSG(in.dbid != 0, "HTLC DB ID was not set.");
/* Saving again should get us a collision */
CHECK_MSG(!transaction_wrap(w->db, wallet_htlc_save_in(w, chan, &in)),
"Saving two HTLCs with the same data must not succeed.");
CHECK(wallet_err);
wallet_err = tal_free(wallet_err);
/* Update */
CHECK_MSG(transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, RCVD_ADD_HTLC, NULL)),
"Update HTLC with null payment_key failed");
CHECK_MSG(
transaction_wrap(w->db, wallet_htlc_update(w, in.dbid, SENT_REMOVE_HTLC, &payment_key)),
"Update HTLC with payment_key failed");
CHECK_MSG(transaction_wrap(w->db, wallet_htlc_save_out(w, chan, &out)),
tal_fmt(ctx, "Save htlc_out failed: %s", wallet_err));
CHECK_MSG(out.dbid != 0, "HTLC DB ID was not set.");
CHECK_MSG(!transaction_wrap(w->db, wallet_htlc_save_out(w, chan, &out)),
"Saving two HTLCs with the same data must not succeed.");
CHECK(wallet_err);
wallet_err = tal_free(wallet_err);
/* Attempt to load them from the DB again */
htlc_in_map_init(htlcs_in);
htlc_out_map_init(htlcs_out);
db_begin_transaction(w->db);
CHECK(!wallet_err);
CHECK_MSG(wallet_htlcs_load_for_channel(w, chan, htlcs_in, htlcs_out),
"Failed loading HTLCs");
CHECK_MSG(wallet_htlcs_reconnect(w, htlcs_in, htlcs_out),
"Unable to reconnect htlcs.");
db_commit_transaction(w->db);
CHECK(!wallet_err);
hin = htlc_in_map_get(htlcs_in, &in.key);
hout = htlc_out_map_get(htlcs_out, &out.key);
CHECK(hin != NULL);
CHECK(hout != NULL);
/* Have to free manually, otherwise we get our dependencies
* twisted */
tal_free(hin);
tal_free(hout);
htlc_in_map_clear(htlcs_in);
htlc_out_map_clear(htlcs_out);
return true;
}
static bool test_payment_crud(struct lightningd *ld, const tal_t *ctx)
{
struct wallet_payment *t = tal(ctx, struct wallet_payment), *t2;
struct wallet *w = create_test_wallet(ld, ctx);
mempat(t, sizeof(*t));
memset(&t->destination, 1, sizeof(t->destination));
t->id = 0;
t->msatoshi = 100;
t->status = PAYMENT_PENDING;
t->payment_preimage = NULL;
memset(&t->payment_hash, 1, sizeof(t->payment_hash));
db_begin_transaction(w->db);
wallet_payment_setup(w, tal_dup(NULL, struct wallet_payment, t));
wallet_payment_store(w, &t->payment_hash);
t2 = wallet_payment_by_hash(ctx, w, &t->payment_hash);
CHECK(t2 != NULL);
CHECK(t2->status == t->status);
CHECK(pubkey_cmp(&t2->destination, &t->destination) == 0);
CHECK(t2->msatoshi == t->msatoshi);
CHECK(!t2->payment_preimage);
t->status = PAYMENT_COMPLETE;
t->payment_preimage = tal(w, struct preimage);
memset(t->payment_preimage, 2, sizeof(*t->payment_preimage));
wallet_payment_set_status(w, &t->payment_hash, t->status,
t->payment_preimage);
t2 = wallet_payment_by_hash(ctx, w, &t->payment_hash);
CHECK(t2 != NULL);
CHECK(t2->status == t->status);
CHECK(pubkey_cmp(&t2->destination, &t->destination) == 0);
CHECK(t2->msatoshi == t->msatoshi);
CHECK(structeq(t->payment_preimage, t2->payment_preimage));
db_commit_transaction(w->db);
return true;
}
int main(void)
{
bool ok = true;
tal_t *tmpctx = tal_tmpctx(NULL);
struct lightningd *ld = tal(tmpctx, struct lightningd);
/* Only elements in ld we should access */
list_head_init(&ld->peers);
pubkey_from_der(tal_hexdata(tmpctx, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &ld->id);
/* Accessed in peer destructor sanity check */
htlc_in_map_init(&ld->htlcs_in);
htlc_out_map_init(&ld->htlcs_out);
ok &= test_wallet_outputs();
ok &= test_shachain_crud();
ok &= test_channel_crud(ld, tmpctx);
ok &= test_channel_config_crud(ld, tmpctx);
ok &= test_htlc_crud(ld, tmpctx);
ok &= test_payment_crud(ld, tmpctx);
tal_free(tmpctx);
return !ok;
}