2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LiquidのトランザクションのTxIdの作り方を調べた

Posted at

結論

flagに0セットしてWitness部分を取り除いたものをdouble sha256する。

コード読み

core_write.cppのTxToUnivというgetrawtransactionの結果を作っていると思われる関数に、

entry.pushKV("txid", tx.GetHash().GetHex());

という箇所があった。ここではTransactionからtxidを作成しているっぽい。

tx.GetHash()は、SERIALIZE_TRANSACTION_NO_WITNESSフラグを設定してSerializeHashを呼ぶ

// primitives/transaction.cpp
uint256 CMutableTransaction::GetHash() const
{
    return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
}

SERIALiZE_NO_WITNESSをVersionに設定したCHashWriterを作り、<<にtxを送ると

// hash.h
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
    CHashWriter ss(nType, nVersion);
    ss << obj;
    return ss.GetHash();
}

CTransactionのSerializeが、CHashWriterをStreamとして受け取る

// hash.h
template<typename T>
CHashWriter& operator<<(const T& obj) {
    // Serialize to this stream
    ::Serialize(*this, obj); return (*this);
}

グローバルのジェネリックな::Serializeを介してCTransactionのSerializeが呼ばれる

template<typename Stream, typename T>
inline void Serialize(Stream& os, const T& a)
{
    a.Serialize(os);
}

そしてグローバルのSerializeTransactionが呼ばれる

    template <typename Stream>
    inline void Serialize(Stream& s) const {
        SerializeTransaction(*this, s);
    }

SerializeTransactionでは、serialize.hで定義された型ごとのシリアライザによって、シリアライズされたCTransactionがCHashWriterに書き込まれる。上でCHashWriterにセットしたバージョン(SERIALIZE_TRANSACTION_NO_WITNESS)によってflagsに0が設定されるので、witness部分はシリアライズされない。

template<typename Stream, typename TxType>
inline void SerializeTransaction(const TxType& tx, Stream& s) {
    const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);

    s << tx.nVersion;

    // Consistency check
    assert(tx.witness.vtxinwit.size() <= tx.vin.size());
    assert(tx.witness.vtxoutwit.size() <= tx.vout.size());

    // Check whether witnesses need to be serialized.
    unsigned char flags = 0;
    if (fAllowWitness && tx.HasWitness()) {
        flags |= 1;
    }

    // Witness serialization is different between Elements and Core.
    if (g_con_elementsmode) {
        // In Elements-style serialization, all normal data is serialized first and the
        // witnesses all in the end.
        s << flags;
        s << tx.vin;
        s << tx.vout;
        s << tx.nLockTime;
        if (flags & 1) {
            const_cast<CTxWitness*>(&tx.witness)->vtxinwit.resize(tx.vin.size());
            const_cast<CTxWitness*>(&tx.witness)->vtxoutwit.resize(tx.vout.size());
            s << tx.witness;
        }
    }
    ...

SerializeHashに戻って、CHashWriterのGetHashが呼ばれる。

// hash.h
class CHashWriter
{
private:
    CHash256 ctx;
    ...
    // invalidates the object
    uint256 GetHash() {
        uint256 result;
        ctx.Finalize((unsigned char*)&result);
        return result;
    }
    ...

GetHashは、シリアライズ時にCHashWriterに書き込まれたデーターのdouble SHA-256を返す

// hash.h
private:
    CSHA256 sha;
public:
    ...
    void Finalize(unsigned char hash[OUTPUT_SIZE]) {
        unsigned char buf[CSHA256::OUTPUT_SIZE];
        sha.Finalize(buf);
        sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(hash);
    }
    ...

GetHash()の戻り値uint256に対してGetHex()が呼ばれて、txid文字列が作られる。(終)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?