mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
wallet: Retrieve transaction annotations when listing transactions
This triple join should be efficient to read, and to process. We have a one-to-many (tx-to-annotations), followed by a one-to-one (annotation-to-channel) join, so we are limited to annotations x transactions results.
This commit is contained in:
parent
ddae604f3d
commit
d981b58234
@ -3410,24 +3410,88 @@ struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t
|
|||||||
{
|
{
|
||||||
struct db_stmt *stmt;
|
struct db_stmt *stmt;
|
||||||
size_t count;
|
size_t count;
|
||||||
struct wallet_transaction *cur, *txs = tal_arr(ctx, struct wallet_transaction, 0);
|
struct wallet_transaction *cur = NULL, *txs = tal_arr(ctx, struct wallet_transaction, 0);
|
||||||
|
struct bitcoin_txid last;
|
||||||
|
|
||||||
|
/* Make sure we can check for changing txids */
|
||||||
|
memset(&last, 0, sizeof(last));
|
||||||
|
|
||||||
stmt = db_prepare_v2(
|
stmt = db_prepare_v2(
|
||||||
w->db,
|
w->db,
|
||||||
SQL("SELECT id, id, rawtx, blockheight, txindex, type, channel_id "
|
SQL("SELECT"
|
||||||
"FROM transactions"));
|
" t.id"
|
||||||
|
", t.rawtx"
|
||||||
|
", t.blockheight"
|
||||||
|
", t.txindex"
|
||||||
|
", t.type as txtype"
|
||||||
|
", c2.short_channel_id as txchan"
|
||||||
|
", a.location"
|
||||||
|
", a.idx as ann_idx"
|
||||||
|
", a.type as annotation_type"
|
||||||
|
", c.short_channel_id"
|
||||||
|
" FROM"
|
||||||
|
" transactions t LEFT JOIN"
|
||||||
|
" transaction_annotations a ON (a.txid = t.id) LEFT JOIN"
|
||||||
|
" channels c ON (a.channel = c.id) LEFT JOIN"
|
||||||
|
" channels c2 ON (t.channel_id = c2.id) "
|
||||||
|
"ORDER BY blockheight, txindex ASC"));
|
||||||
db_query_prepared(stmt);
|
db_query_prepared(stmt);
|
||||||
|
|
||||||
for (count = 0; db_step(stmt); count++) {
|
for (count = 0; db_step(stmt); count++) {
|
||||||
tal_resize(&txs, count + 1);
|
struct bitcoin_txid curtxid;
|
||||||
cur = &txs[count];
|
db_column_txid(stmt, 0, &curtxid);
|
||||||
db_column_txid(stmt, 1, &cur->id);
|
|
||||||
cur->rawtx = tal_dup_arr(txs, u8, db_column_blob(stmt, 2),
|
/* If this is a new entry, allocate it in the array and set
|
||||||
db_column_bytes(stmt, 2), 0);
|
* the common fields (all fields from the transactions
|
||||||
cur->blockheight = db_column_int(stmt, 3);
|
* table. */
|
||||||
cur->txindex = db_column_int(stmt, 4);
|
if (!bitcoin_txid_eq(&last, &curtxid)) {
|
||||||
cur->type = db_column_int(stmt, 5);
|
last = curtxid;
|
||||||
cur->channel_id = db_column_int(stmt, 6);
|
tal_resize(&txs, count + 1);
|
||||||
|
cur = &txs[count];
|
||||||
|
db_column_txid(stmt, 0, &cur->id);
|
||||||
|
cur->tx = db_column_tx(txs, stmt, 1);
|
||||||
|
cur->rawtx = tal_dup_arr(txs, u8, db_column_blob(stmt, 1),
|
||||||
|
db_column_bytes(stmt, 1), 0);
|
||||||
|
cur->blockheight = db_column_int(stmt, 2);
|
||||||
|
cur->txindex = db_column_int(stmt, 3);
|
||||||
|
if (!db_column_is_null(stmt, 4))
|
||||||
|
cur->annotation.type = db_column_u64(stmt, 4);
|
||||||
|
else
|
||||||
|
cur->annotation.type = 0;
|
||||||
|
if (!db_column_is_null(stmt, 5))
|
||||||
|
db_column_short_channel_id(stmt, 5, &cur->annotation.channel);
|
||||||
|
else
|
||||||
|
cur->annotation.channel.u64 = 0;
|
||||||
|
|
||||||
|
cur->output_annotations = tal_arrz(txs, struct tx_annotation, cur->tx->wtx->num_outputs);
|
||||||
|
cur->input_annotations = tal_arrz(txs, struct tx_annotation, cur->tx->wtx->num_inputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should always be set by the above if-statement,
|
||||||
|
* otherwise we have a txid of all 0x00 bytes... */
|
||||||
|
assert(cur != NULL);
|
||||||
|
|
||||||
|
/* Check if we have any annotations. If there are none the
|
||||||
|
* fields are all set to null */
|
||||||
|
if (!db_column_is_null(stmt, 6)) {
|
||||||
|
enum wallet_tx_annotation_type loc = db_column_int(stmt, 6);
|
||||||
|
int idx = db_column_int(stmt, 7);
|
||||||
|
struct tx_annotation *ann;
|
||||||
|
|
||||||
|
/* Select annotation from array to fill in. */
|
||||||
|
if (loc == OUTPUT_ANNOTATION)
|
||||||
|
ann = &cur->output_annotations[idx];
|
||||||
|
else if (loc == INPUT_ANNOTATION)
|
||||||
|
ann = &cur->input_annotations[idx];
|
||||||
|
else
|
||||||
|
fatal("Transaction annotations are only available for inputs and outputs. Value %d", loc);
|
||||||
|
|
||||||
|
ann->type = db_column_int(stmt, 8);
|
||||||
|
if (!db_column_is_null(stmt, 9))
|
||||||
|
db_column_short_channel_id(stmt, 9, &ann->channel);
|
||||||
|
else
|
||||||
|
ann->channel.u64 = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tal_free(stmt);
|
tal_free(stmt);
|
||||||
return txs;
|
return txs;
|
||||||
|
@ -219,6 +219,11 @@ enum wallet_payment_status {
|
|||||||
PAYMENT_FAILED = 2
|
PAYMENT_FAILED = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tx_annotation {
|
||||||
|
enum wallet_tx_type type;
|
||||||
|
struct short_channel_id channel;
|
||||||
|
};
|
||||||
|
|
||||||
static inline enum wallet_payment_status wallet_payment_status_in_db(enum wallet_payment_status w)
|
static inline enum wallet_payment_status wallet_payment_status_in_db(enum wallet_payment_status w)
|
||||||
{
|
{
|
||||||
switch (w) {
|
switch (w) {
|
||||||
@ -295,8 +300,17 @@ struct wallet_transaction {
|
|||||||
u32 blockheight;
|
u32 blockheight;
|
||||||
u32 txindex;
|
u32 txindex;
|
||||||
u8 *rawtx;
|
u8 *rawtx;
|
||||||
enum wallet_tx_type type;
|
|
||||||
u64 channel_id;
|
/* Fully parsed transaction */
|
||||||
|
const struct bitcoin_tx *tx;
|
||||||
|
|
||||||
|
struct tx_annotation annotation;
|
||||||
|
|
||||||
|
/* tal_arr containing the annotation types, if any, for the respective
|
||||||
|
* inputs and outputs. 0 if there are no annotations for the
|
||||||
|
* element. */
|
||||||
|
struct tx_annotation *input_annotations;
|
||||||
|
struct tx_annotation *output_annotations;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1179,7 +1193,7 @@ void free_unreleased_txs(struct wallet *w);
|
|||||||
*
|
*
|
||||||
* @param ctx: allocation context for the returned list
|
* @param ctx: allocation context for the returned list
|
||||||
* @param wallet: Wallet to load from.
|
* @param wallet: Wallet to load from.
|
||||||
* @return A tal_arr of wallet transactions
|
* @return A tal_arr of wallet annotated transactions
|
||||||
*/
|
*/
|
||||||
struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t *ctx);
|
struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t *ctx);
|
||||||
|
|
||||||
|
@ -936,12 +936,6 @@ static struct command_result *json_listtransactions(struct command *cmd,
|
|||||||
json_add_hex_talarr(response, "rawtx", txs[i].rawtx);
|
json_add_hex_talarr(response, "rawtx", txs[i].rawtx);
|
||||||
json_add_u64(response, "blockheight", txs[i].blockheight);
|
json_add_u64(response, "blockheight", txs[i].blockheight);
|
||||||
json_add_num(response, "txindex", txs[i].txindex);
|
json_add_num(response, "txindex", txs[i].txindex);
|
||||||
json_add_txtypes(response, "type", txs[i].type);
|
|
||||||
if (txs[i].channel_id != 0) {
|
|
||||||
json_add_num(response, "channel_id", txs[i].channel_id);
|
|
||||||
} else {
|
|
||||||
json_add_null(response, "channel_id");
|
|
||||||
}
|
|
||||||
json_object_end(response);
|
json_object_end(response);
|
||||||
}
|
}
|
||||||
json_array_end(response);
|
json_array_end(response);
|
||||||
|
Loading…
Reference in New Issue
Block a user