aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2018-08-14 16:42:36 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2018-08-14 16:52:36 +0200
commit3e5424faf6ff4f0990f7b3b9ca879d434f2abbb2 (patch)
treed28eb61520e2d0ad6edd8272452d4b345982c34a /src
parentdabfcb03071ebb4d36fbc42a9f16b092389e2868 (diff)
parentbd19cc78cfc455cf06e120adb0d12c2f96ba8fca (diff)
downloadbitcoin-3e5424faf6ff4f0990f7b3b9ca879d434f2abbb2.tar.xz
Merge #13960: Fix PSBT deserialization of 0-input transactions
bd19cc78cfc455cf06e120adb0d12c2f96ba8fca Serialize non-witness utxo as a non-witness tx but always deserialize as witness (Andrew Chow) 43811e63380d803e037de69dc0567aae590fa109 Fix PSBT deserialization of 0-input transactions (Andrew Chow) Pull request description: 0-input transactions can be ambiguously deserialized as being witness transactions. Since the unsigned transaction is never serialized as a witness transaction as it has no witnesses, we should always deserialize it as a non-witness transaction and set the serialization flags as such. When a transaction is serliazed for the non-witness-utxo, it is always a valid network transaction and thus it should be always be deserialized as a witness transaction and the deserialzation flags are set as such. Fixes #13958 Tree-SHA512: 1937b3cb2618534478d4f533541fb9efce3cb5badb5d1964bfe19400f4aacc6c8ecedaf1f20d26b20baf94f81fd07dfb15b3b08089ecbd63aeecbc18c7c48086
Diffstat (limited to 'src')
-rw-r--r--src/script/sign.h16
-rw-r--r--src/streams.h1
2 files changed, 13 insertions, 4 deletions
diff --git a/src/script/sign.h b/src/script/sign.h
index 24cddda51b..80fda617e9 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -223,7 +223,8 @@ struct PSBTInput
// If there is a non-witness utxo, then don't add the witness one.
if (non_witness_utxo) {
SerializeToVector(s, PSBT_IN_NON_WITNESS_UTXO);
- SerializeToVector(s, non_witness_utxo);
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS);
+ SerializeToVector(os, non_witness_utxo);
} else if (!witness_utxo.IsNull()) {
SerializeToVector(s, PSBT_IN_WITNESS_UTXO);
SerializeToVector(s, witness_utxo);
@@ -297,13 +298,17 @@ struct PSBTInput
// Do stuff based on type
switch(type) {
case PSBT_IN_NON_WITNESS_UTXO:
+ {
if (non_witness_utxo) {
throw std::ios_base::failure("Duplicate Key, input non-witness utxo already provided");
} else if (key.size() != 1) {
throw std::ios_base::failure("Non-witness utxo key is more than one byte type");
}
- UnserializeFromVector(s, non_witness_utxo);
+ // Set the stream to unserialize with witness since this is always a valid network transaction
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() & ~SERIALIZE_TRANSACTION_NO_WITNESS);
+ UnserializeFromVector(os, non_witness_utxo);
break;
+ }
case PSBT_IN_WITNESS_UTXO:
if (!witness_utxo.IsNull()) {
throw std::ios_base::failure("Duplicate Key, input witness utxo already provided");
@@ -547,7 +552,8 @@ struct PartiallySignedTransaction
SerializeToVector(s, PSBT_GLOBAL_UNSIGNED_TX);
// Write serialized tx to a stream
- SerializeToVector(s, *tx);
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS);
+ SerializeToVector(os, *tx);
// Write the unknown things
for (auto& entry : unknown) {
@@ -601,7 +607,9 @@ struct PartiallySignedTransaction
throw std::ios_base::failure("Global unsigned tx key is more than one byte type");
}
CMutableTransaction mtx;
- UnserializeFromVector(s, mtx);
+ // Set the stream to serialize with non-witness since this should always be non-witness
+ OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS);
+ UnserializeFromVector(os, mtx);
tx = std::move(mtx);
// Make sure that all scriptSigs and scriptWitnesses are empty
for (const CTxIn& txin : tx->vin) {
diff --git a/src/streams.h b/src/streams.h
index 2dcca6646d..096ebfc9c2 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -61,6 +61,7 @@ public:
int GetVersion() const { return nVersion; }
int GetType() const { return nType; }
+ size_t size() const { return stream->size(); }
};
template<typename S>