Skip to content

Commit f372a01

Browse files
committed
Merge #215: [Consensus] Change Elements serialization format
d3a48d5 changed elements serialization to new style with no marker 0x00 byte and witness data at the end (tdudz)
2 parents de19cfe + d3a48d5 commit f372a01

File tree

8 files changed

+43
-79
lines changed

8 files changed

+43
-79
lines changed

qa/rpc-tests/test_framework/mininode.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -598,25 +598,17 @@ def __init__(self, tx=None):
598598

599599
def deserialize(self, f):
600600
self.nVersion = struct.unpack("<i", f.read(4))[0]
601+
flags = struct.unpack("<B", f.read(1))[0]
601602
self.vin = deser_vector(f, CTxIn)
602-
flags = 0
603-
if len(self.vin) == 0:
604-
flags = struct.unpack("<B", f.read(1))[0]
605-
# Not sure why flags can't be zero, but this
606-
# matches the implementation in bitcoind
607-
if (flags != 0):
608-
self.vin = deser_vector(f, CTxIn)
609-
self.vout = deser_vector(f, CTxOut)
610-
else:
611-
self.vout = deser_vector(f, CTxOut)
603+
self.vout = deser_vector(f, CTxOut)
604+
self.nLockTime = struct.unpack("<I", f.read(4))[0]
612605
if flags & 1 > 0:
613606
self.wit.vtxinwit = [CTxInWitness() for i in range(len(self.vin))]
614607
self.wit.vtxoutwit = [CTxOutWitness() for i in range(len(self.vout))]
615608
self.wit.deserialize(f)
616-
617609
if flags > 1:
618610
raise TypeError('Extra witness flags:' + str(flags))
619-
self.nLockTime = struct.unpack("<I", f.read(4))[0]
611+
620612
self.sha256 = None
621613
self.hash = None
622614

@@ -636,12 +628,10 @@ def serialize_with_witness(self):
636628
flags |= 1
637629
r = b""
638630
r += struct.pack("<i", self.nVersion)
639-
if flags:
640-
dummy = []
641-
r += ser_vector(dummy)
642-
r += struct.pack("<B", flags)
631+
r += struct.pack("<B", flags)
643632
r += ser_vector(self.vin)
644633
r += ser_vector(self.vout)
634+
r += struct.pack("<I", self.nLockTime)
645635
if flags & 1:
646636
if (len(self.wit.vtxinwit) != len(self.vin)):
647637
# vtxinwit must have the same length as vin
@@ -652,7 +642,6 @@ def serialize_with_witness(self):
652642
for i in range(len(self.wit.vtxoutwit), len(self.vout)):
653643
self.wit.vtxoutwit.append(CTxInWitness())
654644
r += self.wit.serialize()
655-
r += struct.pack("<I", self.nLockTime)
656645
return r
657646

658647
def serialize(self):

src/bitcoin-tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ static int CommandLineRawTx(int argc, char* argv[])
906906
if (strHexTx == "-") // "-" implies standard input
907907
strHexTx = readStdin();
908908

909-
if (!DecodeHexTx(tx, strHexTx, true))
909+
if (!DecodeHexTx(tx, strHexTx))
910910
throw std::runtime_error("invalid transaction encoding");
911911

912912
startArg = 2;

src/core_io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class UniValue;
1818
// core_read.cpp
1919
CScript ParseScript(const std::string& s);
2020
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
21-
bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false);
21+
bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx);
2222
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
2323
uint256 ParseHashUV(const UniValue& v, const std::string& strName);
2424
uint256 ParseHashStr(const std::string&, const std::string& strName);

src/core_read.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,26 +88,13 @@ CScript ParseScript(const std::string& s)
8888
return result;
8989
}
9090

91-
bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness)
91+
bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx)
9292
{
9393
if (!IsHex(strHexTx))
9494
return false;
9595

9696
std::vector<unsigned char> txData(ParseHex(strHexTx));
9797

98-
if (fTryNoWitness) {
99-
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
100-
try {
101-
ssData >> tx;
102-
if (ssData.eof()) {
103-
return true;
104-
}
105-
}
106-
catch (const std::exception&) {
107-
// Fall through.
108-
}
109-
}
110-
11198
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
11299
try {
113100
ssData >> tx;

src/primitives/transaction.h

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -615,45 +615,31 @@ class CTxWitness
615615
struct CMutableTransaction;
616616

617617
/**
618-
* Basic transaction serialization format:
618+
* Elements transaction serialization format:
619619
* - int32_t nVersion
620+
* - unsigned char flags
621+
* - bit 1: witness data
620622
* - std::vector<CTxIn> vin
621623
* - std::vector<CTxOut> vout
622624
* - uint32_t nLockTime
623-
*
624-
* Extended transaction serialization format:
625-
* - int32_t nVersion
626-
* - unsigned char dummy = 0x00
627-
* - unsigned char flags (!= 0)
628-
* - std::vector<CTxIn> vin
629-
* - std::vector<CTxOut> vout
630625
* - if (flags & 1):
631626
* - CTxWitness wit;
632-
* - uint32_t nLockTime
633627
*/
634628
template<typename Stream, typename TxType>
635629
inline void UnserializeTransaction(TxType& tx, Stream& s) {
636-
const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);
637630
s >> tx.nVersion;
638631
unsigned char flags = 0;
639632
tx.vin.clear();
640633
tx.vout.clear();
641634
tx.wit.SetNull();
642-
/* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
635+
636+
s >> flags;
643637
s >> tx.vin;
644-
if (tx.vin.size() == 0 && fAllowWitness) {
645-
/* We read a dummy or an empty vin. */
646-
s >> flags;
647-
if (flags != 0) {
648-
s >> tx.vin;
649-
s >> tx.vout;
650-
}
651-
} else {
652-
/* We read a non-empty vin. Assume a normal vout follows. */
653-
s >> tx.vout;
654-
}
655-
if ((flags & 1) && fAllowWitness) {
656-
/* The witness flag is present, and we support witnesses. */
638+
s >> tx.vout;
639+
s >> tx.nLockTime;
640+
641+
if (flags & 1) {
642+
/* The witness flag is present. */
657643
flags ^= 1;
658644
const_cast<CTxWitness*>(&tx.wit)->vtxinwit.resize(tx.vin.size());
659645
const_cast<CTxWitness*>(&tx.wit)->vtxoutwit.resize(tx.vout.size());
@@ -663,43 +649,35 @@ inline void UnserializeTransaction(TxType& tx, Stream& s) {
663649
/* Unknown flag in the serialization */
664650
throw std::ios_base::failure("Unknown transaction optional data");
665651
}
666-
s >> tx.nLockTime;
667652
}
668653

669654
template<typename Stream, typename TxType>
670655
inline void SerializeTransaction(const TxType& tx, Stream& s) {
671-
const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);
672-
656+
const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);
673657
s << tx.nVersion;
674-
675658
unsigned char flags = 0;
676659
// Consistency check
677660
assert(tx.wit.vtxoutwit.size() <= tx.vout.size());
678-
if (fAllowWitness) {
679-
/* Check whether witnesses need to be serialized. */
680-
if (tx.HasWitness()) {
681-
flags |= 1;
682-
}
683-
}
684-
if (flags) {
685-
/* Use extended format in case witnesses are to be serialized. */
686-
std::vector<CTxIn> vinDummy;
687-
s << vinDummy;
688-
s << flags;
661+
662+
/* Check whether witnesses need to be serialized. */
663+
if (fAllowWitness && tx.HasWitness()) {
664+
flags |= 1;
689665
}
666+
667+
s << flags;
690668
s << tx.vin;
691669
s << tx.vout;
670+
s << tx.nLockTime;
671+
692672
if (flags & 1) {
693673
const_cast<CTxWitness*>(&tx.wit)->vtxinwit.resize(tx.vin.size());
694674
const_cast<CTxWitness*>(&tx.wit)->vtxoutwit.resize(tx.vout.size());
695675
s << tx.wit;
696676
}
697-
s << tx.nLockTime;
698677
}
699678

700-
701679
/** The basic transaction that is broadcasted on the network and contained in
702-
* blocks. A transaction can contain multiple inputs and outputs.
680+
* blocks. A transaction can contain multiple inputs and outputs.
703681
*/
704682
class CTransaction
705683
{

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
10751075

10761076
CMutableTransaction mtx;
10771077

1078-
if (!DecodeHexTx(mtx, request.params[0].get_str(), true))
1078+
if (!DecodeHexTx(mtx, request.params[0].get_str()))
10791079
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
10801080

10811081
UniValue result(UniValue::VOBJ);

0 commit comments

Comments
 (0)