From b2819f9f97882bdc328ec87469571b5dec52ec8a Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 16 Feb 2018 17:55:33 +0100 Subject: [PATCH] wallet: Add check that wallet matches the network on startup Adds a simple check that compares genesis-blockhashes from the chainparams against the blockhash that the wallet was created with. The wallet is network specific, so mixing is always a bad idea. Signed-off-by: Christian Decker --- lightningd/lightningd.c | 3 +++ lightningd/test/run-find_my_path.c | 4 ++++ wallet/wallet.c | 31 ++++++++++++++++++++++++++++++ wallet/wallet.h | 12 ++++++++++++ 4 files changed, 50 insertions(+) diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 836b1bbc3..10b722579 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -304,6 +304,9 @@ int main(int argc, char *argv[]) /* Everything is within a transaction. */ db_begin_transaction(ld->wallet->db); + if (!wallet_network_check(ld->wallet, get_chainparams(ld))) + errx(1, "Wallet network check failed."); + /* Initialize the transaction filter with our pubkeys. */ init_txfilter(ld->wallet, ld->owned_txfilter); diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index 9b16093c3..288836f3e 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -107,6 +107,10 @@ bool wallet_htlcs_reconnect(struct wallet *wallet UNNEEDED, /* Generated stub for wallet_invoice_load */ bool wallet_invoice_load(struct wallet *wallet UNNEEDED) { fprintf(stderr, "wallet_invoice_load called!\n"); abort(); } +/* Generated stub for wallet_network_check */ +bool wallet_network_check(struct wallet *w UNNEEDED, + const struct chainparams *chainparams UNNEEDED) +{ fprintf(stderr, "wallet_network_check called!\n"); abort(); } /* Generated stub for wallet_new */ struct wallet *wallet_new(struct lightningd *ld UNNEEDED, struct log *log UNNEEDED, struct timers *timers UNNEEDED) diff --git a/wallet/wallet.c b/wallet/wallet.c index 6795ee7c1..1713825fa 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1618,3 +1618,34 @@ void wallet_htlc_sigs_save(struct wallet *w, u64 channel_id, db_exec_prepared(w->db, stmt); } } + +bool wallet_network_check(struct wallet *w, + const struct chainparams *chainparams) +{ + sqlite3_stmt *stmt = db_query(__func__, w->db, + "SELECT val FROM vars WHERE name='genesis_hash'"); + struct bitcoin_blkid chainhash; + + if (stmt && sqlite3_step(stmt) == SQLITE_ROW) { + sqlite3_column_sha256_double(stmt, 0, &chainhash.shad); + sqlite3_finalize(stmt); + if (!structeq(&chainhash, &chainparams->genesis_blockhash)) { + log_broken(w->log, "Wallet blockchain hash does not " + "match network blockchain hash: %s " + "!= %s", + type_to_string(w, struct bitcoin_blkid, + &chainhash), + type_to_string(w, struct bitcoin_blkid, + &chainparams->genesis_blockhash)); + return false; + } + } else { + /* Still a pristine wallet, claim it for the chain + * that we are running */ + sqlite3_finalize(stmt); + stmt = db_prepare(w->db, "INSERT INTO vars (name, val) VALUES ('genesis_hash', ?);"); + sqlite3_bind_sha256_double(stmt, 1, &chainparams->genesis_blockhash.shad); + db_exec_prepared(w->db, stmt); + } + return true; +} diff --git a/wallet/wallet.h b/wallet/wallet.h index f911065fe..de32f47ef 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -3,6 +3,7 @@ #include "config.h" #include "db.h" +#include #include #include #include @@ -618,4 +619,15 @@ const struct wallet_payment **wallet_payment_list(const tal_t *ctx, */ void wallet_htlc_sigs_save(struct wallet *w, u64 channel_id, secp256k1_ecdsa_signature *htlc_sigs); + +/** + * wallet_network_check - Check that the wallet is setup for this chain + * + * Ensure that the genesis_hash from the chainparams matches the + * genesis_hash with which the DB was initialized. Returns false if + * the check failed, i.e., if the genesis hashes do not match. + */ +bool wallet_network_check(struct wallet *w, + const struct chainparams *chainparams); + #endif /* WALLET_WALLET_H */