Author

Topic: Bitcoin Core noob question - how are CTransaction objects created? (Read 861 times)

legendary
Activity: 1722
Merit: 1003
I was looking for a "new CTransaction" somewhere, which doesn't exist since the above is how the tx obj is created from the bytes read into a CNetMessage obj. Guess I have to refamiliarize myself with C++'s serialization operators (it's been almost 20yrs).

new is almost never used in modern C++.

That's not a "C++ serialization operator". In Bitcoin Core, data streams like CDataStream (vRecv there) overload the >> and << operators to do serialization. The actual serialization is mostly done by code in serialize.h via the ADD_SERIALIZE_METHODS and READWRITE macros used in each class that can be serialized.

So vRecv >> tx is actually vRecv.operator>>(tx), which ends up callings tx.SerializationOp(vRecv, ...), which applies the READWRITE macro to each serialized CTransaction field (plus maybe some other work), which either directly unserializes the value for simple types, or calls the value's SerializationOp method to do it.

The point of this somewhat complicated setup is that you just need to do vRecv >> tx to (securely) unserialize a whole transaction, and CTransaction only needs to have a few lines of code to make this happen.


Aha....thank you. That sets my mind in the right direction. Appreciate the detail.
administrator
Activity: 5166
Merit: 12850
I was looking for a "new CTransaction" somewhere, which doesn't exist since the above is how the tx obj is created from the bytes read into a CNetMessage obj. Guess I have to refamiliarize myself with C++'s serialization operators (it's been almost 20yrs).

new is almost never used in modern C++.

That's not a "C++ serialization operator". In Bitcoin Core, data streams like CDataStream (vRecv there) overload the >> and << operators to do serialization. The actual serialization is mostly done by code in serialize.h via the ADD_SERIALIZE_METHODS and READWRITE macros used in each class that can be serialized.

So vRecv >> tx is actually vRecv.operator>>(tx), which ends up callings tx.SerializationOp(vRecv, ...), which applies the READWRITE macro to each serialized CTransaction field (plus maybe some other work), which either directly unserializes the value for simple types, or calls the value's SerializationOp method to do it.

The point of this somewhat complicated setup is that you just need to do vRecv >> tx to (securely) unserialize a whole transaction, and CTransaction only needs to have a few lines of code to make this happen.
staff
Activity: 3374
Merit: 6530
Just writing some code
Another thing to help you as you look through bitcoin, the official documentation. You can find it here: https://dev.visucore.com/bitcoin/doxygen/
legendary
Activity: 1722
Merit: 1003
Thanks DumbFruit, though I was looking for where txns are created when processing messages from other nodes (as opposed to within my node's wallet).

Found it, though: https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp#L4195
Code:
...
CTransaction tx;
vRecv >> tx;
...

I was looking for a "new CTransaction" somewhere, which doesn't exist since the above is how the tx obj is created from the bytes read into a CNetMessage obj. Guess I have to refamiliarize myself with C++'s serialization operators (it's been almost 20yrs).


For reference, this was also helpful: https://en.bitcoin.it/wiki/Satoshi_Client_Sockets_and_Messages


sr. member
Activity: 433
Merit: 263
I don't do C++ programming, so I apologize if this is totally wrong, but I think it's created here starting on line 1783;
https://github.com/bitcoin/bitcoin/blob/master/src/wallet/wallet.cpp

It gets pushed out as a CWalletTx and gets parsed into CTransaction/CMutableTransaction on the miner side.
legendary
Activity: 1722
Merit: 1003
I see in net.cpp where protocol messages are read in, and various places throughout the codebase where CTransaction objects are used, but I don't see where any CTransaction objects (or CMutableTransaction objs) are initially created.

What am I missing? How are the bytes read in from CNode::ReceiveMsgBytes() turned into CTransaction objects (for inclusion in the mempool, etc)?
Jump to: