diff --git a/daemon/chaintopology.c b/daemon/chaintopology.c index a4596b820..dadd939c3 100644 --- a/daemon/chaintopology.c +++ b/daemon/chaintopology.c @@ -279,10 +279,7 @@ void broadcast_tx(struct peer *peer, const struct bitcoin_tx *tx) list_add_tail(&peer->outgoing_txs, &otx->list); tal_add_destructor(otx, destroy_outgoing_tx); - /* FIXME: log_struct */ - log_add(peer->log, " (tx %02x%02x%02x%02x...)", - otx->txid.sha.u.u8[0], otx->txid.sha.u.u8[1], - otx->txid.sha.u.u8[2], otx->txid.sha.u.u8[3]); + log_add_struct(peer->log, " (tx %s)", struct sha256_double, &otx->txid); rawtx = linearize_tx(txs, otx->tx); txs[0] = tal_hexstr(txs, rawtx, tal_count(rawtx)); @@ -337,11 +334,8 @@ static struct block *new_block(struct lightningd_state *dstate, struct block *b = tal(topo, struct block); sha256_double(&b->blkid, &blk->hdr, sizeof(blk->hdr)); - log_debug(dstate->base_log, "Adding block %02x%02x%02x%02x...\n", - b->blkid.sha.u.u8[0], - b->blkid.sha.u.u8[1], - b->blkid.sha.u.u8[2], - b->blkid.sha.u.u8[3]); + log_debug_struct(dstate->base_log, "Adding block %s", + struct sha256_double, &b->blkid); assert(!block_map_get(&topo->block_map, &b->blkid)); b->next = next; diff --git a/daemon/log.c b/daemon/log.c index 4fb1a5fa8..b7da4c6ff 100644 --- a/daemon/log.c +++ b/daemon/log.c @@ -1,6 +1,10 @@ +#include "bitcoin/locktime.h" +#include "bitcoin/pubkey.h" +#include "bitcoin/tx.h" #include "controlled_time.h" #include "log.h" #include "pseudorand.h" +#include "utils.h" #include #include #include @@ -263,11 +267,53 @@ void log_add(struct log *log, const char *fmt, ...) va_end(ap); } -void log_add_hex(struct log *log, const void *data, size_t len) +void log_struct_(struct log *log, int level, + const char *structname, + const char *fmt, ...) { - char hex[hex_str_size(len)]; - hex_encode(data, len, hex, hex_str_size(len)); - log_add(log, "%s", hex); + char *s; + union loggable_structs u; + va_list ap; + + /* Macro wrappers ensure we only have one arg. */ + va_start(ap, fmt); + u.charp_ = va_arg(ap, const char *); + va_end(ap); + + /* GCC checks we're one of these, so we should be. */ + if (streq(structname, "struct pubkey")) + s = tal_hexstr(log, u.pubkey->der, sizeof(u.pubkey->der)); + else if (streq(structname, "struct sha256_double")) + s = tal_hexstr(log, u.sha256_double, sizeof(*u.sha256_double)); + else if (streq(structname, "struct sha256")) + s = tal_hexstr(log, u.sha256, sizeof(*u.sha256)); + else if (streq(structname, "struct rel_locktime")) { + if (rel_locktime_is_seconds(u.rel_locktime)) + s = tal_fmt(log, "+%usec", + rel_locktime_to_seconds(u.rel_locktime)); + else + s = tal_fmt(log, "+%ublocks", + rel_locktime_to_blocks(u.rel_locktime)); + } else if (streq(structname, "struct abs_locktime")) { + if (abs_locktime_is_seconds(u.abs_locktime)) + s = tal_fmt(log, "%usec", + abs_locktime_to_seconds(u.abs_locktime)); + else + s = tal_fmt(log, "%ublocks", + abs_locktime_to_blocks(u.abs_locktime)); + } else if (streq(structname, "struct bitcoin_tx")) { + u8 *lin = linearize_tx(NULL, u.bitcoin_tx); + s = tal_hexstr(log, lin, tal_count(lin)); + tal_free(lin); + } else + fatal("Logging unknown type %s", structname); + + if (level == -1) + log_add(log, fmt, s); + else + log_(log, level, fmt, s); + + tal_free(s); } void log_each_line_(const struct log_record *lr, diff --git a/daemon/log.h b/daemon/log.h index 3dcdefcb6..a877a8900 100644 --- a/daemon/log.h +++ b/daemon/log.h @@ -39,18 +39,49 @@ void log_io(struct log *log, bool in, const void *data, size_t len); void log_(struct log *log, enum log_level level, const char *fmt, ...) PRINTF_FMT(3,4); void log_add(struct log *log, const char *fmt, ...) PRINTF_FMT(2,3); -void log_add_hex(struct log *log, const void *data, size_t len); void logv(struct log *log, enum log_level level, const char *fmt, va_list ap); -#define log_add_struct(log, structtype, ptr) \ - log_add_struct_((log), stringify(structtype), \ - ((void)sizeof((ptr) == (structtype *)NULL), (ptr))) -#define log_add_enum(log, enumtype, val) \ - log_add_enum_((log), stringify(enumtype), (val)) +/* Makes sure ptr is a 'structtype', makes sure it's in loggable_structs. */ +#define log_struct_check_(log, loglevel, fmt, structtype, ptr) \ + log_struct_((log), (loglevel), stringify(structtype), (fmt), \ + ((void)sizeof((ptr) == (structtype *)NULL), \ + ((union loggable_structs)(ptr)).charp_)) + +/* These must have %s where the struct is to go. */ +#define log_add_struct(log, fmt, structtype, ptr) \ + log_struct_check_((log), -1, (fmt), structtype, (ptr)) + +#define log_debug_struct(log, fmt, structtype, ptr) \ + log_struct_check_((log), LOG_DBG, (fmt), structtype, (ptr)) +#define log_info_struct(log, fmt, structtype, ptr) \ + log_struct_check_((log), LOG_INFORM, (fmt), structtype, (ptr)) +#define log_unusual_struct(log, fmt, structtype, ptr) \ + log_struct_check_((log), LOG_UNUSUAL, (fmt), structtype, (ptr)) +#define log_broken_struct(log, fmt, structtype, ptr) \ + log_struct_check_((log), LOG_BROKEN, (fmt), structtype, (ptr)) + +/* This must match the log_add_struct_ definitions. */ +union loggable_structs { + /* Yech, need both const and non-const versions. */ + const struct pubkey *const_pubkey; + struct pubkey *pubkey; + const struct sha256_double *const_sha256_double; + struct sha256_double *sha256_double; + const struct sha256 *const_sha256; + struct sha256 *sha256; + const struct rel_locktime *const_rel_locktime; + struct rel_locktime *rel_locktime; + const struct abs_locktime *const_abs_locktime; + struct abs_locktime *abs_locktime; + const struct bitcoin_tx *const_bitcoin_tx; + struct bitcoin_tx *bitcoin_tx; + const char *charp_; +}; -void log_add_struct_(struct log *log, const char *structname, const void *ptr); -void log_add_enum_(struct log *log, const char *enumname, unsigned int val); +void PRINTF_FMT(4,5) log_struct_(struct log *log, int level, + const char *structname, + const char *fmt, ...); void set_log_level(struct log_record *lr, enum log_level level); void set_log_prefix(struct log *log, const char *prefix); diff --git a/daemon/secrets.c b/daemon/secrets.c index 7c6135101..3dd7da1d8 100644 --- a/daemon/secrets.c +++ b/daemon/secrets.c @@ -209,6 +209,5 @@ void secrets_init(struct lightningd_state *dstate) SECP256K1_EC_COMPRESSED)) fatal("Invalid privkey"); - log_info(dstate->base_log, "ID: "); - log_add_hex(dstate->base_log, dstate->id.der, sizeof(dstate->id.der)); + log_info_struct(dstate->base_log, "ID: %s", struct pubkey, &dstate->id); }