wallet: Reserve UTXOs used in build_utxos

This commit is contained in:
Christian Decker 2017-05-31 16:16:59 +02:00 committed by Rusty Russell
parent 19a4e7f542
commit bdb6b1002f
4 changed files with 82 additions and 8 deletions

View File

@ -179,7 +179,12 @@ static void unreserve_utxo(struct lightningd *ld, const struct utxo *unres)
{ {
struct tracked_utxo *utxo; struct tracked_utxo *utxo;
list_for_each(&ld->utxos, utxo, list) { assert(wallet_update_output_status(ld->wallet, &unres->txid,
unres->outnum, output_state_reserved,
output_state_available));
list_for_each(&ld->utxos, utxo, list)
{
if (unres != &utxo->utxo) if (unres != &utxo->utxo)
continue; continue;
assert(utxo->reserved); assert(utxo->reserved);
@ -225,6 +230,10 @@ const struct utxo **build_utxos(const tal_t *ctx,
utxos[i] = &utxo->utxo; utxos[i] = &utxo->utxo;
utxo->reserved = true; utxo->reserved = true;
assert(wallet_update_output_status(
ld->wallet, &utxo->utxo.txid, utxo->utxo.outnum,
output_state_available, output_state_reserved));
/* Add this input's weight. */ /* Add this input's weight. */
weight += (32 + 4 + 4) * 4; weight += (32 + 4 + 4) * 4;
if (utxos[i]->is_p2sh) if (utxos[i]->is_p2sh)

View File

@ -25,3 +25,27 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
tal_free(tmpctx); tal_free(tmpctx);
return result; return result;
} }
bool wallet_update_output_status(struct wallet *w,
const struct sha256_double *txid,
const u32 outnum, enum output_status oldstatus,
enum output_status newstatus)
{
tal_t *tmpctx = tal_tmpctx(w);
char *hextxid = tal_hexstr(tmpctx, txid, sizeof(*txid));
if (oldstatus != output_state_any) {
db_exec(__func__, w->db,
"UPDATE outputs SET status=%d WHERE status=%d "
"AND prev_out_tx = '%s' AND prev_out_index = "
"%d;",
newstatus, oldstatus, hextxid, outnum);
} else {
db_exec(__func__, w->db,
"UPDATE outputs SET status=%d WHERE "
"AND prev_out_tx = '%s' AND prev_out_index = "
"%d;",
newstatus, hextxid, outnum);
}
tal_free(tmpctx);
return sqlite3_changes(w->db->sql) > 0;
}

View File

@ -50,4 +50,19 @@ struct wallet *wallet_new(const tal_t *ctx, struct log *log);
bool wallet_add_utxo(struct wallet *w, struct utxo *utxo, bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
enum wallet_output_type type); enum wallet_output_type type);
/**
* wallet_update_output_status - Perform an output state transition
*
* Change the current status of an output we are tracking in the
* database. Returns true if the output exists with the @oldstatus and
* was successfully updated to @newstatus. May fail if either the
* output does not exist, or it does not have the expected
* @oldstatus. In case we don't care about the previous state use
* `output_state_any` as @oldstatus.
*/
bool wallet_update_output_status(struct wallet *w,
const struct sha256_double *txid,
const u32 outnum, enum output_status oldstatus,
enum output_status newstatus);
#endif /* WALLET_WALLET_H */ #endif /* WALLET_WALLET_H */

View File

@ -6,7 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
static bool test_wallet_add_utxo(void) static bool test_wallet_outputs(void)
{ {
char filename[] = "/tmp/ldb-XXXXXX"; char filename[] = "/tmp/ldb-XXXXXX";
struct utxo u; struct utxo u;
@ -16,26 +16,52 @@ static bool test_wallet_add_utxo(void)
close(fd); close(fd);
w->db = db_open(w, filename); w->db = db_open(w, filename);
CHECK_MSG(w->db,"Failed opening the db"); CHECK_MSG(w->db, "Failed opening the db");
CHECK_MSG(db_migrate(w->db), "DB migration failed"); CHECK_MSG(db_migrate(w->db), "DB migration failed");
memset(&u, 0, sizeof(u)); memset(&u, 0, sizeof(u));
/* Should work, it's the first time we add it */ /* 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"); CHECK_MSG(wallet_add_utxo(w, &u, p2sh_wpkh),
"wallet_add_utxo failed on first add");
/* Should fail, we already have that UTXO */ /* Should fail, we already have that UTXO */
CHECK_MSG(!wallet_add_utxo(w, &u, p2sh_wpkh), "wallet_add_utxo succeeded on second add"); CHECK_MSG(!wallet_add_utxo(w, &u, p2sh_wpkh),
"wallet_add_utxo succeeded on second add");
/* 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");
tal_free(w); tal_free(w);
return true; return true;
} }
int main(void) int main(void)
{ {
bool ok = true; bool ok = true;
ok &= test_wallet_add_utxo(); ok &= test_wallet_outputs();
return !ok; return !ok;
} }