Changeset View
Changeset View
Standalone View
Standalone View
src/psbt.h
Show First 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | template <typename Stream> inline void Serialize(Stream &s) const { | ||||
s << entry.first; | s << entry.first; | ||||
s << entry.second; | s << entry.second; | ||||
} | } | ||||
s << PSBT_SEPARATOR; | s << PSBT_SEPARATOR; | ||||
} | } | ||||
template <typename Stream> inline void Unserialize(Stream &s) { | template <typename Stream> inline void Unserialize(Stream &s) { | ||||
// Used for duplicate key detection | |||||
std::set<std::vector<uint8_t>> key_lookup; | |||||
// Read loop | // Read loop | ||||
bool found_sep = false; | bool found_sep = false; | ||||
while (!s.empty()) { | while (!s.empty()) { | ||||
// Read | // Read | ||||
std::vector<uint8_t> key; | std::vector<uint8_t> key; | ||||
s >> key; | s >> key; | ||||
// the key is empty if that was actually a separator byte | // the key is empty if that was actually a separator byte | ||||
// This is a special case for key lengths 0 as those are not allowed | // This is a special case for key lengths 0 as those are not allowed | ||||
// (except for separator) | // (except for separator) | ||||
if (key.empty()) { | if (key.empty()) { | ||||
found_sep = true; | found_sep = true; | ||||
break; | break; | ||||
} | } | ||||
// First byte of key is the type | // First byte of key is the type | ||||
uint8_t type = key[0]; | uint8_t type = key[0]; | ||||
// Do stuff based on type | // Do stuff based on type | ||||
switch (type) { | switch (type) { | ||||
case PSBT_IN_UTXO: | case PSBT_IN_UTXO: | ||||
if (!utxo.IsNull()) { | if (!key_lookup.emplace(key).second) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Duplicate Key, input utxo already provided"); | "Duplicate Key, input utxo already provided"); | ||||
} else if (key.size() != 1) { | } else if (key.size() != 1) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"utxo key is more than one byte type"); | "utxo key is more than one byte type"); | ||||
} | } | ||||
UnserializeFromVector(s, utxo); | UnserializeFromVector(s, utxo); | ||||
break; | break; | ||||
Show All 21 Lines | template <typename Stream> inline void Unserialize(Stream &s) { | ||||
s >> sig; | s >> sig; | ||||
// Add to list | // Add to list | ||||
partial_sigs.emplace(pubkey.GetID(), | partial_sigs.emplace(pubkey.GetID(), | ||||
SigPair(pubkey, std::move(sig))); | SigPair(pubkey, std::move(sig))); | ||||
break; | break; | ||||
} | } | ||||
case PSBT_IN_SIGHASH: | case PSBT_IN_SIGHASH: | ||||
if (sighash_type.getRawSigHashType() != 0) { | if (!key_lookup.emplace(key).second) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Duplicate Key, input sighash type already " | "Duplicate Key, input sighash type already " | ||||
"provided"); | "provided"); | ||||
} else if (key.size() != 1) { | } else if (key.size() != 1) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Sighash type key is more than one byte type"); | "Sighash type key is more than one byte type"); | ||||
} | } | ||||
UnserializeFromVector(s, sighash_type); | UnserializeFromVector(s, sighash_type); | ||||
break; | break; | ||||
case PSBT_IN_REDEEMSCRIPT: { | case PSBT_IN_REDEEMSCRIPT: { | ||||
if (!redeem_script.empty()) { | if (!key_lookup.emplace(key).second) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Duplicate Key, input redeemScript already " | "Duplicate Key, input redeemScript already " | ||||
"provided"); | "provided"); | ||||
} else if (key.size() != 1) { | } else if (key.size() != 1) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Input redeemScript key is more than one byte " | "Input redeemScript key is more than one byte " | ||||
"type"); | "type"); | ||||
} | } | ||||
s >> redeem_script; | s >> redeem_script; | ||||
break; | break; | ||||
} | } | ||||
case PSBT_IN_BIP32_DERIVATION: { | case PSBT_IN_BIP32_DERIVATION: { | ||||
DeserializeHDKeypaths(s, key, hd_keypaths); | DeserializeHDKeypaths(s, key, hd_keypaths); | ||||
break; | break; | ||||
} | } | ||||
case PSBT_IN_SCRIPTSIG: { | case PSBT_IN_SCRIPTSIG: { | ||||
if (!final_script_sig.empty()) { | if (!key_lookup.emplace(key).second) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Duplicate Key, input final scriptSig already " | "Duplicate Key, input final scriptSig already " | ||||
"provided"); | "provided"); | ||||
} else if (key.size() != 1) { | } else if (key.size() != 1) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Final scriptSig key is more than one byte type"); | "Final scriptSig key is more than one byte type"); | ||||
} | } | ||||
s >> final_script_sig; | s >> final_script_sig; | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | template <typename Stream> inline void Serialize(Stream &s) const { | ||||
s << entry.first; | s << entry.first; | ||||
s << entry.second; | s << entry.second; | ||||
} | } | ||||
s << PSBT_SEPARATOR; | s << PSBT_SEPARATOR; | ||||
} | } | ||||
template <typename Stream> inline void Unserialize(Stream &s) { | template <typename Stream> inline void Unserialize(Stream &s) { | ||||
// Used for duplicate key detection | |||||
std::set<std::vector<uint8_t>> key_lookup; | |||||
// Read loop | // Read loop | ||||
bool found_sep = false; | bool found_sep = false; | ||||
while (!s.empty()) { | while (!s.empty()) { | ||||
// Read | // Read | ||||
std::vector<uint8_t> key; | std::vector<uint8_t> key; | ||||
s >> key; | s >> key; | ||||
// the key is empty if that was actually a separator byte | // the key is empty if that was actually a separator byte | ||||
// This is a special case for key lengths 0 as those are not allowed | // This is a special case for key lengths 0 as those are not allowed | ||||
// (except for separator) | // (except for separator) | ||||
if (key.empty()) { | if (key.empty()) { | ||||
found_sep = true; | found_sep = true; | ||||
break; | break; | ||||
} | } | ||||
// First byte of key is the type | // First byte of key is the type | ||||
uint8_t type = key[0]; | uint8_t type = key[0]; | ||||
// Do stuff based on type | // Do stuff based on type | ||||
switch (type) { | switch (type) { | ||||
case PSBT_OUT_REDEEMSCRIPT: { | case PSBT_OUT_REDEEMSCRIPT: { | ||||
if (!redeem_script.empty()) { | if (!key_lookup.emplace(key).second) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Duplicate Key, output redeemScript already " | "Duplicate Key, output redeemScript already " | ||||
"provided"); | "provided"); | ||||
} else if (key.size() != 1) { | } else if (key.size() != 1) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Output redeemScript key is more than one byte " | "Output redeemScript key is more than one byte " | ||||
"type"); | "type"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | struct PartiallySignedTransaction { | ||||
template <typename Stream> inline void Unserialize(Stream &s) { | template <typename Stream> inline void Unserialize(Stream &s) { | ||||
// Read the magic bytes | // Read the magic bytes | ||||
uint8_t magic[5]; | uint8_t magic[5]; | ||||
s >> magic; | s >> magic; | ||||
if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) { | if (!std::equal(magic, magic + 5, PSBT_MAGIC_BYTES)) { | ||||
throw std::ios_base::failure("Invalid PSBT magic bytes"); | throw std::ios_base::failure("Invalid PSBT magic bytes"); | ||||
} | } | ||||
// Used for duplicate key detection | |||||
std::set<std::vector<uint8_t>> key_lookup; | |||||
// Read global data | // Read global data | ||||
bool found_sep = false; | bool found_sep = false; | ||||
while (!s.empty()) { | while (!s.empty()) { | ||||
// Read | // Read | ||||
std::vector<uint8_t> key; | std::vector<uint8_t> key; | ||||
s >> key; | s >> key; | ||||
// the key is empty if that was actually a separator byte | // the key is empty if that was actually a separator byte | ||||
// This is a special case for key lengths 0 as those are not allowed | // This is a special case for key lengths 0 as those are not allowed | ||||
// (except for separator) | // (except for separator) | ||||
if (key.empty()) { | if (key.empty()) { | ||||
found_sep = true; | found_sep = true; | ||||
break; | break; | ||||
} | } | ||||
// First byte of key is the type | // First byte of key is the type | ||||
uint8_t type = key[0]; | uint8_t type = key[0]; | ||||
// Do stuff based on type | // Do stuff based on type | ||||
switch (type) { | switch (type) { | ||||
case PSBT_GLOBAL_UNSIGNED_TX: { | case PSBT_GLOBAL_UNSIGNED_TX: { | ||||
if (tx) { | if (!key_lookup.emplace(key).second) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Duplicate Key, unsigned tx already provided"); | "Duplicate Key, unsigned tx already provided"); | ||||
} else if (key.size() != 1) { | } else if (key.size() != 1) { | ||||
throw std::ios_base::failure( | throw std::ios_base::failure( | ||||
"Global unsigned tx key is more than one byte " | "Global unsigned tx key is more than one byte " | ||||
"type"); | "type"); | ||||
} | } | ||||
CMutableTransaction mtx; | CMutableTransaction mtx; | ||||
▲ Show 20 Lines • Show All 151 Lines • Show Last 20 Lines |