How does a light client via SPV make sure that the requested merkle path is not fake?
I know that the client has its own copy of the block headers, so it can trust the merkle root from there. It then queries a full node for the merkle path, calculates the merkle root from that, and finally compares the reference merkle root with the calculated one. If both are the same, the client can be sure the transaction was included, even if it does not trust the full node, since there is no way for the full node to engineer the same merkle root from different data. So far so good.
However, how can it trust the received path in case both merkle roots do not match? The full node could send a fake path, which then leads to a different merkle root upon verification, which let's the client assume the transaction was not included when in reality it might have been included.
Can someone please clarify? Thanks :)
UPDATE: Thanks to the answers and many comments I now understand that SPV via merkle root does not prove non-inclusion of a transaction in a specific block. In can only prove inclusion. In case the merkle roots match, we can be sure that the transaction is included in the block. If the merkle roots do not match, then the transaction could be included (fake path received) or not (legitimate path received), we don't know for sure.
In order to prove inclusion AND non-inclusion, it is probably easier and more secure to just have the transaction data of the block in question, received from a trusted full node.
Other 'workarounds' could be to:
- trust the server
- query multiple servers
- ignore the merkle root mismatch (do nothing, notify the user)
Finally it turns out that merkle trees are not really that useful since SPV does not really work the way it was supposed to and that's why it is rarely used. A simple hash over all transaction would have worked as well.
Another addition, thanks to @Pieter Wuille for the hints: A possible advantage of using merkle trees would be that inclusion can be proved by just a single legitimate path when querying multiple servers, because a valid merkle proof cannot be faked. That means all non-matching proofs (when querying multiple servers) can just be ignored in case there is a single one that matches.
Thank you everybody for the help!