I have chosen to write a code explanation of the initial version of bitcoin, akka bitcoin v0.1. I hope it helps you to understand better the fundational concepts behind bitcoin, and get an overview how bitcoin actually works behind the scene. Thus, I hope it helps to provide you the necessary confidence to become a long term investor in bitcoin
The bitcoin v0.1 code is available here : https://tinyurl.com/k24m7p9c. It is written mainly in C++
It is released under the MIT X11 licence, that means anyone can copy and modify it
The bitcoin Core software .exe can be launched here : https://tinyurl.com/3ttejt9w
There are two .dll files included :
- libeay32.dll -> this is the OpenSSL encryption library, used by the .exe to create the encryption keys
- mingwm10.dll -> it is a free and open source Windows port of the GCC compiler. It is necessary to launch Qt, which powers the GUI “Graphical User Interface” engine used by the .exe
The bitcoin Core is mainly usefull to send bitcoin from one address to another address, without any intermediary
Code summary
Now let’s go through the code. I have created a summary table, to provide an overview, before going into the details of each file
Overall, bitcoin core v0.1 has 31 794 lines of code. The biggest files being the GUI management (Graphical User Interface) – by far the biggest – and the blockchain operation (blocks, proof of work, cryptography). All the other files are much smaller but also an essential part of the software
File | Lines | Purpose | % of total lines |
---|---|---|---|
base58.h | 201 | Implements base58 encoding and decoding functionalities specifically used for bitcoin addresses. base58 is a specific variant of base64 encoding that avoids visually similar characters and aims to produce more user-friendly output. The code includes methods for encoding and decoding both standard and checksum-enhanced base58 representations of bitcoin addresses | 1% |
bignum.h | 498 | This code involves the definition and implementation of several classes and functions that deal with precision arithmetics for cryptographic applications. This kind of functionality is critical in blockchain technology, cryptocurrencies, and any applications that require handling large integers, such as those used in cryptography | 2% |
db.cpp | 604 | This code focuses on database operations for managing transactions, addresses, and wallets. It includes functionality for initializing the database, reading and writing to it, and managing the wallet’s state | 2% |
db.h | 420 | This code focuses on database operations for managing transactions, addresses, and wallets. It includes functionality for initializing the database, reading and writing to it, and managing the wallet’s state | 1% |
headers.h | 71 | This code imports many important libraries and links the .h files together. It is a small file but an essential part | 0% |
irc.cpp | 265 | This code provides the infrastructure for managing network communications using IRC. The encoding and decoding functions ensure that addresses are processed safely and effectively, while the variant functions for sending and receiving data handle the specifics of socket communication. The threaded operation allows for asynchronous processing of network events, necessary in the context of real time and peer to peer transactions | 1% |
irc.h | 7 | This code is the header file of irc.cpp and is important to implement asynchronous connections and the network decentralization | 0% |
key.h | 156 | This code defines the cryptographic key management system, using elliptic curve digital signature algorithm (ECDSA) | 0% |
main.cpp | 2660 | This code implements the blockchain management of transactions, wallets, and blocks. It employs locking mechanisms to prevent data corruption in concurrent environments and maintains an in-memory database to facilitate quick access and updates | 8% |
main.h | 1297 | This code is the header file of main.cpp. The implementation includes mechanisms for memory management, transaction validation, and persistence in a database | 4% |
makefile | 83 | The provided code is designed to automate the compilation and linking process, defining how to build the application, manage dependencies, and specify settings for the compiler | 0% |
makefile.vc | 77 | This file is used by makefile for building the bitcoin Windows application. It uses Microsoft Visual C++ compiler commands, preprocessor directives, and settings for linking with various libraries such as OpenSSL, wxWidgets, and Berkeley DB | 0% |
market.cpp | 264 | This is a partially completed distributed market place. It was not implemented in later versions of bitcoin core | 1% |
market.h | 182 | It is the header file of market.cpp. It ensures the market place can securely identify users and verify actions within the application | 1% |
net.cpp | 1020 | The code ensures that the application can reliably communicate over the peer to peer network, establish connection threads, and terminate operations when required | 3% |
net.h | 856 | This is the header file of net.cpp, implementing the communication between network nodes | 3% |
script.cpp | 1127 | Bitcoin is programmable money. Bitcoin core uses scripts that are run into a stack, and opcodes are the underlying operations that help build the bitcoin scripts | 4% |
script.h | 597 | This is the header file of script.cpp. It defines the conditions under which funds can be unlocked and spent | 2% |
serialize.h | 1151 | This code implements serialization. The code converts objects of a particular class into a stream of bytes. It is used to store it in memory or transmit it over the network | 4% |
shap.cpp | 554 | This code is the hashing utility and the cryptographic foundation of bitcoin. Hash functions ensure that data is secure and allow users to verify the integrity of transaction data | 2% |
sha.h | 177 | This is the header file of sha.cpp. It is essential for initializing hash states, transforming data for hashing, and byte order manipulation | 1% |
ui.cpp | 3228 | This code implements the GUI (Graphical User Interface). It uses the wxWidgets library. The code includes several classes that represent different dialogs and interactions within the application, such as sending money and managing an address book | 10% |
ui.h | 412 | This is the header file of ui.cpp | 1% |
ui.rc | 14 | This resource file declares various graphical assets utilized in wxWidgets | 0% |
uibase.cpp | 1806 | This file structures the GUI elements, manages events and functionalities related to user inputs, such as sending bitcoin | 6% |
uibase.h | 720 | This header file defines several base dialog classes generated with wxFormBuilder | 2% |
unint256.h | 750 | This code includes definitions for handling large integers using the uint256 class. This class is necessary for managing values that exceed the size of standard built-in data types, as is the case for bitcoin hashes and addresses | 2% |
uiproject.fbp | 11825 | This code is the XML representation of the wxWidgets. The XML format is used to describe various objects, properties, and events | 37% |
util.cpp | 373 | The code is responsible for various utilities in bitcoin, such as multithreading support for OpenSSL, generating random numbers, file management, time synchronization, and custom error handling | 1% |
util.h | 399 | This is the header file of util.cpp. It covers type definitions, error handling, hash functions, and more | 1% |
base58.h
This file implements base58 encoding and decoding functionalities specifically used for bitcoin addresses. Here is base58.h : https://tinyurl.com/4j2rdrvj
The first line defines the character set for Base58 encoding. The characters 0
, O
, I
, and l
are excluded to avoid visual ambiguity
- EncodeBase58 encodes data into base58 string format
- EncodeBase58check extends EncodeBase58 by appending a 4-byte hash (checksum) to the end of the data before encoding. This helps in verifying the integrity of the address
- Hash160ToAddress takes a hashed public key and prefixes it with a version byte before producing a Base58Check encoded string (bitcoin address)
- IsValidBitcoinAddress checks whether a given address is valid by attempting to decode it
- PubKeyToAddress converts a public key into its corresponding bitcoin address using Hash160 and Hash160ToAddress
bignum.h
This code is implemented to manage large integers in the cryptography component of bitcoin. Here is bignum.h : https://tinyurl.com/43y92jb2
- The code utilizes OpenSSL big numbers functionality
- CBigNum is a custom class that inherits from OpenSSL bignum. It includes some important methods (constructors, arithmetic operations, conversion methods,…), and also operators overload and bitwise operations
- The serialize methods allow for serialization and deserialization of CBigNum objects
db.cpp, db.h
This code focuses on database operations for managing transactions, addresses, and wallets. It includes functionality for initializing the database, reading and writing to it, and managing the wallet’s state. The database is based upon Berkeley DB (https://tinyurl.com/mr2zb4hw)
The db.cpp file is here : https://tinyurl.com/3zfe8x4t
- The DbEnv is an object representing the Berkeley DB environmnt
- The class CDBInit initializes the database environment in its constructor
- The CDB constructor tries to open a database file with the specified mode (r, w, c, etc.) and initializes various settings associated with the BDB environment
- The CTxDB class handles transaction data in the database (reading, updating, deleting transaction entries based on their hashes)
- The CAddrDB class is responsible to manage addresses in the database (write new addresses, load existing ones)
- The CWalletDB class manages wallet data, including reading and writing wallet entries, such as addresses and transactions
The db.h file is here : https://tinyurl.com/ea39pj4s
- The code starts by including the Berkeley DB header and classes used throughout the database operations. It uses several external variables for managing the address book, client status, and database environment configuration
- The CDB class is defined, with a constructor taking the file name and opening the BD database, and handling transactions in argument, and with a destructor closing the database.
- The CTxDB class manages transaction metadata
headers.h
This code imports many important libraries and links the .h files together. Here is headers.h : https://tinyurl.com/yerp5r9s
- Preprocessor directives
Theses directives check if the code is compiled with Microsoft Visual C++ and disable specific compiler warnings
It is also targeting Windows 95 (0x0400) instead of a later version
- These libraries provide a wide range of functionalities, from UI components and cryptography to standard I/O operations and memory management
- Additional libraries are included, to perform operations on data structures and algorithms. The boost library is also used (https://www.boost.org/)
- The local headers are also included, that contain application-specific code that deals with serialization, cryptography, transaction handling, user interface, and networking features
irc.cpp, irc.h
Support for the IRC communication chanel was removed from bitcoin core in March 2014 (see this Wiki about IRC : https://en.wikipedia.org/wiki/IRC)
Here is irc.cpp : https://tinyurl.com/yvw3xnz2
It enables the software to connect with other nodes using IRC, allowing for the exchange of information. Key functionalities include encoding and decoding addresses, sending and receiving messages, handling connections, and managing the state of sockets
- ThreadIRCSeed handles the connection to an IRC server for broadcasting and receiving bitcoin node messages. It processes various IRC commands, enabling interaction with other nodes in the network via IRC
Here is irc.h : https://tinyurl.com/mrypzyt2
- It is used for the setup of the network socket connection, and the corresponding IRC thread
key.h
This file is an implementation of key management and cryptographic operations using Elliptic Curve Cryptography (ECC), specifically bitcoin publick-key cryptography secp256k1 (https://en.bitcoin.it/wiki/Secp256k1), which is now commonly used in cryptocurrencies
Here is key.h : https://tinyurl.com/3c3tc377
- The code contains commented constants representing the sizes of private keys, public keys, and signatures for elliptic curves
A secure_allocator is designed to manage sensitive data like private keys. The vector part represents a dynamic array that can hold bytes. This byte array is used to store binary data, such as private keys, serialized objects, or any byte sequence
- The Ckey class contains many important methods : constructor and desctructor, key management, public key management, signature operations, static signature methods
main.cpp
This code implements the blockchain management of transactions, wallets, and blocks. Here is the main.cpp : https://tinyurl.com/ujf6u85z
As the code is very long, I provide a summary table of each function or method. I then provide a few more detailed analysis
Function name | Start line | Purpose |
---|---|---|
AddKey | 65 | Add a cryptographic key to the wallet, which will be used to handle Bitcoin transactions |
GenerateNewKey | 75 | Generates a key, adds it to the wallet, and returns the public part of the key |
AddToWallet | 92 | Adds a transaction (CWalletTx) to a Bitcoin wallet. It handles both inserting new transactions and updating existing transactions |
AddToWalletIfMine | 149 | Adds a transaction to a wallet if it is determined that the wallet owns the corresponding coins (the transaction is “mine”). If the transaction is already present in the wallet, it ensures that it is updated appropriately |
EraseFromWallet | 162 | Removes a transaction from a Bitcoin wallet based on its transaction hash. This function ensures that both the in-memory representation and persistent storage are updated |
AddOrphanTx | 185 | Adds a transaction to a collection of orphan transactions in a Bitcoin wallet or node. Orphan transactions are those that cannot be fully processed because they depend on inputs that are not currently available in the local node’s memory |
EraseOrphanTx | 197 | Removes a specified orphan transaction from the collection of orphan transactions in a Bitcoin wallet or node. This function ensures that orphan transactions are properly removed from memory when they are no longer needed |
CTxIn::IsMine | 231 | Member function of the CTxIn class, which represents an input in a Bitcoin transaction. This function determines whether the output being referenced by the transaction input belongs to the wallet, meaning it checks if the wallet controls that specific input |
CTxIn::GetDebit | 247 | Member function of the CTxIn class, which represents an input in a Bitcoin transaction. This function is used to calculate the debit amount for that specific transaction input, effectively determining how much currency is being spent from the wallet |
CWalletTx::GetTxTime | 263 | Member function of the CWalletTx class, which represents a transaction in a wallet. This function determines the time associated with the transaction, either by using the time it was received or, if it wasn’t received directly, by using the time of the block in which it was included |
CMerkleTx:: SetMerkleBranch | 286 | Sets the Merkle branch for a given transaction within a block in a Bitcoin wallet or node implementation. This branch allows the transaction to be verified as part of a block’s Merkle tree, which ensures the integrity and inclusion of the transaction in that block |
CWalletTx:: AddSupportingTransactions | 339 | Retrieves and manages the supporting transactions that are associated with a given transaction (represented by CWalletTx). It gathers transactions that are inputs to the current transaction, enabling the wallet to maintain a complete context of the transactions involved |
CTransaction:: AcceptTransaction | 406 | Validates and accepts a new transaction into memory or the transaction pool. It checks for errors, conflicts with existing transactions, and dependencies on previous transactions |
CTransaction:: AddToMemoryPool | 481 | Adds a transaction to the in-memory transaction pool (mempool). This function is designed to be called only by other functions (like AcceptTransaction), which ensures that the transaction is valid before it is added |
CTransaction:: RemoveFromMemoryPool | 497 | Removes a transaction from the in-memory transaction pool (mempool) |
CMerkleTx:: GetDepthInMainChain | 515 | Assesses where the transaction is within the blockchain, based on its position in the tree structure of blocks (and their associated transactions) and ensures that it is indeed part of the main chain |
CMerkleTx:: GetBlocksToMaturity | 540 | Determines how many additional blocks need to be mined before a coinbase transaction (the first transaction in a block that creates new coins) can be considered mature and the funds can be spent |
CMerkleTx:: AcceptTransaction | 548 | Accepts a transaction while considering whether it is being processed in a client mode or a full node mode |
CWalletTx:: AcceptWalletTransaction | 564 | Accepts transactions into the wallet while checking any associated previous transactions (inputs) that the current transaction depends on |
ReacceptWalletTransactions | 583 | Re-accepts transactions that belong to the wallet but are not currently associated with any blocks on the blockchain. This function loops through all transactions in the wallet and ensures they remain valid and are accepted into the wallet’s transaction pool again |
CWalletTx:: RelayWalletTransaction | 599 | Broadcasts a wallet transaction and its associated previous transactions across the network to ensure that they are relayed to other nodes, as transactions need to be propagated for inclusion in blocks |
RelayWalletTransactions | 621 | Relays transactions within the decentralized Bitcoin network |
CBlock::ReadFromDisk | 662 | Member function of the CBlock class, responsible for reading a block from disk storage based on its index information |
GetOrphanRoot | 667 | Determines the original block that is at the base of an orphan block tree |
CBlock::GetBlockValue | 675 | Calculates the total value (or reward) that a block provides to the miner who successfully creates it, taking into account both the block subsidy and the transaction fees associated with the transactions included in the block |
GetNextWorkRequired | 685 | Calculates the difficulty target for the next block based on the time taken to mine previous blocks, ensuring that new blocks continue to be produced at a steady rate |
CTransaction:: DisconnectInputs | 739 | Responsible for undoing the effects of a transaction, when a block is confirmed or re-processed. This function effectively “disconnects” a transaction by marking its inputs as unspent, allowing those outputs to be reused in future transactions |
CTransaction:: ConnectInputs | 772 | Validates that the inputs of the transaction can be connected to the Bitcoin network by ensuring that they are currently unspent and that all signatures and conditions are met |
CTransaction:: ClientConnectInputs | 873 | Checks and validates the inputs of a transaction specifically for a client (such as a lightweight client that does not have a full transaction database) |
CBlock::DisconnectBlock | 918 | Removes the transactions contained in the block and updates the disk index accordingly |
CBlock::ConnectBlock | 937 | Accepts a block and processes its transactions, ensuring they are valid and updating the blockchain state accordingly |
Reorganize | 974 | Handles the transition between different branches of the blockchain. When the blockchain experiences a fork (due to conflicting blocks), this function will reorganize the blockchain to ensure the longest valid chain is retained and that the state of transactions is accurately reflected |
CBlock::AddToBlockIndex | 1072 | Adds a new block to the blockchain index, ensuring that the block’s information is properly recorded, and manages the relationships between different blocks in the blockchain |
CBlock::CheckBlock | 1154 | Validates a block’s integrity and compliance with the protocol’s rules before it can be added to the blockchain, or even stored as an orphan block |
CBlock::AcceptBlock | 1194 | Validates and accepts a block into the blockchain. It performs various essential checks and operations to ensure the integrity of the blockchain structure |
ProcessBlock | 1236 | Handles incoming blocks from peers, validates them, and integrates them into the blockchain. This function first checks for duplicates, validates the block, and handles orphan blocks that depend on it |
ScanMessageStart | 1304 | Scans a data stream for a specific message start prefix, which is a critical part of the Bitcoin protocol for ensuring that communications between nodes are properly formatted |
GetAppDir | 1344 | Determines the application directory for the Bitcoin wallet application, returning a string that represents the path where the application data should be stored. It checks various locations, including environment variables, to set this directory |
OpenBlockFile | 1379 | Handles reading and writing blocks to disk while ensuring that they fit within storage limits and perform necessary operations safely |
AppendBlockFile | 1399 | Handles reading and writing blocks to disk while ensuring that they fit within storage limits and perform necessary operations safely |
LoadBlockIndex | 1420 | Loads existing blocks from the transaction database but also handles the creation and addition of the genesis block, which is the very first block in the Bitcoin blockchain |
PrintBlockTree | 1496 | Designed to visualize the structure of the blockchain by printing the relationships between blocks in a tree-like format. It allows users or developers to see how blocks are linked in terms of their parent-child relationships, along with other relevant information such as transaction counts and timestamps |
AlreadyHave | 1592 | Checks whether a specific item (transaction, block, review, or product) is already known to the node, allowing it to avoid reprocessing or requesting the same item again. This function is part of the inventory management aspect of a Bitcoin node, which helps optimize communication and bandwidth usage |
ProcessMessages | 1611 | Handles incoming messages from other nodes in the Bitcoin network. It reads and processes messages, ensuring they conform to the expected format while efficiently managing the message buffer |
ProcessMessage | 1690 | Processes incoming messages from other nodes, interprets them according to the command they represent, and performs the necessary actions based on the command type |
SendMessages | 2056 | Sends various types of messages to a connected peer node in the Bitcoin network. It handles several tasks, including ensuring that only validated data is sent, managing inventory updates, and handling address propagation |
FormatHashBlocks | 2138 | Prepares a byte buffer for hashing by ensuring it conforms to the requirements of the hashing algorithm used in Bitcoin (such as SHA-256). It properly pads and formats the input data for efficient hashing |
BlockSHA256 | 2156 | Computes the SHA-256 hash for a specified number of data blocks using the crypto library. It takes an array of input data, processes it in blocks, and outputs the resulting SHA-256 hash in a specified buffer |
BitcoinMiner | 2183 | Responsible for the mining process in the Bitcoin software. It works by repeatedly attempting to create a valid block by solving a computational puzzle known as proof-of-work |
GetBalance | 2386 | Calculates the total balance of a Bitcoin wallet by summing the values of the unspent transactions that belong to the wallet |
SelectCoins | 2410 | Selects a set of wallet transactions that meet a specified target value, which is crucial for constructing a new transaction with sufficient funds. This function attempts to find the optimal subset of Unspent Transaction Outputs (UTXOs) that total close to the target value while also considering various conditions |
CreateTransaction | 2514 | Facilitate the creation of a new transaction by selecting appropriate unspent transaction outputs (UTXOs), calculating fees, preparing inputs and outputs, and signing the transaction |
CommitTransactionSpent | 2595 | Updates the wallet’s state after a transaction has been committed. Specifically, it marks the inputs of the newly added transaction as spent and updates the wallet’s transaction history, utilizing a critical section to ensure thread safety during concurrent access to shared data |
SendMoney | 2625 | Handles the process of creating and sending transactions. It involves transaction creation, validation, fee calculations, modifications to the wallet state, and broadcasting the transaction across the network |
- GetBlockValue function is part of the CBlock class. This function calculates the total value of a newly created block, considering its subsidy and transaction fees
int64 nFees represents the total transaction fees included in the block.
Local Variable nSubsidy is initially set as 50 * COIN, which means that the standard subsidy for a new coinbase block is 50 bitcoin (50 coins)
The subsidy is designed to be halved approximately every four years. The condition nBestHeight / 210000 calculates how many 210,000 block intervals have been mined (since 210,000 blocks roughly correspond to four years at 10-minute block intervals). The expression nSubsidy >>= (nBestHeight / 210000) uses a right bitwise shift operator (>>=), effectively halving the subsidy for each completed interval of 210,000 blocks. This implements bitcoin’s block reward halving mechanism
The total value of the block is the sum of the current subsidy (after accounting for halvings) and any transaction fees associated with the transactions included in the block
The table below helps visualize the evolution of block subsidy rewards after each halving. From this table, the 21 000 000 bitcoin maximum quantity can be derived. That means that the hard cap of 21 million bitcoin is an implicit limit, not an explicit limit
The halving curve can be visualized with this graph :
- GetNextWorkRequired function is responsible for adjusting the mining difficulty based on the time it took to mine the last set of blocks
nTargetTimespan sets the ideal duration for mining 2016 blocks, which is two weeks
nTargetSpacing defines the desired time between blocks, set to 10 minutes
nInterval calculates the number of blocks that should be adjusted for difficulty (2016 blocks in this case)
The lines below check if the current block height (nHeight) plus one is not a multiple of nInterval. If it isn’t, the function returns the current difficulty (nBits) without making any changes. This ensures that the difficulty is adjusted only once every 2016 blocks
The function below calculates the actual time taken to mine the last nInterval blocks by subtracting the time of pindexFirst from pindexLast. This actual time span (nActualTimespan) is then forced to a minimum of 25% of the target timespan and a maximum of 400% to prevent extreme adjustments in difficulty
The lines below create a new difficulty target (bnNew) based on the previous difficulty and the actual time span compared to the target timespan. If the new difficulty exceeds the defined proof-of-work limit, it caps it to the maximum allowable difficulty
Here below the evolution of the real network difficulty
- CheckBlock function validates a block before it is processed further. It conducts several checks on the block’s properties to ensure that it adheres to the rules defined by the blockchain protocol
It verifies that the block size is valid
It verifies that the timestamp of the block is valid (not too far in the future as compared with the current time)
It verifies that the first transaction in the block is a coinbase transaction (the special transaction that rewards miners for adding a block), and that there is only one coinbase transaction
It iterates through all transactions in the block (vtx) and calls the CheckTransaction() method on each. If any transaction fails its validity check, it returns an error
It validates the block’s proof of work (POW)
nBits value (which indicates the difficulty of the proof of work) shall not exceed the predefined limit (bnProofOfWorkLimit)
Block’s hash (calculated by the GetHash() method) is less than or equal to the target dictated by nBits
If these checks fail, it returns an error
It validates that the hashMerkleRoot stored in the block matches the hash generated from the Merkle tree of the transactions in the block. If they don’t match, it returns an error
In the bitcoin protocol, a transaction will be stored in the mempool (memory pool) until it is duly validated. You can visualize the live mempool size : https://tinyurl.com/2z8zujvk
main.h
This file defines constants, classes, methods used in main.cpp. I’m not going to detail the content, and just provide informations about important constants used in the program
Here is the main.h : https://tinyurl.com/z8y66m7y
- Constant definitions
The maximum block size in bytes is 0x02000000, or equivalent to about 32 MB (32 * 1024 * 1024 bytes). In the bitcoin context, this can restrict the maximum block size to maintain efficiency and performance
In practice, the real block size is much lower, as can be seen on the graph below. The real block size usage has increased following an increase in the blockchain transactions
Coin represents the base unit for a cryptocurrency, here defined as 1 Bitcoin being equal to 100,000,000 satoshis. It allows for smaller denominations of Bitcoin to be used in transactions
Cent represents a smaller unit equivalent to one hundredth of a Bitcoin, or 1 Cent = 1,000,000 satoshis, further allowing the representation of transactions in finer detail. It helps in calculations involving cents
Coinbase maturity indicates that newly mined coins (the output of a coinbase transaction) cannot be spent until a certain number of blocks (in this case, 100 blocks) have been confirmed after the block containing the coinbase transaction. This rule is implemented to prevent double-spending in the case of newly created coins
bnProofOfWorkLimit sets the limit for the proof of work difficulty. uint256(0) creates a value that represents the maximum possible value for a 256-bit unsigned integer (i.e., all bits are set). Shifting this value right by 32 bits effectively reduces the maximum target value by a factor of (2^{32}).
makefile, makefile.vc
Makefile is used by the make build automation tool to manage the compilation of the bitcoin.exe target. The paths where the compiler will look for header files and where it will look for libraries are defined
makefile is here : https://tinyurl.com/yah6ap9c
market.cpp, market.h
This is a partially completed distributed market place. It was not implemented in later versions of bitcoin core, so I’m not going to detail anything
market.cpp is here : https://tinyurl.com/3u5x88cc
net.cpp, net.h
We all know that bitcoin is decentralized, and based upon the synchronization of nodes (mainly operated by miners). net.cpp is an important file for the execution of this network layer
Here is net.cpp : https://tinyurl.com/yju4rp55
It manages network connections and threading in a Bitcoin node. This code handles aspects like network socket creation, listening for incoming connections, sending and receiving messages, handling of issues like connection failures and data integrity, and proper cleanup during shutdown
- Global variables
Here you find address definitions, flags, primitives. For example, vNodes keeps track of connected nodes, and mapAddresses stores known network addresses
- ConnectSocket function
This function establishes a socket connection to the specified address (addrConnect).
The function creates a socket, and attempts to connect. If successful, it returns true and sets hSocketRet to the connected socket
- GetMyExternalIP function
This function attempts to determine the external IP address of the machine by connecting to a known address. After establishing a socket connection, it sends an HTTP GET request to retrieve the external IP and then processes the response. If successful, it sets ipRet to the detected external IP address
- ThreadSocketHandler and ThreadOpenConnections represent functions handling socket connections and messages, running indefinitely in their respective threads
- ThreadMessageHandler
This function is responsible for processing incoming and outgoing messages to connected nodes
- StartNode and StopNode functions
StartNode : this function initializes the networking components, binds to a local address, listens for incoming connections, and starts necessary threads
StopNode : this function shuts down the node, marking a shutdown flag and ensuring all threads are complete before cleanup
script.cpp, script.h
Bitcoin is programmable money, and like any program, you can add commands to it to execute certain actions
For this purpose, bitcoin Core uses scripts that are run into a stack, and opcodes are the underlying operations that help build the bitcoin scripts
Technically, the scripting language is based upon Forth : https://tinyurl.com/43tpat57
The use of such a scripting language is like having an embedded, assembly-like language, to use for specific tasks inside the application. As such, the opcodes are similar to the mnemonics used in assembly programming
You can find a complete list of opcodes here : https://tinyurl.com/5e8kaypr
The script.h file can be found here : https://tinyurl.com/b9u8s2bd. You will find inside :
- Opcode enumeration
The enum contains different opcodes representing operations in bitcoin script. They include commands for pushing data, control flow, stack manipulation, bitwise operations, cryptography, and more
- Function to get opcode names
This function returns a string representation of an opcode based on its enum value. If the opcode doesn’t match any known type, it returns “UNKNOWN_OPCODE”
- CScript Class
The class CScript is used for script management and manipulation. It has various constructors and operator overloads
These operators can handle different data types and build scripts, and pushing values onto the stack
- Script parsing
This method retrieves the next opcode from the script and updates the program counter
The script.cpp file can be found here : https://tinyurl.com/mt29va73
This file includes functions that are important and used for transaction verification and execution. They are used extensively within the Bitcoin network, for verifying transactions and ensuring that they are executed correctly according to the provided scripts
- EvalScript is essential for executing and validating Bitcoin scripts. It processes opcodes sequentially, modifying the execution stack as required and handles both control flow and cryptographic operations to ensure each script fulfills its intended purpose correctly. Each opcode has specific logic that defines how it interacts with the stack and how it affects the program’s flow
- SignatureHash is a crucial part of Bitcoin’s transaction model, responsible for generating a hash of a transaction input that includes the signature data. This hash is what is actually signed by the private key, ensuring that the signature is uniquely associated with a specific transaction input state
- IsMine checks whether the provided public key script (scriptPubKey) belongs to the wallet (i.e., whether the wallet holds the corresponding private key)
- ExtractPubKey extracts the public key from the public key script (scriptPubKey). It optionally checks if the public key belongs to the wallet
- ExtractHash160 is designed to extract the hash of a public key (specifically, the result of a RIPEMD-160 hashing operation on a SHA-256 hash of the public key) from a given script. This hash is used in Bitcoin transactions as a means of identifying addresses uniquely
- SignSignature generates a digital signature for a transaction input. It combines the transaction data with the relevant script and signs it using the private key associated with the corresponding public key
- VerifySignature checks if the input is valid. It confirms that the transaction hash matches the expected hash. Finally, it verifies the signature using the script evaluation process
This function is important for maintaining the security and integrity of the Bitcoin network, ensuring that funds can only be spent by their rightful owners. If any of the checks fail, it ensures that the transaction cannot proceed
serialize.h
This code implements serialization : https://en.wikipedia.org/wiki/Serialization
The code converts objects of a particular class into a stream of bytes. It is used to store it in memory or transmit it over the network
Here is the serialize.h : https://tinyurl.com/msmd2r3k
For example, the WriteCompactSize function is designed to serialize a size value (of type uint64) into a compact format for efficient storage and transmission. It uses a specific encoding scheme that optimizes for smaller sizes when possible, making it important for handling variable-length data
sha.cpp, sha.h
Here is sha.cpp : https://tinyurl.com/mvhzu39d
The provided code implements the SHA1, SHA224, SHA256, SHA384, SHA512 hashing algorithm
It also includes an accelerated version of SHA52, written in assembly language, for compatible hardware
ui.cpp, ui.h, ui.rc, uibase.cpp, uibase.h, uiproject.fbp
All these files are here to implement the user interface of the bitcoin application
It is based upon the Qt framework : https://www.qt.io/product/framework
It uses wxFormbuilder widgets, to hep create the user interface (example below)
The volume of code is important : about 18 000 lines of code. We can imagine the time spent on this if bitcoin was developped by a single person !
uint256.h
This file defines two custom data types, uint160 and uint256, for handling 160-bit and 256-bit unsigned integers, respectively. These types are commonly used in blockchain and cryptocurrency applications, to represent data like hashes (SHA-256 outputs) and addresses
Here is uint256.h : https://tinyurl.com/5bfnp858
util.cpp, util.h
This code implements several utilities : random cryptographic seed generation, exceptions, parser, time management. They are quite standard but essential components, for the cryptography processes and the block timestamp