mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
wallet: Added unilateral close info to utxo
This is necessary to grad the their_unilateral/to-us outputs since they aren't being harvested by `onchaind` Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
@@ -1,11 +1,20 @@
|
||||
#ifndef LIGHTNING_COMMON_UTXO_H
|
||||
#define LIGHTNING_COMMON_UTXO_H
|
||||
#include "config.h"
|
||||
#include <bitcoin/pubkey.h>
|
||||
#include <bitcoin/shadouble.h>
|
||||
#include <bitcoin/tx.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Information needed for their_unilateral/to-us outputs */
|
||||
struct unilateral_close_info {
|
||||
u64 channel_id;
|
||||
struct pubkey peer_id;
|
||||
struct pubkey commitment_point;
|
||||
};
|
||||
|
||||
struct utxo {
|
||||
struct bitcoin_txid txid;
|
||||
u32 outnum;
|
||||
@@ -13,6 +22,10 @@ struct utxo {
|
||||
u32 keyindex;
|
||||
bool is_p2sh;
|
||||
u8 status;
|
||||
|
||||
/* Optional unilateral close information, NULL if this is just
|
||||
* a HD key */
|
||||
struct unilateral_close_info *close_info;
|
||||
};
|
||||
|
||||
void towire_utxo(u8 **pptr, const struct utxo *utxo);
|
||||
|
||||
@@ -99,6 +99,7 @@ int main(void)
|
||||
utxo.outnum = 0;
|
||||
utxo.amount = 5000000000;
|
||||
utxo.is_p2sh = false;
|
||||
utxo.close_info = NULL;
|
||||
funding_satoshis = 10000000;
|
||||
fee = 13920;
|
||||
|
||||
|
||||
15
wallet/db.c
15
wallet/db.c
@@ -150,6 +150,9 @@ char *dbmigrations[] = {
|
||||
* pre-release software, so it's forgivable. */
|
||||
"ALTER TABLE channels ADD first_blocknum INTEGER;",
|
||||
"UPDATE channels SET first_blocknum=CAST(short_channel_id AS INTEGER) WHERE short_channel_id IS NOT NULL;",
|
||||
"ALTER TABLE outputs ADD COLUMN channel_id INTEGER;",
|
||||
"ALTER TABLE outputs ADD COLUMN peer_id BLOB;",
|
||||
"ALTER TABLE outputs ADD COLUMN commitment_point BLOB;",
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -493,3 +496,15 @@ bool sqlite3_bind_sha256(sqlite3_stmt *stmt, int col, const struct sha256 *p)
|
||||
sqlite3_bind_blob(stmt, col, p, sizeof(struct sha256), SQLITE_TRANSIENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sqlite3_column_sha256_double(sqlite3_stmt *stmt, int col, struct sha256_double *dest)
|
||||
{
|
||||
assert(sqlite3_column_bytes(stmt, col) == sizeof(struct sha256_double));
|
||||
return memcpy(dest, sqlite3_column_blob(stmt, col), sizeof(struct sha256_double));
|
||||
}
|
||||
|
||||
bool sqlite3_bind_sha256_double(sqlite3_stmt *stmt, int col, const struct sha256_double *p)
|
||||
{
|
||||
sqlite3_bind_blob(stmt, col, p, sizeof(struct sha256_double), SQLITE_TRANSIENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -132,4 +132,7 @@ bool sqlite3_bind_preimage(sqlite3_stmt *stmt, int col, const struct preimage *p
|
||||
bool sqlite3_column_sha256(sqlite3_stmt *stmt, int col, struct sha256 *dest);
|
||||
bool sqlite3_bind_sha256(sqlite3_stmt *stmt, int col, const struct sha256 *p);
|
||||
|
||||
bool sqlite3_column_sha256_double(sqlite3_stmt *stmt, int col, struct sha256_double *dest);
|
||||
bool sqlite3_bind_sha256_double(sqlite3_stmt *stmt, int col, const struct sha256_double *p);
|
||||
|
||||
#endif /* WALLET_DB_H */
|
||||
|
||||
@@ -17,6 +17,7 @@ static void db_log_(struct log *log, enum log_level level, const char *fmt, ...)
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/memleak.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -87,16 +88,22 @@ static bool test_wallet_outputs(void)
|
||||
char filename[] = "/tmp/ldb-XXXXXX";
|
||||
struct utxo u;
|
||||
int fd = mkstemp(filename);
|
||||
struct wallet *w = tal(NULL, struct wallet);
|
||||
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);
|
||||
|
||||
@@ -108,6 +115,27 @@ static bool test_wallet_outputs(void)
|
||||
CHECK_MSG(!wallet_add_utxo(w, &u, p2sh_wpkh),
|
||||
"wallet_add_utxo succeeded on second add");
|
||||
|
||||
/* Attempt to save a 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,
|
||||
@@ -133,6 +161,7 @@ static bool test_wallet_outputs(void)
|
||||
"could not change output state ignoring oldstate");
|
||||
|
||||
db_commit_transaction(w->db);
|
||||
|
||||
tal_free(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,13 +29,22 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
stmt = db_prepare(w->db, "INSERT INTO outputs (prev_out_tx, prev_out_index, value, type, status, keyindex) VALUES (?, ?, ?, ?, ?, ?);");
|
||||
stmt = db_prepare(w->db, "INSERT INTO outputs (prev_out_tx, prev_out_index, value, type, status, keyindex, channel_id, peer_id, commitment_point) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
||||
sqlite3_bind_blob(stmt, 1, &utxo->txid, sizeof(utxo->txid), SQLITE_TRANSIENT);
|
||||
sqlite3_bind_int(stmt, 2, utxo->outnum);
|
||||
sqlite3_bind_int64(stmt, 3, utxo->amount);
|
||||
sqlite3_bind_int(stmt, 4, type);
|
||||
sqlite3_bind_int(stmt, 5, output_state_available);
|
||||
sqlite3_bind_int(stmt, 6, utxo->keyindex);
|
||||
if (utxo->close_info) {
|
||||
sqlite3_bind_int64(stmt, 7, utxo->close_info->channel_id);
|
||||
sqlite3_bind_pubkey(stmt, 8, &utxo->close_info->peer_id);
|
||||
sqlite3_bind_pubkey(stmt, 9, &utxo->close_info->commitment_point);
|
||||
} else {
|
||||
sqlite3_bind_null(stmt, 7);
|
||||
sqlite3_bind_null(stmt, 8);
|
||||
sqlite3_bind_null(stmt, 9);
|
||||
}
|
||||
return db_exec_prepared_mayfail(w->db, stmt);
|
||||
}
|
||||
|
||||
@@ -46,12 +55,21 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
||||
*/
|
||||
static bool wallet_stmt2output(sqlite3_stmt *stmt, struct utxo *utxo)
|
||||
{
|
||||
memcpy(&utxo->txid, sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
|
||||
sqlite3_column_sha256_double(stmt, 0, &utxo->txid.shad);
|
||||
utxo->outnum = sqlite3_column_int(stmt, 1);
|
||||
utxo->amount = sqlite3_column_int(stmt, 2);
|
||||
utxo->is_p2sh = sqlite3_column_int(stmt, 3) == p2sh_wpkh;
|
||||
utxo->status = sqlite3_column_int(stmt, 4);
|
||||
utxo->keyindex = sqlite3_column_int(stmt, 5);
|
||||
if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) {
|
||||
utxo->close_info = tal(utxo, struct unilateral_close_info);
|
||||
utxo->close_info->channel_id = sqlite3_column_int64(stmt, 6);
|
||||
sqlite3_column_pubkey(stmt, 7, &utxo->close_info->peer_id);
|
||||
sqlite3_column_pubkey(stmt, 8, &utxo->close_info->commitment_point);
|
||||
} else {
|
||||
utxo->close_info = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,7 +103,8 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum ou
|
||||
int i;
|
||||
|
||||
sqlite3_stmt *stmt = db_prepare(
|
||||
w->db, "SELECT prev_out_tx, prev_out_index, value, type, status, keyindex "
|
||||
w->db, "SELECT prev_out_tx, prev_out_index, value, type, status, keyindex, "
|
||||
"channel_id, peer_id, commitment_point "
|
||||
"FROM outputs WHERE status=?1 OR ?1=255");
|
||||
sqlite3_bind_int(stmt, 1, state);
|
||||
|
||||
@@ -829,6 +848,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx,
|
||||
utxo->status = output_state_available;
|
||||
bitcoin_txid(tx, &utxo->txid);
|
||||
utxo->outnum = output;
|
||||
utxo->close_info = NULL;
|
||||
log_debug(w->log, "Owning output %zu %"PRIu64" (%s) txid %s",
|
||||
output, tx->output[output].amount,
|
||||
is_p2sh ? "P2SH" : "SEGWIT",
|
||||
|
||||
Reference in New Issue
Block a user