<blockquote>
  <p>How does a light node know which block its transaction got included in?</p>
</blockquote>

<p>Most SPV wallets use <a href="https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki" rel="nofollow noreferrer">BIP 37</a>. The protocol defined in BIP 37 is roughly as follows:</p>

<ol>
<li>Wallet sends to a full node a bloom filter which, when applied to transactions, indicates whether a transaction applies to that wallet.</li>
<li>Full nodes, for every block and transaction, applies the filter to see if there is a match.</li>
<li>If there is, relay the transactions to the wallet.</li>
<li>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.</li>
<li>Update the filter on matches.</li>
<li>When blocks are received, send the block header to the wallet.</li>
</ol>

<p>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.</p>

<p>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.</p>

<blockquote>
  <p>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?</p>
</blockquote>

<p>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.</p>

CC BY-SA 4.0
2018-09-12T19:49:17.727Z
2018-09-12T19:49:17.727Z
Ava Chow
<blockquote>
  <p><strong>How does a light node know which block its transaction got included in?</strong></p>
</blockquote>

<p>Lightweight clients use Simplified Payment Verification (SPV).</p>

<p><a href="https://en.bitcoin.it/wiki/Scalability#Simplified_payment_verification" rel="nofollow noreferrer">The Bitcoin wiki</a> says:</p>

<blockquote>
  <p>[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. </p>
</blockquote>

<p>Section 8 of <a href="https://bitcoin.org/bitcoin.pdf" rel="nofollow noreferrer">Satoshi Nakamoto's Bitcoin white paper</a> says</p>

<blockquote>
  <p>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.</p>
</blockquote>

<hr>

<p>See also:</p>

<ul>
<li><a href="https://bitcoin.stackexchange.com/q/36818/13866">How do SPV get their transactions after being offline?</a></li>
<li><a href="https://bitcoin.stackexchange.com/q/4649/13866">What is an SPV client?</a></li>
<li><a href="https://bitcoin.stackexchange.com/q/74285/13866">SPV Wallets vs API Wallets - Pragmatic</a></li>
<li><a href="https://bitcoin.stackexchange.com/q/35997/13866">How does an SPV node verify an unconfirmed transaction?</a></li>
<li><a href="https://bitcoin.stackexchange.com/q/53217/13866">How does SPV prevent double spending of UTXO?</a></li>
<li><a href="https://en.bitcoin.it/wiki/Thin_Client_Security" rel="nofollow noreferrer">Thin client security</a></li>
</ul>

CC BY-SA 4.0
2018-09-11T11:05:34.453Z
how does the full node know which block to search for the transaction in?
Does it persist all the accepted transactions? Or does it do a linear search across all blocks?
pd176
CC BY-SA 4.0
2018-09-11T11:08:06.513Z
@pd176 that's an implementation detail that probably varies depending on who wrote the code used by that node.
RedGrittyBrick
CC BY-SA 4.0
2018-09-11T10:01:36.157Z
2018-09-11T10:13:04.177Z
2018-09-11T10:13:04.177Z
RedGrittyBrick
<p>How does a light node know which block its transaction got included in?</p>

<p>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? </p>

<p>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?</p>

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

<transactions><spv>
Light clients transaction verification
pd176
# Light clients transaction verification

(Asked by: username_0 on 2018-09-11)

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!

**Tags:** transactions, spv


---

## 2 answers

### Answer by username_1 on 2018-09-12. Score: 2 | Accepted answer

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

Most SPV wallets use [BIP 37](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki). The protocol defined in BIP 37 is roughly as follows:

1. Wallet sends to a full node a bloom filter which, when applied to transactions, indicates whether a transaction applies to that wallet.
2. Full nodes, for every block and transaction, applies the filter to see if there is a match.
3. If there is, relay the transactions to the wallet.
4. 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.
5. Update the filter on matches.
6. 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.


---

### Answer by username_2 on 2018-09-11. Score: 1

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

Lightweight clients use Simplified Payment Verification (SPV).

[The Bitcoin wiki](https://en.bitcoin.it/wiki/Scalability#Simplified_payment_verification) says:

> [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.

Section 8 of [Satoshi Nakamoto's Bitcoin white paper](https://bitcoin.org/bitcoin.pdf) says

> 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.

---

See also:

* [How do SPV get their transactions after being offline?](https://bitcoin.stackexchange.com/q/36818/13866)
* [What is an SPV client?](https://bitcoin.stackexchange.com/q/4649/13866)
* [SPV Wallets vs API Wallets - Pragmatic](https://bitcoin.stackexchange.com/q/74285/13866)
* [How does an SPV node verify an unconfirmed transaction?](https://bitcoin.stackexchange.com/q/35997/13866)
* [How does SPV prevent double spending of UTXO?](https://bitcoin.stackexchange.com/q/53217/13866)
* [Thin client security](https://en.bitcoin.it/wiki/Thin_Client_Security)

> **Comments:**
> **username_0**: how does the full node know which block to search for the transaction in? Does it persist all the accepted transactions? Or does it do a linear search across all blocks?  
> **username_2**: @username_0 that's an implementation detail that probably varies depending on who wrote the code used by that node.  

---

