Operating Modes

The BitcoinEvo Software employs various levels of security and trade-offs to ensure the blockchain is properly verified.

Introduction

At present, there are two main methods clients use to validate the blockchain: Full nodes and SPV clients. Other approaches, such as those that trust servers, are not covered here as they are generally not advisable.

Full Node

The most secure method, employed by BitcoinEvo Core, is what’s often referred to as a “full” or “complete” chain client. This model ensures the blockchain’s integrity by downloading and verifying all blocks, starting from the first (genesis) block to the latest block. This process uses the height of a specific block to confirm the client’s perspective of the network.

For an attacker to deceive a client, they would need to present an entirely different blockchain history with greater difficulty than the current “true” chain. This is practically infeasible because the chain with the most cumulative proof of work is, by design, considered the “true” chain. Since creating new blocks at the chain’s tip is computationally demanding, misleading a full node becomes highly unlikely after 6 confirmations. This verification method is also strongly resistant to sybil attacks, as only one honest network peer is necessary to retrieve and confirm the legitimate state of the blockchain.


Block Height Compared To Block Depth

Simplified Payment Verification (SPV)

An alternative method outlined in the Whitepaper involves a client that downloads only the block headers during the initial synchronization, and then queries full nodes for specific transactions when needed. This approach scales with the blockchain height, requiring only 80 bytes per block header, which amounts to about 4.2MB per year, independent of the total block size.

As explained in the white paper, the merkle root contained in the block header, along with a merkle branch, can verify for the SPV client that a specific transaction is part of the blockchain. However, this does not ensure the authenticity of the transaction itself. Instead, it shows how much effort would be required to execute a double-spend attack.

The depth of a block within the blockchain reflects the cumulative difficulty added by building subsequent blocks on top of it. The SPV client is aware of the merkle root and related transaction details, and it requests the corresponding merkle branch from a full node. Once the merkle branch is retrieved, proving the transaction’s inclusion in the block, the SPV client can use the block depth as an indicator of the transaction’s security and validity. The difficulty and cost for a malicious node to alter the transaction grows with the cumulative work added to the blockchain, as the rogue node would need to mine this altered chain alone.

Potential SPV Weaknesses

If not implemented carefully, SPV clients have some notable vulnerabilities.

Firstly, while it’s difficult to trick an SPV client into believing a transaction is in a block when it’s not, the opposite is possible. A full node can simply withhold information, causing the SPV client to think that a transaction has not occurred. This can be viewed as a form of Denial of Service (DoS). One way to reduce this risk is to connect to multiple full nodes and send the same request to each, although this method can be undermined by network partitioning or Sybil attacks, given the ease of creating fake identities, and it may consume a lot of bandwidth. It’s essential to ensure that the client maintains access to trustworthy nodes.

Secondly, an SPV client only requests transactions associated with the keys it owns from full nodes. If it downloads all the blocks and discards the irrelevant ones, it can consume excessive bandwidth. On the other hand, if it simply asks for specific transactions from the full nodes, this could expose the public addresses linked to the user, resulting in a significant privacy issue. This makes users vulnerable to attacks like DoS against specific clients, users, or addresses, and makes it easy to link funds. A client could send out numerous fake transaction requests to obscure this, but that would place a heavy load on the SPV client, potentially undermining the purpose of a thin client.

To address this privacy concern, Bloom filters have been introduced as a means of compressing and obfuscating the data requests related to blocks.

Bloom Filters

A Bloom filter is an efficient probabilistic data structure designed for testing whether an element is a member of a set. It offers excellent data compression but allows for a controlled false positive rate.

A Bloom filter begins as an array of n bits, all initialized to 0. A set of k random hash functions is selected, each of which generates an integer value within the range of 1 to n.

To add an element to the Bloom filter, the element is hashed k separate times, and for each hash result, the bit at the corresponding index in the filter is set to 1.

When querying the Bloom filter, the same k hash functions are applied to the element. If all k bits accessed are set to 1, it indicates with high probability that the element is in the set. However, due to the possibility of collisions with other elements, the Bloom filter may produce false positives. The acceptable false positive rate can be adjusted by the user based on the chosen parameters.

Elements cannot be removed individually from a Bloom filter. Instead, the entire filter must be discarded and recreated from scratch if necessary.

Application Of Bloom Filters

Rather than viewing the false positive rate as a drawback, it can be treated as a controllable parameter that influences the balance between privacy and bandwidth usage. An SPV client creates its Bloom filter and sends it to a full node using the filterload message, which sets the filter for identifying relevant transactions. The filteradd command allows additional data to be added to the filter without needing to resend the entire Bloom filter, while filterclear resets the filter, reverting to standard block discovery methods. Once a filter is loaded, full nodes send a modified version of blocks, known as merkle blocks. These include the block header and the merkle branch that corresponds to the loaded Bloom filter.

An SPV client can include not only transactions but also public keys, data from signature scripts, pubkey scripts, and more in the filter. This capability enables the discovery of P2SH transactions.

For users who prioritize privacy, the Bloom filter can be adjusted to generate more false positives, increasing privacy at the cost of higher bandwidth consumption. Conversely, users with limited bandwidth can reduce the false-positive rate, though this gives full nodes a clearer view of which transactions are relevant to the client.

Future Proposals

Looking ahead, proposals like Unspent Transaction Output (UTXO) commitments in the blockchain aim to provide a better balance between requiring a full copy of the blockchain and trusting that most connected peers are honest. UTXO commitments would allow for highly secure clients with limited storage by utilizing an authenticated data structure within the blockchain. However, these proposals are still in the early stages of development and would require soft forks to be implemented in the network.

Until such improvements are adopted, users should select operating modes based on the anticipated threat model, their computing and bandwidth resources, and the level of liability in BitcoinEvo value.