2021-12-04 11:23:56 +00:00
|
|
|
#include "config.h"
|
2017-11-27 15:17:43 +00:00
|
|
|
#include <bitcoin/script.h>
|
2021-09-16 06:00:42 +01:00
|
|
|
#include <ccan/crypto/siphash24/siphash24.h>
|
2018-02-26 12:39:09 +00:00
|
|
|
#include <ccan/mem/mem.h>
|
|
|
|
#include <common/memleak.h>
|
|
|
|
#include <common/pseudorand.h>
|
2021-12-04 11:23:56 +00:00
|
|
|
#include <wallet/txfilter.h>
|
2018-02-26 12:39:09 +00:00
|
|
|
#include <wallet/wallet.h>
|
2017-11-27 15:17:43 +00:00
|
|
|
|
2019-06-06 21:54:52 +01:00
|
|
|
static size_t scriptpubkey_hash(const u8 *out)
|
|
|
|
{
|
|
|
|
struct siphash24_ctx ctx;
|
|
|
|
siphash24_init(&ctx, siphash_seed());
|
|
|
|
siphash24_update(&ctx, out, tal_bytelen(out));
|
|
|
|
return siphash24_done(&ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const u8 *scriptpubkey_keyof(const u8 *out)
|
|
|
|
{
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int scriptpubkey_eq(const u8 *a, const u8 *b)
|
|
|
|
{
|
|
|
|
return memeq(a, tal_bytelen(a), b, tal_bytelen(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
HTABLE_DEFINE_TYPE(u8, scriptpubkey_keyof, scriptpubkey_hash, scriptpubkey_eq, scriptpubkeyset);
|
|
|
|
|
2017-11-27 15:17:43 +00:00
|
|
|
struct txfilter {
|
2019-06-06 21:54:52 +01:00
|
|
|
struct scriptpubkeyset scriptpubkeyset;
|
2017-11-27 15:17:43 +00:00
|
|
|
};
|
|
|
|
|
2021-10-13 04:45:36 +01:00
|
|
|
static size_t outpoint_hash(const struct bitcoin_outpoint *out)
|
2018-02-26 12:39:09 +00:00
|
|
|
{
|
|
|
|
struct siphash24_ctx ctx;
|
|
|
|
siphash24_init(&ctx, siphash_seed());
|
|
|
|
siphash24_update(&ctx, &out->txid, sizeof(out->txid));
|
2021-10-13 04:45:36 +01:00
|
|
|
siphash24_u32(&ctx, out->n);
|
2018-02-26 12:39:09 +00:00
|
|
|
return siphash24_done(&ctx);
|
|
|
|
}
|
|
|
|
|
2021-10-13 04:45:36 +01:00
|
|
|
static const struct bitcoin_outpoint *outpoint_keyof(const struct bitcoin_outpoint *out)
|
2018-02-26 12:39:09 +00:00
|
|
|
{
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2021-10-13 04:45:36 +01:00
|
|
|
HTABLE_DEFINE_TYPE(struct bitcoin_outpoint, outpoint_keyof, outpoint_hash, bitcoin_outpoint_eq,
|
2018-02-26 12:39:09 +00:00
|
|
|
outpointset);
|
2017-11-27 15:17:43 +00:00
|
|
|
|
2018-02-26 12:39:09 +00:00
|
|
|
struct outpointfilter {
|
|
|
|
struct outpointset *set;
|
|
|
|
};
|
2017-11-27 15:17:43 +00:00
|
|
|
|
|
|
|
struct txfilter *txfilter_new(const tal_t *ctx)
|
|
|
|
{
|
|
|
|
struct txfilter *filter = tal(ctx, struct txfilter);
|
2019-06-06 21:54:52 +01:00
|
|
|
scriptpubkeyset_init(&filter->scriptpubkeyset);
|
2017-11-27 15:17:43 +00:00
|
|
|
return filter;
|
|
|
|
}
|
|
|
|
|
2018-03-07 00:06:01 +00:00
|
|
|
void txfilter_add_scriptpubkey(struct txfilter *filter, const u8 *script TAKES)
|
2017-11-27 15:17:43 +00:00
|
|
|
{
|
2019-06-06 21:54:52 +01:00
|
|
|
scriptpubkeyset_add(
|
|
|
|
&filter->scriptpubkeyset,
|
2020-02-27 02:17:01 +00:00
|
|
|
notleak(tal_dup_talarr(filter, u8, script)));
|
2017-11-27 15:17:43 +00:00
|
|
|
}
|
|
|
|
|
2018-03-07 00:06:01 +00:00
|
|
|
void txfilter_add_derkey(struct txfilter *filter,
|
pubkey: rename PUBKEY_DER_LEN to PUBKEY_CMPR_LEN.
Pubkeys are not not actually DER encoding, but Pieter Wuille corrected
me: it's SEC 1 documented encoding.
Results from 5 runs, min-max(mean +/- stddev):
store_load_msec,vsz_kb,store_rewrite_sec,listnodes_sec,listchannels_sec,routing_sec,peer_write_all_sec
38922-39297(39180.6+/-1.3e+02),2880728,41.040000-41.160000(41.106+/-0.05),2.270000-2.530000(2.338+/-0.097),44.570000-53.980000(49.696+/-3),32.840000-33.080000(32.95+/-0.095),43.060000-44.950000(43.696+/-0.72)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-04-08 07:34:05 +01:00
|
|
|
const u8 derkey[PUBKEY_CMPR_LEN])
|
2017-11-27 15:17:43 +00:00
|
|
|
{
|
2023-07-10 17:27:43 +01:00
|
|
|
u8 *skp, *p2sh, *p2tr;
|
2017-11-27 15:17:43 +00:00
|
|
|
|
|
|
|
skp = scriptpubkey_p2wpkh_derkey(tmpctx, derkey);
|
|
|
|
p2sh = scriptpubkey_p2sh(tmpctx, skp);
|
2023-07-10 17:27:43 +01:00
|
|
|
p2tr = scriptpubkey_p2tr_derkey(tmpctx, derkey);
|
2017-11-27 15:17:43 +00:00
|
|
|
|
|
|
|
txfilter_add_scriptpubkey(filter, take(skp));
|
|
|
|
txfilter_add_scriptpubkey(filter, take(p2sh));
|
2023-07-10 17:27:43 +01:00
|
|
|
txfilter_add_scriptpubkey(filter, take(p2tr));
|
2017-11-27 15:17:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool txfilter_match(const struct txfilter *filter, const struct bitcoin_tx *tx)
|
|
|
|
{
|
2019-03-25 10:35:56 +00:00
|
|
|
for (size_t i = 0; i < tx->wtx->num_outputs; i++) {
|
|
|
|
const u8 *oscript = bitcoin_tx_output_get_script(tmpctx, tx, i);
|
2017-11-27 15:17:43 +00:00
|
|
|
|
2019-04-13 18:14:07 +01:00
|
|
|
if (!oscript)
|
|
|
|
continue;
|
|
|
|
|
2019-06-06 21:54:52 +01:00
|
|
|
if (scriptpubkeyset_get(&filter->scriptpubkeyset, oscript))
|
|
|
|
return true;
|
2017-11-27 15:17:43 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-02-26 12:39:09 +00:00
|
|
|
|
2021-10-13 04:45:36 +01:00
|
|
|
void outpointfilter_add(struct outpointfilter *of,
|
|
|
|
const struct bitcoin_outpoint *outpoint)
|
2018-02-26 12:39:09 +00:00
|
|
|
{
|
2021-10-13 04:45:36 +01:00
|
|
|
if (outpointfilter_matches(of, outpoint))
|
2018-02-26 12:39:09 +00:00
|
|
|
return;
|
|
|
|
/* Have to mark the entries as notleak since they'll not be
|
|
|
|
* pointed to by anything other than the htable */
|
2021-10-13 04:45:36 +01:00
|
|
|
outpointset_add(of->set, notleak(tal_dup(of->set,
|
|
|
|
struct bitcoin_outpoint,
|
|
|
|
outpoint)));
|
2018-02-26 12:39:09 +00:00
|
|
|
}
|
|
|
|
|
2021-10-13 04:45:36 +01:00
|
|
|
bool outpointfilter_matches(struct outpointfilter *of,
|
|
|
|
const struct bitcoin_outpoint *outpoint)
|
2018-02-26 12:39:09 +00:00
|
|
|
{
|
2021-10-13 04:45:36 +01:00
|
|
|
return outpointset_get(of->set, outpoint) != NULL;
|
2018-02-26 12:39:09 +00:00
|
|
|
}
|
|
|
|
|
2021-10-13 04:45:36 +01:00
|
|
|
void outpointfilter_remove(struct outpointfilter *of,
|
|
|
|
const struct bitcoin_outpoint *outpoint)
|
2018-02-26 12:39:09 +00:00
|
|
|
{
|
2021-10-13 04:45:36 +01:00
|
|
|
outpointset_del(of->set, outpoint);
|
2018-02-26 12:39:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct outpointfilter *outpointfilter_new(tal_t *ctx)
|
|
|
|
{
|
|
|
|
struct outpointfilter *opf = tal(ctx, struct outpointfilter);
|
|
|
|
opf->set = tal(opf, struct outpointset);
|
|
|
|
outpointset_init(opf->set);
|
|
|
|
return opf;
|
|
|
|
}
|