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

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

## コード読み
core_write.cppのTxToUnivというgetrawtransactionの結果を作っていると思われる関数に、

```cpp
entry.pushKV("txid", tx.GetHash().GetHex());
```
という箇所があった。ここではTransactionからtxidを作成しているっぽい。

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

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

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

```cpp
// 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として受け取る

```cpp
// hash.h
template<typename T>
CHashWriter& operator<<(const T& obj) {
    // Serialize to this stream
    ::Serialize(*this, obj); return (*this);
}
```
グローバルのジェネリックな::Serializeを介してCTransactionのSerializeが呼ばれる

```cpp
template<typename Stream, typename T>
inline void Serialize(Stream& os, const T& a)
{
    a.Serialize(os);
}
```
そしてグローバルのSerializeTransactionが呼ばれる

```cpp
    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部分はシリアライズされない。

```cpp
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が呼ばれる。


```cpp
// 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を返す

```cpp
// 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文字列が作られる。（終）