Bitcoin Core - When is fAllowWitness evaluated to true?

2

In Bitcoin Core, when is fAllowWitness evaluated to true?

transaction.h

const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);

In particular, I cant figure out the value of s.GetVersion()

Thank you

tsknakamura

Posted 2017-09-13T08:17:03.920

Reputation: 145

Answers

3

Doing a grep on SERIALIZE_TRANSACTION_NO_WITNESS shows that it's ORed with PROTOCOL_VERSION when creating a CDataStream object for example. This is the first clue that the no witness flag is to be found along with the version protocol.

A little more digging shows that this define is used when building a Tx message in lines 1105-1126 of net_processing.cpp (v0.15.0.1):

        else if (inv.type == MSG_TX || inv.type == MSG_WITNESS_TX)
        {
            // Send stream from relay memory
            bool push = false;
            auto mi = mapRelay.find(inv.hash);
            int nSendFlags = (inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
            if (mi != mapRelay.end()) {
                connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
                push = true;
            } else if (pfrom->timeLastMempoolReq) {
                auto txinfo = mempool.info(inv.hash);
                // To protect privacy, do not answer getdata using the mempool when
                // that TX couldn't have been INVed in reply to a MEMPOOL request.
                if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) {
                    connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
                    push = true;
                }
            }
            if (!push) {
                vNotFound.push_back(inv);
            }
        }

The above code shows that the int variable nSendFlags may contain the no witness flag. Later, msgMaker.Make will use this variable to create the Tx message as shown in line 1119:

                    connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));

You can then follow the serialization by looking at the class CNetMsgMaker in netmessagemaker.h which itself uses CVectorWriter to serialize the data.

To summarize, the GetVersion() value is built using the protocol version optionally ORed with the SERIALIZE_TRANSACTION_NO_WITNESS. This value is never sent over the wire. It's used only to control the serialization of the Tx message.

ricvg

Posted 2017-09-13T08:17:03.920

Reputation: 46