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 .
Sunday, 9 July 2017
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;
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
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
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
Subscribe to:
Posts (Atom)