The key to finding out where a piece of code is without already knowing where it is is to start at the thing that will eventually lead to what you want to find. These can be logically thought through. For example, for relay and validation, these all occur after a node has received a block or transaction, so begin at the point where a block or transaction is received.
There are generally three kinds of actions that Bitcoin Core does: validation and relay of blocks and transactions, the wallet, and startup
Validation and relay
In order for Bitcoin Core to be able to validate and relay a block or transaction, it has to first receive it. So logically the place to begin looking is at the point where a block or transaction has been received and it is beginning to be processed. That is in
ProcessMessages function in
src/net_processing.cpp. Within this function, there are several
if statements for each type of network message that can be received.
For transactions, you want to look at the
if block for
NetMsgType::TX. By reading through the code in this
if block and following the functions that are called, you will eventually reach where a transaction is verified, added to the mempool, and relayed. The most important function within this block is
AcceptToMemoryPool and that is where all of the validation for an unconfirmed transaction is done.
For blocks, you want to look at the
if block for
NetMsgType::BLOCK. Reading through this code will lead you to
ProcessNewBlock and later
ConnectTip which are the functions that contain the validation of blocks.
Almost all of the wallet's functionality is centered around the creation and receiving of transactions. These logically begin when the user wants to send Bitcoin. So a good starting place is the
sendtoaddress RPC. Following this function will take you to
CreateTransaction and later
SelectCoins which are responsible for transaction creation and coin selection.
Some other things that are interesting in the wallet would include wallet creation and loading which occurs in
CreateWalletFromFile and wallet encryption and unlocking which have good starting points of the
encryptwallet RPC and
Startup and initialization
Lastly some interesting occur during startup such as DNS seeding, connecting to nodes, loading the blockchain from disk, etc. The obvious and actual starting point is the
main function. The main function is the entry point for pretty much every C/C++ program so it's a good place to look at for startup. Following the main function will bring you to
AppInitMain which is where the bulk of loading and initialization occurs.