to take a dogecoin payment without trusting anyone, you need a full node
a phone cannot carry 13.6 gb of utxo set, so light wallets ask a server instead, and that server learns which addresses are yours. you are choosing between running a machine you probably do not want to run and telling a stranger what you own.
compact block filters are the fix for both halves of that. the node publishes a small summary of every block saying which scripts it touched, the wallet fetches summaries instead of blocks, and nobody has to be told which script was being looked for. bitcoin core has built the index since 0.19 and served it to peers since 0.21. dogecoin core has merged neither, so today every dogecoin light wallet either trusts a server or is not light.
the second thing it unlocks is small payments. a channel lets you pay the same person over and over with nothing touching the chain until you are done, so a coffee, a tip, a second of a stream or a single api call stops costing a transaction and a confirmation wait. that only works if the person being paid can check the funding is real in the time it takes to hand over the coffee, and checking it is exactly what needs the filters. the two are the same problem wearing different clothes.
47/47 answered the handshake and 1/47 advertise
NODE_COMPACT_FILTERS, and that one resolved to the prober's own public
ip.three things were built separately and they meet at one question, which is whether a given output is in the chain, buried and unspent. a full node answers it instantly and carries that 13.6 gb to do it. a filter client answers it from a bounded range of blocks. nothing else answers it without trusting the person doing the paying, which is the one thing a payment protocol exists to avoid.
run the channel in your browser
koinu is the client. it is a dogecoin wallet written in c that syncs and verifies compact block filters rather than downloading blocks, so it can find the outputs that pay a script without a chain of its own and without telling a server which script it cares about. the part that matters for merging anything is that its on-disk record is not a new format, and you can settle that by reading two files rather than by trusting anyone's comparison.
core v0.21.0 src/index/blockfilterindex.cpp
fileout << filter.GetBlockHash() << filter.GetEncodedFilter();
32-byte hash compactsize length, then the bytes
koinu net/cfstore.c:128-130
fwrite(block_hash, 1, 32, f); wr_varint(f, flen); fwrite(filter, 1, flen, f);
32-byte hash compactsize length then the bytes
koinu's wr_varint is bitcoin's compactsize to the byte: a single
byte under 0xfd, then 0xfd and a little-endian
uint16, 0xfe and a uint32, 0xff and a uint64. so the
records are the same by construction, not by coincidence. one difference, which
you would find yourself and should hear first: koinu tags a new file with four
magic bytes at offset 0 and core's fltr?????.dat has no file header
at all, so the records match and the files are offset by four bytes. the
measured comparison below is of records.
fltr00000.dat, 0 differing. the koinu author's measurement, not reproducible from this pagepayment-channel is an application that cannot work without the filters being served. it is a unidirectional channel: a customer funds a 2-of-2 with a timelocked refund, then pays the merchant as many times as they like off-chain, and only the last transaction is ever broadcast. the merchant signs nothing he has not checked, and every check he makes is local arithmetic except one. he cannot tell by himself whether the funding output is really on the chain, so he shells out to ask, and the customer is holding a socket open while that runs. the budget is three seconds.
bip157 and bip158 are what make that three seconds possible. the node builds
a small probabilistic filter per block describing which scripts it touched, the
client fetches filters instead of blocks, and a bounded range of them answers
"was this output paid, and has it been spent" without either side learning much.
bitcoin core added the index in 0.19.0.1, which explicitly did not serve filters
over p2p, and added serving in 0.21.0 behind
-blockfilterindex=1 -peerblockfilters=1. dogecoin core has neither,
so the client has the format right and nothing to talk to.
seed.dogecoin.wiki is NXDOMAIN; seed.dogecoin.com answers authoritatively with nonegettxoutsetinfonet/headers.h:87; the rest is multiplicationre-running that probe is harder than it was. two of the four seeds it asks
are gone, and seed.multidoge.org is a delegation to a seeder daemon
rather than a record, so a resolver that will not follow it returns nothing:
8.8.8.8 gives zero addresses for it today while
1.1.1.1 and 9.9.9.9 both give 25. a sceptic who runs
contrib/probe-filters.py on a google resolver gets an empty set and
concludes the tool is broken rather than that the seeds have decayed.
the shape of the question, and the exit codes that are the whole contract between the merchant and whatever he asks:
bob: kw outpoint --daemon /run/kwd.sock --watch 2NFrH5n… --outpoint a109176…:0 --since 400
unspent height 381 depth 6 value 10000000000 koinu → ship the goods
exit 3 → refuse, it is not there
exit 4 → refuse, it did not look far enough back
on provenance, since the whole point of a page like this is that it survives being checked. the channel numbers come from this repository and from payment-channel's own suite, and the commands that produce them are on the demo page. the record format above is two source files you can read. the pruning refusal, the seed decay and the resolver split were measured here and each one names the command. the six filter measurements are the koinu author's, taken on mainnet against a node we do not control, and nothing on this page lets you re-derive them: they are quoted because the structural claim they support can be checked independently, not as a substitute for it. there are no performance numbers for the pull request itself, measured or estimated, because none have been taken.
so the ask is to serve bip157 and bip158 from dogecoin core the way core upstream already does. an operator who turns it on pays for the index, and it is incompatible with pruning: dogecoind refuses to start with both, with "Prune mode is incompatible with -blockfilterindex". everyone running a light client stops needing a full node in order to accept a payment, and the format they read is the one core already writes.
that is pull request #4031,
open since 27 july 2026 with no review on it and no conflicts against master.
it asks for two things rather than one. alongside the filters it carries a
chainstate migration: the utxo set moves from one record per transaction to one
record per unspent output, upgrading in place on first start, and undo files it
writes cannot be read by earlier versions, so downgrading after it connects a
block needs a full -reindex. src/txdb.cpp carries both
the new DB_COIN and the legacy DB_COINS, which is the
migration in the code rather than in the notes. that is the larger ask by some
distance, and bundling the two explains three months of silence better than
disinterest does. the filter half is the half this page is about.