Bitcoinビットコインのソースコードの解読-取引のライフサイクル
3562 ワード
1、取引を作成する.
財布にビットコインがあることを前提に、テストポイントを起動して、自分で鉱山を掘ることができます.RPC`getnewaddressでアドレス`,`sendtoaddress`を取得してトランザクションを作成します.次のようになります.
> bitcoin-cli getnewaddress
1LXVDTasMALkmkLRw7J35pzSdN38VG1Fvp
>bitcoin-cli sendtoaddress 1LXVDTasMALkmkLRw7J35pzSdN38VG1Fvp 1
txid
sendtoaddressはSendMoneyに呼び出され、CWallet::CreateTransactionに呼び出されます.CWallet::CreateTransactionは次のことをします.
AvailableCoinsを呼び出して財布で使用可能な通貨(UTXO)を取得します.
CScript scriptChangeルックアップスクリプトを初期化します.
その後、while(true)のサイクルで適切な通貨(取引の入力)を見つけて、出力と取引費を満たす.
次にselected_を入力します.coinsはProduceSignatureに1つずつ署名します(署名をスキップして、後で話します).CreateTransactionが完了しました.
次にCWallet::CommitTransactionを呼び出してトランザクションをメモリプールに格納します.AcceptToMemoryPoolがAcceptToMemoryPoolWorkerに呼び出されます.このWorkerは取引の出力値範囲が妥当かどうか、入力が重複しているかどうか、(費用がかかっていない)、手数料が妥当かどうか、CheckInputsは入力した署名が正しいかどうかをチェックします.accepttomemorypoolの後、CWalletTx::RelayWalletTransactionを呼び出します.さいよびだし
MSG経由でTXは、この取引のidを隣接ノードにブロードキャストする.
2、インターネット放送取引.
PushInventoryはトランザクションIDをセットsetInventory TxToSendに入れてnet_processing.cpp中
送信間隔を満たすとトランザクションidが配列で送信される.隣接ノードはnet_で受信しましたprocessing.cppでの処理
RequestTxに呼び出し、取引idをpeer_に配置download_state.m_tx_announced.insert(txid);とpeer_download_state.m_tx_process_time.emplace(process_time, txid);で行ないます.
処理時間が満たされたらconnman->PushMessage(pto,msgMaker.Make(NetMsgType::GETDATA,vGetData);この取引idを放送する隣接ノードに取引の具体的なデータを要求する.
隣接ノードは、GETDATAを処理する際に、NetMsgType::TXを介してリクエスト側に取引を返信する.
ノードがNetMsgType::TXを受信した場合、処理ロジックはnet_processing.cpp
主にAcceptToMemoryPool(このプロセスは上と同じ)ですが、入力が存在しないことに気づき、取引を独児プールに置き、すべての入力が揃ってから再AcceptToMemoryPoolにします.
3.ブロックに梱包する.
RPCコマンドによるブロックの作成
>bitcoin-cli generatetoaddress 1LXVDTasMALkmkLRw7J35pzSdN38VG1Fvp
次にBlockAssembler::CreateNewBlockに実行し、ブロックの初期化とcoinbaseの作成を担当します.
次にBlockAssembler::addPackagetTxsを実行し、メモリプールのトランザクションをブロックに格納します.
これで、取引が完了し、ネットワークに記録されます.
財布にビットコインがあることを前提に、テストポイントを起動して、自分で鉱山を掘ることができます.RPC`getnewaddressでアドレス`,`sendtoaddress`を取得してトランザクションを作成します.次のようになります.
> bitcoin-cli getnewaddress
1LXVDTasMALkmkLRw7J35pzSdN38VG1Fvp
>bitcoin-cli sendtoaddress 1LXVDTasMALkmkLRw7J35pzSdN38VG1Fvp 1
txid
sendtoaddressはSendMoneyに呼び出され、CWallet::CreateTransactionに呼び出されます.CWallet::CreateTransactionは次のことをします.
AvailableCoinsを呼び出して財布で使用可能な通貨(UTXO)を取得します.
CScript scriptChangeルックアップスクリプトを初期化します.
その後、while(true)のサイクルで適切な通貨(取引の入力)を見つけて、出力と取引費を満たす.
次にselected_を入力します.coinsはProduceSignatureに1つずつ署名します(署名をスキップして、後で話します).CreateTransactionが完了しました.
次にCWallet::CommitTransactionを呼び出してトランザクションをメモリプールに格納します.AcceptToMemoryPoolがAcceptToMemoryPoolWorkerに呼び出されます.このWorkerは取引の出力値範囲が妥当かどうか、入力が重複しているかどうか、(費用がかかっていない)、手数料が妥当かどうか、CheckInputsは入力した署名が正しいかどうかをチェックします.accepttomemorypoolの後、CWalletTx::RelayWalletTransactionを呼び出します.さいよびだし
void relayTransaction(const uint256& txid) override
{
CInv inv(MSG_TX, txid);
g_connman->ForEachNode([&inv](CNode* node) { node->PushInventory(inv); });
}
MSG経由でTXは、この取引のidを隣接ノードにブロードキャストする.
2、インターネット放送取引.
PushInventoryはトランザクションIDをセットsetInventory TxToSendに入れてnet_processing.cpp中
// Determine transactions to relay
if (fSendTrickle) {
// Produce a vector with all candidates for sending
....
if (vInv.size() == MAX_INV_SZ) {
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
vInv.clear();
}
....
送信間隔を満たすとトランザクションidが配列で送信される.隣接ノードはnet_で受信しましたprocessing.cppでの処理
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic& interruptMsgProc, bool enable_bip61)
{
...
if (strCommand == NetMsgType::INV) {
...
for (CInv &inv : vInv)
{
...
else
{
pfrom->AddInventoryKnown(inv);
if (fBlocksOnly) {
LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d
", inv.hash.ToString(), pfrom->GetId());
} else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) {
RequestTx(State(pfrom->GetId()), inv.hash, nNow);
}
}
}
RequestTxに呼び出し、取引idをpeer_に配置download_state.m_tx_announced.insert(txid);とpeer_download_state.m_tx_process_time.emplace(process_time, txid);で行ないます.
処理時間が満たされたらconnman->PushMessage(pto,msgMaker.Make(NetMsgType::GETDATA,vGetData);この取引idを放送する隣接ノードに取引の具体的なデータを要求する.
隣接ノードは、GETDATAを処理する際に、NetMsgType::TXを介してリクエスト側に取引を返信する.
ノードがNetMsgType::TXを受信した場合、処理ロジックはnet_processing.cpp
bool static ProcessMessage(...
...
if (strCommand == NetMsgType::TX) {
主にAcceptToMemoryPool(このプロセスは上と同じ)ですが、入力が存在しないことに気づき、取引を独児プールに置き、すべての入力が揃ってから再AcceptToMemoryPoolにします.
3.ブロックに梱包する.
RPCコマンドによるブロックの作成
>bitcoin-cli generatetoaddress 1LXVDTasMALkmkLRw7J35pzSdN38VG1Fvp
次にBlockAssembler::CreateNewBlockに実行し、ブロックの初期化とcoinbaseの作成を担当します.
次にBlockAssembler::addPackagetTxsを実行し、メモリプールのトランザクションをブロックに格納します.
これで、取引が完了し、ネットワークに記録されます.