Sunday, 9 July 2017

Bitcoin core tutorial & code walk through (Part 3) - getblock

1) The bitcoin-cli command can be used to get blockhash and get block information. For testing purpose, the regtest network is used.

bitcoin-cli -regtest getblockhash 0
(it returns the block hash)
bitcoin-cli -regtest getblock 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206
(it takes block hash as parameter)

2) In this analysis, the source code that handles getblockhash and getblock RPC will be walked through.


For getblockhash rpc
rpc/blockchain.cpp
define RegisterBlockchainRPCCommands(CRPCTable &t)

UniValue getblockhash(const JSONRPCRequest& request)

This function checks the block height, make sure it is not out of range. Then it calls CBlockIndex class GetBlockHash() function

chain.h

GetBlockHash() simply returns the pointer to hash block. 

For getblock rpc
rpc/blockchain.cpp
UniValue getblock(const JSONRPCRequest& request)
This function firstly check the verbosity. It checks mapBlockIndex is not out of range. The it calls ReadBlockFromDisk() and blockToJSON() to print out the block data in JSON format.

UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails)

It builds the JSON value pair using the CBlock and CBlockIndex.

validation.cpp

bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
This function builds a CAutoFile object which contains a FILE *. The OpenBlockFile() is used to return the FILE *. Then, the FILE * is copied to CBlock.

FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly)

It is a misc function that calls OpenDiskFile().

static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)

It uses fsbridge::fopen() to build FILE *, and returns FILE *. The fsbridge is Bitcoin core namespace.

mapBlockIndex is defined in validation.cpp as

BlockMap mapBlockIndex;
and extern BlockMap mapBlockIndex; in validation.h.

typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;

It is unordered_map in C++ std namespace .


Wednesday, 5 July 2017

Bitcoin core tutorial & code walk through (Part 2) - sendtoaddress

1) The bitcoin-cli command can be used to send bitcoin to any recipient address. For testing purpose, the regtest network is used.

bitcoin-cli -regtest getaccountaddress ""  - get the address from default account
bitcoin-cli -regtest sendtoaddress mjSTBVs....... {amount} <comment>  - this returns transaction id

2) In this analysis, the source code that handles sendtoaddress RPC will be walked through.

httprpc.cpp 
In HTTPReq_JSONRPC(HTTPRequest *req, const std::string &)
call jreq.parse(valRequest)    - parse the request
call tableRPC.execute(jreq)  - execute the RPC comamnd

rpc/server.cpp

In CRPCTable::execute(const JSONRPCRequest &request)
initialise pcmd
  CRPCCommand *pcmd = tableRPC[request.strMethod]
The tableRPC array is filled in init.cpp

init.cpp

In AppInitParameterInteraction()
call RegisterAllCoreRPCCommands(tableRPC)
and RegisterWalletRPCCommands(tableRPC)

rpc/register.h

define the function RegisterAllCoreRPCCommands(CRPCTable &t), which calls
RegisterBlockchainRPCCommands(t)
RegisterMiscRPCCommands(t)
RegisterMiningRPCCommands(t)
RegisterRawTransactionRPCCommands(t)

rpc/blockchain.cpp

define RegisterBlockchainRPCCommands(CRPCTable &t)

rpc/net.cpp

define RegisterNetRPCCommands(CRPCTable &t)

rpc/mining.cpp

define RegisterMiningRPCCommands(CRPCTable &t)

rpc/rawtransaction.cpp

define RegisterRawTransactionRPCCommands(CRPCTable &t)

Last but not least, RegisterWalletRPCCommands is defined in

wallet/rpcwallet.cpp

The RegisterWalletRPCCommands(CRPCTable &t) fill up the CRPCCommand array. In the CRPCComamnd structure,  actor function pointer, sendtoaddress function is assigned to that field.

The function
UniValue sendtoaddress(const JSONRPCRequest & request)
Firstly, the address is gotten from parameter 0. Then, the amount is gotten from parameter 1. The it calls the SendMoney() function, and returns the hash value of the transaction.

The function
static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount value, bool fSubtractFeeFromAmount, CWalletTx & wtxNew)
Firstly, it gets the balance from the wallet, parse the bitcoin address, find out the recipient.
Then, it declares std::vector<CRecipient> vecSend
and append the recipient to the array vecSend
Then, it calls CWallet function CreateTransaction and CommitTransaction.

wallet/wallet.cpp
In the CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign)

Firstly, it checks the recipient amount , which must be >= 0. Then, it sets the lockTime to the next block to discourage fee sniping. The CTxOut txout object is constructed. The txout is appended to CMutableTransaction txNew vout vector. Then, it chooses the Bitcoin to use for transaction. If input value is greater than selected value, it creates a CTxOut and insert it to same CMutableTransaction vout at position nChangePosInOut.

After that, it creates CTxIn and appends the CTxIn to vin vector. It calculate the minimum fee needed. If the fee needed is less than min relay fee, the transaction is dropped. Then the min fee inclusive of necessary fee is calculated.

If transaction requires signature, a signature is produced (via ProduceSignature function). UpdateTransaction() is called to update with signature data.

Then, the CMutableTransaction txNew is embedded in CWalletTx wtxNew object. If wtxNew size is bigger than mempool's chain limit, transaction will be dropped.

In the bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state)

It calls AddToWallet(wtxNew) and coin.BindWallet(this) to notify old coins are spent.
It then broadcast transaction if wtxNew is accepted to mempool

bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)

It creates the walletdb. It creates the std:pair object from mapWallet.insert(std::make_pair(hash, wtxIn)). From the std::pair object, it creates another CWalletTx wtx object. If it is new transaction, it gets the order position from walletdb, and adds the hash. If it is not new, the code merges the hash block. Finally, it writes to disk with walletdb.WriteTx(wtx).

mapWallet is declared in wallet/wallet.h as
std::map<uint256, CWalletTx> mapWallet;

Tuesday, 4 July 2017

Bitcoin core tutorial & code walk through (Part 1)

Bitcoin core is the reference implementation of Bitcoin code.

1) Download Bitcoin core from github
https://github.com/bitcoin/bitcoin

2) Build it
/autogen.sh
./configure --enable_debug
make
make install

3) Setup the bitconf.conf. In the minimum, setup the rcpuser and rpcpassword field
bitconf.conf configuration file path:
OS                Default bitcoin datadir      Typical path to configuration file
Windows     %APPDATA%\Bitcoin\     C:\Users\username\AppData\Roaming\Bitcoin\bitcoin.conf
Linux           $HOME/.bitcoin/               /home/username/.bitcoin/bitcoin.conf
Mac OSX    $HOME/Library/Application Support/Bitcoin/             /Users/username/Library/Application Support/Bitcoin/bitcoin.conf

4) Useful commands
bitcoind -daemon  ; bitcoin-cli stop      - start and stop bitcoin daemon
bitcoind -printtoconsole                        - print debug message to console
bitcoind -daemon -proxy=192.168.1.1:80   - run bitcoind w/o downloading new blocks
bitcoind -testnet    bitcoin-cli -testnet      - run in test network
bitcoind -regtest    bitcoin-cli -regtest     - run in regression test network
bitcoind -debug=rpc                              - set the debug level

bitcoin-cli getblockhash <number>
bitcoin-cli getblock <hash>
bitcoin-cli getblockcount
bitcoin-cli -regtest getblockchaininfo
bitcoin-cli -regtest generate 500      - mine 500 blocks
bitcoin-cli -regtest getbalance          - check rewards

5) Source code walk through is based on v0.14.99.0 (bitcoind -version)
bitcoind.cpp  
main() calls AppInit()
AppInit() calls AppInitParameterInteraction()
then calls AppInitMain(threadGroup, scheduler) - main init function
init.cpp
AppInitParameterInteraction() - setup debug level, register RPC commands
AppInitMain()
            lock directory
            start lightweight task scheduler thread
            AppInitServers() -  start App servers, such as HTTP, RPC servers
            RegisterNodeSignals(GetNodeSignals())
            create zero message queue
            cache size calculations
            LoadBlockIndex(chainparams)
            check genesis block
            InitBlockIndex(chainparams)
            InitLoadWallet()
            GetConsensus()
           CConnman::Start(scheduler, connOptions)
           wallet->postInitProcess(scheduler)
net.cpp
CConnman::Start(...)     - start threads to accept connections, process messages
call InitBinds(std::vector<CService>&, std::vector<CService>&) - bind to address and port number
InitBinds() call GetListenPort()
validation.cpp
LoadBlockIndex(chainparams)        - load block index from db
GetBlockSubsidy(nHeight, consensusParams)       - get mining block rewards
merkleblock.cpp
CMerkleBlock constructor initialises CPartialMerkleTree
CPartialMerkleTree constructor calls TraverseAndBuild()
net_processing.cpp
ProcessMessages->ProcessMessage->ProcessGetData->CMerkleBlock
net.h
RegisterNodeSignals->CNodeSignals.ProcessMessages
init.cpp 
RegisterNodeSignals
rpc/server.cpp
StartRPC()  - called by AppInitServers
httpserver.cpp
StartHTTPServer()  - clled by AppInitServers
util.cpp
LogPrintStr
util.h
LogPrint          - debug log macro
LogPrintf         - debug log macro
LogAcceptCategory   - check the BCLog category and decide to print log or not
httprpc.cpp
HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)     - parse the rpc request that is sent from bitcoin-cli

Sunday, 2 July 2017

Thesis on Bitcoin

Here is my master thesis on Bitcoin. The topic is :

THE RISK PERCEPTIONS AND TECHNOLOGY ADOPTIONS OF E­-COMMERCE USERS
TOWARDS DIGITAL CURRENCY

It is on google drive at the link below :
click at thesis link