aboutsummaryrefslogtreecommitdiff
path: root/src/script/sign.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/sign.h')
-rw-r--r--src/script/sign.h75
1 files changed, 58 insertions, 17 deletions
diff --git a/src/script/sign.h b/src/script/sign.h
index e3a6196b28..7ade715ee2 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -43,6 +43,19 @@ public:
bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const;
};
+struct FlatSigningProvider final : public SigningProvider
+{
+ std::map<CScriptID, CScript> scripts;
+ std::map<CKeyID, CPubKey> pubkeys;
+ std::map<CKeyID, CKey> keys;
+
+ bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
+ bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
+ bool GetKey(const CKeyID& keyid, CKey& key) const override;
+};
+
+FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b);
+
/** Interface for signature creators. */
class BaseSignatureCreator {
public:
@@ -67,8 +80,10 @@ public:
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};
-/** A signature creator that just produces 72-byte empty signatures. */
+/** A signature creator that just produces 71-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
+/** A signature creator that just produces 72-byte empty signatures. */
+extern const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR;
typedef std::pair<CPubKey, std::vector<unsigned char>> SigPair;
@@ -116,26 +131,24 @@ static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
// as a 0 length key which indicates that this is the separator. The separator has no value.
static constexpr uint8_t PSBT_SEPARATOR = 0x00;
-// Takes a stream and multiple arguments and serializes them into a vector and then into the stream
+// Takes a stream and multiple arguments and serializes them as if first serialized into a vector and then into the stream
// The resulting output into the stream has the total serialized length of all of the objects followed by all objects concatenated with each other.
template<typename Stream, typename... X>
void SerializeToVector(Stream& s, const X&... args)
{
- std::vector<unsigned char> ret;
- CVectorWriter ss(SER_NETWORK, PROTOCOL_VERSION, ret, 0);
- SerializeMany(ss, args...);
- s << ret;
+ WriteCompactSize(s, GetSerializeSizeMany(s, args...));
+ SerializeMany(s, args...);
}
// Takes a stream and multiple arguments and unserializes them first as a vector then each object individually in the order provided in the arguments
template<typename Stream, typename... X>
void UnserializeFromVector(Stream& s, X&... args)
{
- std::vector<unsigned char> data;
- s >> data;
- CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
- UnserializeMany(ss, args...);
- if (!ss.eof()) {
+ size_t expected_size = ReadCompactSize(s);
+ size_t remaining_before = s.size();
+ UnserializeMany(s, args...);
+ size_t remaining_after = s.size();
+ if (remaining_after + expected_size != remaining_before) {
throw std::ios_base::failure("Size of value was not the stated size");
}
}
@@ -210,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);
@@ -284,14 +298,22 @@ 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");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Witness utxo key is more than one byte type");
}
UnserializeFromVector(s, witness_utxo);
break;
@@ -321,6 +343,8 @@ struct PSBTInput
case PSBT_IN_SIGHASH:
if (sighash_type > 0) {
throw std::ios_base::failure("Duplicate Key, input sighash type already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Sighash type key is more than one byte type");
}
UnserializeFromVector(s, sighash_type);
break;
@@ -328,6 +352,8 @@ struct PSBTInput
{
if (!redeem_script.empty()) {
throw std::ios_base::failure("Duplicate Key, input redeemScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input redeemScript key is more than one byte type");
}
s >> redeem_script;
break;
@@ -336,6 +362,8 @@ struct PSBTInput
{
if (!witness_script.empty()) {
throw std::ios_base::failure("Duplicate Key, input witnessScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input witnessScript key is more than one byte type");
}
s >> witness_script;
break;
@@ -349,6 +377,8 @@ struct PSBTInput
{
if (!final_script_sig.empty()) {
throw std::ios_base::failure("Duplicate Key, input final scriptSig already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Final scriptSig key is more than one byte type");
}
s >> final_script_sig;
break;
@@ -357,6 +387,8 @@ struct PSBTInput
{
if (!final_script_witness.IsNull()) {
throw std::ios_base::failure("Duplicate Key, input final scriptWitness already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Final scriptWitness key is more than one byte type");
}
UnserializeFromVector(s, final_script_witness.stack);
break;
@@ -444,6 +476,8 @@ struct PSBTOutput
{
if (!redeem_script.empty()) {
throw std::ios_base::failure("Duplicate Key, output redeemScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Output redeemScript key is more than one byte type");
}
s >> redeem_script;
break;
@@ -452,6 +486,8 @@ struct PSBTOutput
{
if (!witness_script.empty()) {
throw std::ios_base::failure("Duplicate Key, output witnessScript already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Output witnessScript key is more than one byte type");
}
s >> witness_script;
break;
@@ -516,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) {
@@ -566,9 +603,13 @@ struct PartiallySignedTransaction
{
if (tx) {
throw std::ios_base::failure("Duplicate Key, unsigned tx already provided");
+ } else if (key.size() != 1) {
+ 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) {
@@ -645,7 +686,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
-/** Signs a PSBTInput */
+/** Signs a PSBTInput, verifying that all provided data matches what is being signed. */
bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, SignatureData& sigdata, int index, int sighash = 1);
/** Extract signature data from a transaction input, and insert it. */