How does a light node know which block its transaction got included in?

Say a light node sends out a transaction spending its UTXO. Does it get some sort of notification when its transaction is mined in some block or does it need to manually ask a full node if its transaction is present in every new block that is mined after it made the transaction?

Also, say a wallet program was loaded after a month of inactivity. Now the wallet needs to know the balance of its address? How does it go about reconstructing its balance after downloading the latest block headers?

Note here that I'm asking about the low level apis and not any service like a block explorer!

2 Answers
2

How does a light node know which block its transaction got included in?

Most SPV wallets use BIP 37. The protocol defined in BIP 37 is roughly as follows:

Wallet sends to a full node a bloom filter which, when applied to transactions, indicates whether a transaction applies to that wallet.

Full nodes, for every block and transaction, applies the filter to see if there is a match.

If there is, relay the transactions to the wallet.

If there is a match for a transaction in a block, generate a merkle proof and send the proof with the transaction to the wallet.

Update the filter on matches.

When blocks are received, send the block header to the wallet.

This is generally how all SPV wallets work too, even ones that don't use BIP 37. They may not use bloom filters, but they use some kind of filter and rely on a full node to check things against the filter and then send along the things that match.

For privacy reasons, the filters do not match exactly. They have a false positive rate (but not a false negative rate) so some things are sent to the wallet that do not apply to it. The wallet just ignores those things.

Also, say a wallet program was loaded after a month of inactivity. Now the wallet needs to know the balance of its address? How does it go about reconstructing its balance after downloading the latest block headers?

It connects to a full node, sends it the filter to use, and then asks the node to send all of the transactions that match that filter that are in all blocks since block X where X is the latest block header the wallet has.

[SPV] clients connect to an arbitrary full node and download only the block headers. They verify the chain headers connect together correctly and that the difficulty is high enough. They then request transactions matching particular patterns from the remote node (ie, payments to your addresses), which provides copies of those transactions along with a Merkle branch linking them to the block in which they appeared. This exploits the Merkle tree structure to allow proof of inclusion without needing the full contents of the block.

It is possible to verify payments without running a full network node. A user only needs to keep a copy of the block headers of the longest proof-of-work chain, which he can get by querying network nodes until he’s convinced he has the longest chain, and obtain the Merkle branch linking the transaction to the block it’s timestamped in. He can’t check the transaction for himself, but by linking it to a place in the chain, he can see that a network node has accepted it, and blocks added after it further confirm the network has accepted it.