1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include <script/bitcoinconsensus.h>
8 #include <primitives/transaction.h>
10 #include <script/interpreter.h>
15 /** A class that deserializes a single CTransaction one time. */
19 TxInputStream(int nTypeIn
, int nVersionIn
, const unsigned char *txTo
, size_t txToLen
) :
21 m_version(nVersionIn
),
26 void read(char* pch
, size_t nSize
)
28 if (nSize
> m_remaining
)
29 throw std::ios_base::failure(std::string(__func__
) + ": end of data");
32 throw std::ios_base::failure(std::string(__func__
) + ": bad destination buffer");
34 if (m_data
== nullptr)
35 throw std::ios_base::failure(std::string(__func__
) + ": bad source buffer");
37 memcpy(pch
, m_data
, nSize
);
43 TxInputStream
& operator>>(T
& obj
)
45 ::Unserialize(*this, obj
);
49 int GetVersion() const { return m_version
; }
50 int GetType() const { return m_type
; }
54 const unsigned char* m_data
;
58 inline int set_error(bitcoinconsensus_error
* ret
, bitcoinconsensus_error serror
)
65 struct ECCryptoClosure
67 ECCVerifyHandle handle
;
70 ECCryptoClosure instance_of_eccryptoclosure
;
73 /** Check that all specified flags are part of the libconsensus interface. */
74 static bool verify_flags(unsigned int flags
)
76 return (flags
& ~(bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL
)) == 0;
79 static int verify_script(const unsigned char *scriptPubKey
, unsigned int scriptPubKeyLen
, CAmount amount
,
80 const unsigned char *txTo
, unsigned int txToLen
,
81 unsigned int nIn
, unsigned int flags
, bitcoinconsensus_error
* err
)
83 if (!verify_flags(flags
)) {
84 return bitcoinconsensus_ERR_INVALID_FLAGS
;
87 TxInputStream
stream(SER_NETWORK
, PROTOCOL_VERSION
, txTo
, txToLen
);
88 CTransaction
tx(deserialize
, stream
);
89 if (nIn
>= tx
.vin
.size())
90 return set_error(err
, bitcoinconsensus_ERR_TX_INDEX
);
91 if (GetSerializeSize(tx
, SER_NETWORK
, PROTOCOL_VERSION
) != txToLen
)
92 return set_error(err
, bitcoinconsensus_ERR_TX_SIZE_MISMATCH
);
94 // Regardless of the verification result, the tx did not error.
95 set_error(err
, bitcoinconsensus_ERR_OK
);
97 PrecomputedTransactionData
txdata(tx
);
98 return VerifyScript(tx
.vin
[nIn
].scriptSig
, CScript(scriptPubKey
, scriptPubKey
+ scriptPubKeyLen
), &tx
.vin
[nIn
].scriptWitness
, flags
, TransactionSignatureChecker(&tx
, nIn
, amount
, txdata
), nullptr);
99 } catch (const std::exception
&) {
100 return set_error(err
, bitcoinconsensus_ERR_TX_DESERIALIZE
); // Error deserializing
104 int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey
, unsigned int scriptPubKeyLen
, int64_t amount
,
105 const unsigned char *txTo
, unsigned int txToLen
,
106 unsigned int nIn
, unsigned int flags
, bitcoinconsensus_error
* err
)
109 return ::verify_script(scriptPubKey
, scriptPubKeyLen
, am
, txTo
, txToLen
, nIn
, flags
, err
);
113 int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey
, unsigned int scriptPubKeyLen
,
114 const unsigned char *txTo
, unsigned int txToLen
,
115 unsigned int nIn
, unsigned int flags
, bitcoinconsensus_error
* err
)
117 if (flags
& bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS
) {
118 return set_error(err
, bitcoinconsensus_ERR_AMOUNT_REQUIRED
);
122 return ::verify_script(scriptPubKey
, scriptPubKeyLen
, am
, txTo
, txToLen
, nIn
, flags
, err
);
125 unsigned int bitcoinconsensus_version()
127 // Just use the API version for now
128 return BITCOINCONSENSUS_API_VER
;