RealPath:
WebPath:
2017/01/08 18:46 (JST) 更新
トランザクション >>

トランザクションの発生と伝搬

Contents

トランザクションが新規に生成された時点では、まだ該当トランザクションはブロックに含まれていない。これはトランザクションが未検証(承認数 = 0)であることに等しい。
未検証トランザクションは短時間(大抵は数秒)のうちに全ノードに伝搬され、各ノードにおける未検証トランザクションプール(CTxMemPool)に格納される。

実践: トランザクションの発生と伝搬

host1 と host2 は(addnode または connect 等により)接続されているものとする。

host1 側で送金トランザクションを生成。

host1
$ bitcoin-cli getnewaddress
mh5tKYs3ywj3y4bWrKsV32ocNx4u2jEYYY … 新規アドレス

$ bitcoin-cli sendtoaddress mh5tKYs3ywj3y4bWrKsV32ocNx4u2jEYYY 0.01 … 送金
676ac762ea5368a0a7fe422ecdb67bf7a734b1a49d2fdf55d723132063b44d7b … トランザクションID

 
上記トランザクションは host2 にも伝搬されている。
host2 側でトランザクション内容を確認するためには getrawtransaction コマンドを用いる。

host2
$ bitcoin-cli getrawtransaction 676ac762ea5368a0a7fe422ecdb67bf7a734b1a49d2fdf55d723132063b44d7b
0200000003f0117259b7ee2328ca836778342ed7b95f3d6be9aa983a8d3e318255238d9370000000006a47304402205a6d34a6ac97542a77702ab1b283e74c064979532e38ad773b080f07f8cc65fd0220619880b384babd06bd6a1b9f9a150dd2075af244fefb7b58d7d4949eabb24fcc012103e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231efeffffff2e92aa794f84229640f7bcf8301875d2a98049badbe117ada273fae9a8c97d6d000000006a4730440220040c9af36edad5f64230211b48c507471e69a31ba4a39cbce08442ae44548e1b02207337f5fe322d7437f102c49fd85366a758f498090c53665db472f61697ccc0ef0121020713b776408a4ccac765a349897d89f363a69254a2f942d9e07e5c1ada572c61feffffffa0f22ba920b39977fb7c243ec901f2c36ec13cd9255410deea45a61e918d569f010000006a473044022034488cdad9a0287f96ab50417397b0c327d054e2b890deccc8e198f2a4d86f0f0220715232caaaa01464b188fed8b58c95ca370b9adf52afcb774f34923297c95356012103e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231efeffffff0270211e00000000001976a9144df3e4fc1d8009d01851502435f887d6293964a688ac80969800000000001976a914113288f7591f767c9758dba01572d3c45d43f65188acce000000

 
getrawtransaction コマンドにより得られる結果は16進表記のバイナリ (hexstring) なのでこのままでは人間には読むことができない。これを decoderawtransaction により人間にも読める形式に変換する。

host2
$ bitcoin-cli decoderawtransaction 0200000003f0117259b7ee2328ca836778342ed7b95f3d6be9aa983a8d3e318255238d9370000000006a47304402205a6d34a6ac97542a77702ab1b283e74c064979532e38ad773b080f07f8cc65fd0220619880b384babd06bd6a1b9f9a150dd2075af244fefb7b58d7d4949eabb24fcc012103e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231efeffffff2e92aa794f84229640f7bcf8301875d2a98049badbe117ada273fae9a8c97d6d000000006a4730440220040c9af36edad5f64230211b48c507471e69a31ba4a39cbce08442ae44548e1b02207337f5fe322d7437f102c49fd85366a758f498090c53665db472f61697ccc0ef0121020713b776408a4ccac765a349897d89f363a69254a2f942d9e07e5c1ada572c61feffffffa0f22ba920b39977fb7c243ec901f2c36ec13cd9255410deea45a61e918d569f010000006a473044022034488cdad9a0287f96ab50417397b0c327d054e2b890deccc8e198f2a4d86f0f0220715232caaaa01464b188fed8b58c95ca370b9adf52afcb774f34923297c95356012103e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231efeffffff0270211e00000000001976a9144df3e4fc1d8009d01851502435f887d6293964a688ac80969800000000001976a914113288f7591f767c9758dba01572d3c45d43f65188acce000000
{
  "txid": "676ac762ea5368a0a7fe422ecdb67bf7a734b1a49d2fdf55d723132063b44d7b",
  "hash": "676ac762ea5368a0a7fe422ecdb67bf7a734b1a49d2fdf55d723132063b44d7b",
  "size": 519,
  "vsize": 519,
  "version": 2,
  "locktime": 206,
  "vin": [
    {
      "txid": "70938d235582313e8d3a98aae96b3d5fb9d72e34786783ca2823eeb7597211f0",
      "vout": 0,
      "scriptSig": {
        "asm": "304402205a6d34a6ac97542a77702ab1b283e74c064979532e38ad773b080f07f8cc65fd0220619880b384babd06bd6a1b9f9a150dd2075af244fefb7b58d7d4949eabb24fcc[ALL] 03e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231e",
        "hex": "47304402205a6d34a6ac97542a77702ab1b283e74c064979532e38ad773b080f07f8cc65fd0220619880b384babd06bd6a1b9f9a150dd2075af244fefb7b58d7d4949eabb24fcc012103e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231e"
      },
      "sequence": 4294967294
    },
    {
      "txid": "6d7dc9a8e9fa73a2ad17e1dbba4980a9d2751830f8bcf7409622844f79aa922e",
      "vout": 0,
      "scriptSig": {
        "asm": "30440220040c9af36edad5f64230211b48c507471e69a31ba4a39cbce08442ae44548e1b02207337f5fe322d7437f102c49fd85366a758f498090c53665db472f61697ccc0ef[ALL] 020713b776408a4ccac765a349897d89f363a69254a2f942d9e07e5c1ada572c61",
        "hex": "4730440220040c9af36edad5f64230211b48c507471e69a31ba4a39cbce08442ae44548e1b02207337f5fe322d7437f102c49fd85366a758f498090c53665db472f61697ccc0ef0121020713b776408a4ccac765a349897d89f363a69254a2f942d9e07e5c1ada572c61"
      },
      "sequence": 4294967294
    },
    {
      "txid": "9f568d911ea645eade105425d93cc16ec3f201c93e247cfb7799b320a92bf2a0",
      "vout": 1,
      "scriptSig": {
        "asm": "3044022034488cdad9a0287f96ab50417397b0c327d054e2b890deccc8e198f2a4d86f0f0220715232caaaa01464b188fed8b58c95ca370b9adf52afcb774f34923297c95356[ALL] 03e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231e",
        "hex": "473044022034488cdad9a0287f96ab50417397b0c327d054e2b890deccc8e198f2a4d86f0f0220715232caaaa01464b188fed8b58c95ca370b9adf52afcb774f34923297c95356012103e9ddbb79c7f51e59ed3937a7c9a53cc9335e920533acc3301015fb09b719231e"
      },
      "sequence": 4294967294
    }
  ],
  "vout": [
    {
      "value": 0.01974640,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 4df3e4fc1d8009d01851502435f887d6293964a6 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a9144df3e4fc1d8009d01851502435f887d6293964a688ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "mnd8VujMwkUM5tiBudfzaQCux1pcRpatHr"
        ]
      }
    },
    {
      "value": 0.10000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 113288f7591f767c9758dba01572d3c45d43f651 OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914113288f7591f767c9758dba01572d3c45d43f65188ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "mh5tKYs3ywj3y4bWrKsV32ocNx4u2jEYYY"
        ]
      }
    }
  ]
}

ソースコード:未検証トランザクションプール(CTxMemPool)

validation.cpp
// グローバル変数
CTxMemPool mempool(::minRelayTxFee);
txmempool.h
class CTxMemPool
{
public:
    typedef boost::multi_index_container<CTxMemPoolEntry, ....> indexed_transaction_set;
    indexed_transaction_set mapTx;

    typedef indexed_transaction_set::nth_index<0>::type::iterator txiter;
    std::vector<std::pair<uint256, txiter> > vTxHashes; //!< All tx witness hashes/entries in mapTx, in random order

    typedef std::set<txiter, ....> setEntries;

private:
    typedef std::map<txiter, setEntries, CompareIteratorByHash> cacheMap;

    struct TxLinks {
        setEntries parents;
        setEntries children;
    };

    typedef std::map<txiter, TxLinks, CompareIteratorByHash> txlinksMap;
    txlinksMap mapLinks;

public:
    indirectmap<COutPoint, const CTransaction*> mapNextTx;
    std::map<uint256, std::pair<double, CAmount> > mapDeltas;
};

ソースコード: トランザクション生成とブロードキャスト

以下処理の流れは sendtoaddress を実行したときの例。

UniValue CRPCTable::execute(const JSONRPCRequest &request) const
↓
UniValue sendtoaddress(const JSONRPCRequest& request)
↓
static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
↓
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state)
↓
GetMainSignals().SyncTransaction(tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
↓
void PeerLogicValidation::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int nPosInBlock)
void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock)

上記処理により未検証トランザクション情報(CTransaction)は他ノードへ伝搬される。

ソースコード: 未検証トランザクションの受信

各ノードは未検証トランザクション(CTransaction)を受け取ると、その情報を CTxMemPoolEntry として未検証トランザクションプール(CTxMemPool)に格納する。

bool ProcessMessages(CNode* pfrom, CConnman& connman)
↓
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman)
{
    ....
    else if(strCommand == NetMsgType::TX)
    {
        ....
        CTransaction tx(deserialize, vRecv); // vRecv のデシリアライズにより tx を構築
        ....
    }
}
↓
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree,
                              bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee,
                              std::vector<uint256>& vHashTxnToUncache)
{
    ....
    // CTransaction を CTxMemPoolEntry に変換
    CTxMemPoolEntry entry(tx, nFees, ....);
    ....
}
↓
bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fCurrentEstimate)
{
    ....
    // ※実際に格納されるのは CTransaction ではなく CTxMemPoolEntry インスタンス
    indexed_transaction_set::iterator newit = mapTx.insert(entry).first;
    ....
}