From 6f441d3cd2d9065dd8d4fb1d17901c6586f6b01e Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Sat, 5 Aug 2017 12:28:44 +0200 Subject: [PATCH] wallet: Add a CRU(D) test for wallet_channels Simple roundtrip testing which writes to DB, reads it back in and checks for equality. --- wallet/wallet_tests.c | 134 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/wallet/wallet_tests.c b/wallet/wallet_tests.c index a8a104c5e..10df14e94 100644 --- a/wallet/wallet_tests.c +++ b/wallet/wallet_tests.c @@ -1,5 +1,6 @@ #include "wallet.c" +#include #include "db.c" #include "wallet/test_utils.h" @@ -96,12 +97,145 @@ static bool test_shachain_crud(void) return true; } +static bool channelseq(struct wallet_channel *c1, struct wallet_channel *c2) +{ + struct peer *p1 = c1->peer, *p2 = c2->peer; + struct channel_info *ci1 = p1->channel_info, *ci2 = p2->channel_info; + struct changed_htlc *lc1 = p1->last_sent_commit, *lc2 = p2->last_sent_commit; + CHECK(c1->id == c2->id); + CHECK(c1->peer_id == c2->peer_id); + CHECK(p1->their_shachain.id == p2->their_shachain.id); + CHECK_MSG(pubkey_eq(&p1->id, &p2->id), "NodeIDs do not match"); + CHECK((p1->scid == NULL && p2->scid == NULL) || short_channel_id_eq(p1->scid, p2->scid)); + CHECK((p1->our_msatoshi == NULL && p2->our_msatoshi == NULL) || *p1->our_msatoshi == *p2->our_msatoshi); + CHECK((p1->remote_shutdown_scriptpubkey == NULL && p2->remote_shutdown_scriptpubkey == NULL) || memeq( + p1->remote_shutdown_scriptpubkey, + tal_len(p1->remote_shutdown_scriptpubkey), + p2->remote_shutdown_scriptpubkey, + tal_len(p2->remote_shutdown_scriptpubkey))); + CHECK((p1->funding_txid == NULL && p2->funding_txid == NULL) || memeq( + p1->funding_txid, + sizeof(struct sha256_double), + p2->funding_txid, + sizeof(struct sha256_double))); + CHECK((ci1 != NULL) == (ci2 != NULL)); + if(ci1) { + CHECK(memeq(&ci1->commit_sig, sizeof(secp256k1_ecdsa_signature), + &ci2->commit_sig, sizeof(secp256k1_ecdsa_signature))); + 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((lc1 != NULL) == (lc2 != NULL)); + if(lc1) { + CHECK(lc1->newstate == lc2->newstate); + CHECK(lc1->id == lc2->id); + } + + return true; +} + +static bool test_channel_crud(void) +{ + char filename[] = "/tmp/ldb-XXXXXX"; + int fd = mkstemp(filename); + struct wallet *w = tal(NULL, struct wallet); + struct wallet_channel c1, *c2 = tal(w, struct wallet_channel); + struct peer p; + struct channel_info ci; + struct sha256_double *hash = tal(w, struct sha256_double); + struct pubkey pk; + struct changed_htlc last_commit; + + u64 msat = 12345; + + w->db = db_open(w, filename); + CHECK_MSG(w->db, "Failed opening the db"); + CHECK_MSG(db_migrate(w->db), "DB migration failed"); + + CHECK_MSG(fd != -1, "Unable to generate temp filename"); + close(fd); + + memset(&c1, 0, sizeof(c1)); + memset(c2, 0, sizeof(*c2)); + memset(&p, 0, sizeof(p)); + memset(&ci, 3, sizeof(ci)); + memset(hash, 'B', sizeof(*hash)); + memset(&last_commit, 0, sizeof(last_commit)); + pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk); + ci.feerate_per_kw = 31337; + memset(&p.id, 'A', sizeof(p.id)); + c1.peer = &p; + p.id = pk; + p.unique_id = 42; + p.our_msatoshi = NULL; + ci.remote_fundingkey = pk; + ci.theirbase.revocation = pk; + ci.theirbase.payment = pk; + ci.theirbase.delayed_payment = pk; + ci.remote_per_commit = pk; + ci.old_remote_per_commit = pk; + + /* Variant 1: insert with null for scid, funding_tx_id, and channel_info */ + CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err)); + CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err)); + CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v1)"); + + /* We just inserted them into an empty DB so this must be 1 */ + CHECK(c1.id == 1); + CHECK(c1.peer_id == 1); + CHECK(c1.peer->their_shachain.id == 1); + + /* Variant 2: update with scid set */ + c1.peer->scid = talz(w, struct short_channel_id); + CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err)); + CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err)); + CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v2)"); + + /* Updates should not result in new ids */ + CHECK(c1.id == 1); + CHECK(c1.peer_id == 1); + CHECK(c1.peer->their_shachain.id == 1); + + /* Variant 3: update with our_satoshi set */ + c1.peer->our_msatoshi = &msat; + CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err)); + CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err)); + CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v3)"); + + /* Variant 4: update with funding_tx_id */ + c1.peer->funding_txid = hash; + CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err)); + CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err)); + CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v4)"); + + /* Variant 5: update with channel_info */ + p.channel_info = &ci; + CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err)); + CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err)); + CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v5)"); + + /* Variant 6: update with last_commit_sent */ + p.last_sent_commit = &last_commit; + CHECK_MSG(wallet_channel_save(w, &c1), tal_fmt(w, "Insert into DB: %s", w->db->err)); + CHECK_MSG(wallet_channel_load(w, c1.id, c2), tal_fmt(w, "Load from DB: %s", w->db->err)); + CHECK_MSG(channelseq(&c1, c2), "Compare loaded with saved (v6)"); + + tal_free(w); + return true; +} + int main(void) { bool ok = true; ok &= test_wallet_outputs(); ok &= test_shachain_crud(); + ok &= test_channel_crud(); return !ok; }