| 1684 | |
| 1685 | template <typename Stream> |
| 1686 | inline void Unserialize(Stream& s) { |
| 1687 | // Read the magic bytes |
| 1688 | uint8_t magic[5]; |
| 1689 | s >> magic; |
| 1690 | if (!std::equal(magic, magic + 5, PSBT_ELEMENTS_MAGIC_BYTES)) { |
| 1691 | throw std::ios_base::failure("Invalid PSBT magic bytes"); |
| 1692 | } |
| 1693 | |
| 1694 | // Used for duplicate key detection |
| 1695 | std::set<std::vector<unsigned char>> key_lookup; |
| 1696 | |
| 1697 | // Track the global xpubs we have already seen. Just for sanity checking |
| 1698 | std::set<CExtPubKey> global_xpubs; |
| 1699 | |
| 1700 | // Read global data |
| 1701 | bool found_sep = false; |
| 1702 | uint64_t input_count = 0; |
| 1703 | uint64_t output_count = 0; |
| 1704 | bool found_input_count = false; |
| 1705 | bool found_output_count = false; |
| 1706 | while(!s.empty()) { |
| 1707 | // Read |
| 1708 | std::vector<unsigned char> key; |
| 1709 | s >> key; |
| 1710 | |
| 1711 | // the key is empty if that was actually a separator byte |
| 1712 | // This is a special case for key lengths 0 as those are not allowed (except for separator) |
| 1713 | if (key.empty()) { |
| 1714 | found_sep = true; |
| 1715 | break; |
| 1716 | } |
| 1717 | |
| 1718 | // Type is compact size uint at beginning of key |
| 1719 | SpanReader skey(s.GetType(), s.GetVersion(), key); |
| 1720 | uint64_t type = ReadCompactSize(skey); |
| 1721 | |
| 1722 | // Do stuff based on type |
| 1723 | switch(type) { |
| 1724 | case PSBT_GLOBAL_UNSIGNED_TX: |
| 1725 | { |
| 1726 | if (g_con_elementsmode) { |
| 1727 | throw std::ios_base::failure("Unsigned tx is not allowed in PSET"); |
| 1728 | } |
| 1729 | if (!key_lookup.emplace(key).second) { |
| 1730 | throw std::ios_base::failure("Duplicate Key, unsigned tx already provided"); |
| 1731 | } else if (key.size() != 1) { |
| 1732 | throw std::ios_base::failure("Global unsigned tx key is more than one byte type"); |
| 1733 | } |
| 1734 | CMutableTransaction mtx; |
| 1735 | // Set the stream to serialize with non-witness since this should always be non-witness |
| 1736 | OverrideStream<Stream> os(&s, s.GetType(), s.GetVersion() | SERIALIZE_TRANSACTION_NO_WITNESS); |
| 1737 | UnserializeFromVector(os, mtx); |
| 1738 | tx = std::move(mtx); |
| 1739 | // Make sure that all scriptSigs and scriptWitnesses are empty |
| 1740 | for (unsigned int i = 0; i < tx->vin.size(); i++) { |
| 1741 | const CTxIn& txin = tx->vin[i]; |
| 1742 | if (!txin.scriptSig.empty() || !tx->witness.vtxinwit[i].scriptWitness.IsNull()) { |
| 1743 | throw std::ios_base::failure("Unsigned tx does not have empty scriptSigs and scriptWitnesses."); |
nothing calls this directly
no test coverage detected