2010-08-29 18:58:15 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
2013-10-20 21:25:06 +02:00
|
|
|
// Copyright (c) 2009-2013 The Bitcoin developers
|
2010-08-29 18:58:15 +02:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
2012-05-18 16:02:28 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
#ifndef H_BITCOIN_SCRIPT
|
|
|
|
#define H_BITCOIN_SCRIPT
|
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
#include "key.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <stdint.h>
|
2011-05-15 09:11:04 +02:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2011-06-29 12:17:49 +02:00
|
|
|
#include <boost/foreach.hpp>
|
2012-05-14 23:44:52 +02:00
|
|
|
#include <boost/variant.hpp>
|
|
|
|
|
Ultraprune
This switches bitcoin's transaction/block verification logic to use a
"coin database", which contains all unredeemed transaction output scripts,
amounts and heights.
The name ultraprune comes from the fact that instead of a full transaction
index, we only (need to) keep an index with unspent outputs. For now, the
blocks themselves are kept as usual, although they are only necessary for
serving, rescanning and reorganizing.
The basic datastructures are CCoins (representing the coins of a single
transaction), and CCoinsView (representing a state of the coins database).
There are several implementations for CCoinsView. A dummy, one backed by
the coins database (coins.dat), one backed by the memory pool, and one
that adds a cache on top of it. FetchInputs, ConnectInputs, ConnectBlock,
DisconnectBlock, ... now operate on a generic CCoinsView.
The block switching logic now builds a single cached CCoinsView with
changes to be committed to the database before any changes are made.
This means no uncommitted changes are ever read from the database, and
should ease the transition to another database layer which does not
support transactions (but does support atomic writes), like LevelDB.
For the getrawtransaction() RPC call, access to a txid-to-disk index
would be preferable. As this index is not necessary or even useful
for any other part of the implementation, it is not provided. Instead,
getrawtransaction() uses the coin database to find the block height,
and then scans that block to find the requested transaction. This is
slow, but should suffice for debug purposes.
2012-07-01 18:54:00 +02:00
|
|
|
class CCoins;
|
2013-04-13 07:13:08 +02:00
|
|
|
class CKeyStore;
|
2010-08-29 18:58:15 +02:00
|
|
|
class CTransaction;
|
2014-06-25 20:21:29 +02:00
|
|
|
struct CMutableTransaction;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2013-01-18 19:55:18 +01:00
|
|
|
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
2014-02-26 18:58:08 +01:00
|
|
|
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
|
2013-01-18 19:55:18 +01:00
|
|
|
|
2014-03-26 20:50:29 +01:00
|
|
|
class scriptnum_error : public std::runtime_error
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit scriptnum_error(const std::string& str) : std::runtime_error(str) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CScriptNum
|
|
|
|
{
|
|
|
|
// Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers.
|
|
|
|
// The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1],
|
|
|
|
// but results may overflow (and are valid as long as they are not used in a subsequent
|
|
|
|
// numeric operation). CScriptNum enforces those semantics by storing results as
|
|
|
|
// an int64 and allowing out-of-range values to be returned as a vector of bytes but
|
|
|
|
// throwing an exception if arithmetic is done or the result is interpreted as an integer.
|
|
|
|
public:
|
|
|
|
|
|
|
|
explicit CScriptNum(const int64_t& n)
|
|
|
|
{
|
|
|
|
m_value = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit CScriptNum(const std::vector<unsigned char>& vch)
|
|
|
|
{
|
|
|
|
if (vch.size() > nMaxNumSize)
|
|
|
|
throw scriptnum_error("CScriptNum(const std::vector<unsigned char>&) : overflow");
|
|
|
|
m_value = set_vch(vch);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }
|
|
|
|
inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; }
|
|
|
|
inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; }
|
|
|
|
inline bool operator< (const int64_t& rhs) const { return m_value < rhs; }
|
|
|
|
inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; }
|
|
|
|
inline bool operator> (const int64_t& rhs) const { return m_value > rhs; }
|
|
|
|
|
|
|
|
inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); }
|
|
|
|
inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); }
|
|
|
|
inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); }
|
|
|
|
inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); }
|
|
|
|
inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); }
|
|
|
|
inline bool operator> (const CScriptNum& rhs) const { return operator> (rhs.m_value); }
|
|
|
|
|
|
|
|
inline CScriptNum operator+( const int64_t& rhs) const { return CScriptNum(m_value + rhs);}
|
|
|
|
inline CScriptNum operator-( const int64_t& rhs) const { return CScriptNum(m_value - rhs);}
|
|
|
|
inline CScriptNum operator+( const CScriptNum& rhs) const { return operator+(rhs.m_value); }
|
|
|
|
inline CScriptNum operator-( const CScriptNum& rhs) const { return operator-(rhs.m_value); }
|
|
|
|
|
|
|
|
inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); }
|
|
|
|
inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); }
|
|
|
|
|
|
|
|
inline CScriptNum operator-() const
|
|
|
|
{
|
|
|
|
assert(m_value != std::numeric_limits<int64_t>::min());
|
|
|
|
return CScriptNum(-m_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline CScriptNum& operator=( const int64_t& rhs)
|
|
|
|
{
|
|
|
|
m_value = rhs;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline CScriptNum& operator+=( const int64_t& rhs)
|
|
|
|
{
|
|
|
|
assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
|
|
|
|
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
|
|
|
|
m_value += rhs;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline CScriptNum& operator-=( const int64_t& rhs)
|
|
|
|
{
|
|
|
|
assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
|
|
|
|
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
|
|
|
|
m_value -= rhs;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getint() const
|
|
|
|
{
|
|
|
|
if (m_value > std::numeric_limits<int>::max())
|
|
|
|
return std::numeric_limits<int>::max();
|
|
|
|
else if (m_value < std::numeric_limits<int>::min())
|
|
|
|
return std::numeric_limits<int>::min();
|
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<unsigned char> getvch() const
|
|
|
|
{
|
|
|
|
return serialize(m_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<unsigned char> serialize(const int64_t& value)
|
|
|
|
{
|
|
|
|
if(value == 0)
|
|
|
|
return std::vector<unsigned char>();
|
|
|
|
|
|
|
|
std::vector<unsigned char> result;
|
|
|
|
const bool neg = value < 0;
|
|
|
|
uint64_t absvalue = neg ? -value : value;
|
|
|
|
|
|
|
|
while(absvalue)
|
|
|
|
{
|
|
|
|
result.push_back(absvalue & 0xff);
|
|
|
|
absvalue >>= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// - If the most significant byte is >= 0x80 and the value is positive, push a
|
|
|
|
// new zero-byte to make the significant byte < 0x80 again.
|
|
|
|
|
|
|
|
// - If the most significant byte is >= 0x80 and the value is negative, push a
|
|
|
|
// new 0x80 byte that will be popped off when converting to an integral.
|
|
|
|
|
|
|
|
// - If the most significant byte is < 0x80 and the value is negative, add
|
|
|
|
// 0x80 to it, since it will be subtracted and interpreted as a negative when
|
|
|
|
// converting to an integral.
|
|
|
|
|
|
|
|
if (result.back() & 0x80)
|
|
|
|
result.push_back(neg ? 0x80 : 0);
|
|
|
|
else if (neg)
|
|
|
|
result.back() |= 0x80;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const size_t nMaxNumSize = 4;
|
|
|
|
|
|
|
|
private:
|
|
|
|
static int64_t set_vch(const std::vector<unsigned char>& vch)
|
|
|
|
{
|
|
|
|
if (vch.empty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int64_t result = 0;
|
|
|
|
for (size_t i = 0; i != vch.size(); ++i)
|
|
|
|
result |= static_cast<int64_t>(vch[i]) << 8*i;
|
|
|
|
|
|
|
|
// If the input vector's most significant byte is 0x80, remove it from
|
|
|
|
// the result's msb and return a negative.
|
|
|
|
if (vch.back() & 0x80)
|
|
|
|
return -(result & ~(0x80 << (8 * (vch.size() - 1))));
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t m_value;
|
|
|
|
};
|
|
|
|
|
2012-03-26 16:48:23 +02:00
|
|
|
/** Signature hash types/flags */
|
2010-08-29 18:58:15 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
SIGHASH_ALL = 1,
|
|
|
|
SIGHASH_NONE = 2,
|
|
|
|
SIGHASH_SINGLE = 3,
|
|
|
|
SIGHASH_ANYONECANPAY = 0x80,
|
|
|
|
};
|
|
|
|
|
2012-11-13 23:03:25 +01:00
|
|
|
/** Script verification flags */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
SCRIPT_VERIFY_NONE = 0,
|
Only create signatures with even S, and verification mode to check.
To fix a minor malleability found by Sergio Lerner (reported here:
https://bitcointalk.org/index.php?topic=8392.msg1245898#msg1245898)
The problem is that if (R,S) is a valid ECDSA signature for a given
message and public key, (R,-S) is also valid. Modulo N (the order
of the secp256k1 curve), this means that both (R,S) and (R,N-S) are
valid. Given that N is odd, S and N-S have a different lowest bit.
We solve the problem by forcing signatures to have an even S value,
excluding one of the alternatives.
This commit just changes the signing code to always produce even S
values, and adds a verification mode to check it. This code is not
enabled anywhere yet. Existing tests in key_tests.cpp verify that
the produced signatures are still valid.
2012-12-26 21:10:49 +01:00
|
|
|
SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
|
|
|
|
SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys
|
2014-02-07 02:19:48 +01:00
|
|
|
SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values (<n/2) in signatures (depends on STRICTENC)
|
Only create signatures with even S, and verification mode to check.
To fix a minor malleability found by Sergio Lerner (reported here:
https://bitcointalk.org/index.php?topic=8392.msg1245898#msg1245898)
The problem is that if (R,S) is a valid ECDSA signature for a given
message and public key, (R,-S) is also valid. Modulo N (the order
of the secp256k1 curve), this means that both (R,S) and (R,N-S) are
valid. Given that N is odd, S and N-S have a different lowest bit.
We solve the problem by forcing signatures to have an even S value,
excluding one of the alternatives.
This commit just changes the signing code to always produce even S
values, and adds a verification mode to check it. This code is not
enabled anywhere yet. Existing tests in key_tests.cpp verify that
the produced signatures are still valid.
2012-12-26 21:10:49 +01:00
|
|
|
SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it)
|
2014-03-10 22:36:35 +01:00
|
|
|
SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
|
2012-11-13 23:03:25 +01:00
|
|
|
};
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2014-03-10 22:31:46 +01:00
|
|
|
// Mandatory script verification flags that all new blocks must comply with for
|
|
|
|
// them to be valid. (but old blocks may not comply with) Currently just P2SH,
|
|
|
|
// but in the future other flags may be added, such as a soft-fork to enforce
|
|
|
|
// strict DER encoding.
|
2014-03-11 03:36:46 +01:00
|
|
|
//
|
|
|
|
// Failing one of these tests may trigger a DoS ban - see CheckInputs() for
|
|
|
|
// details.
|
2014-03-10 22:31:46 +01:00
|
|
|
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
|
|
|
|
|
|
|
|
// Standard script verification flags that standard transactions will comply
|
|
|
|
// with. However scripts violating these flags may still be present in valid
|
|
|
|
// blocks and we must accept those blocks.
|
|
|
|
static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
|
2014-03-10 22:36:35 +01:00
|
|
|
SCRIPT_VERIFY_STRICTENC |
|
|
|
|
SCRIPT_VERIFY_NULLDUMMY;
|
2014-03-10 22:31:46 +01:00
|
|
|
|
2014-03-11 03:36:46 +01:00
|
|
|
// For convenience, standard but not mandatory verify flags.
|
|
|
|
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
|
|
|
|
|
2011-11-08 19:20:29 +01:00
|
|
|
enum txnouttype
|
2011-10-03 19:05:43 +02:00
|
|
|
{
|
|
|
|
TX_NONSTANDARD,
|
|
|
|
// 'standard' transaction types:
|
|
|
|
TX_PUBKEY,
|
|
|
|
TX_PUBKEYHASH,
|
|
|
|
TX_SCRIPTHASH,
|
|
|
|
TX_MULTISIG,
|
2013-06-24 21:09:50 +02:00
|
|
|
TX_NULL_DATA,
|
2011-10-03 19:05:43 +02:00
|
|
|
};
|
|
|
|
|
2012-05-14 23:44:52 +02:00
|
|
|
class CNoDestination {
|
|
|
|
public:
|
|
|
|
friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; }
|
|
|
|
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/** A txout script template with a specific destination. It is either:
|
|
|
|
* * CNoDestination: no destination set
|
|
|
|
* * CKeyID: TX_PUBKEYHASH destination
|
|
|
|
* * CScriptID: TX_SCRIPTHASH destination
|
|
|
|
* A CTxDestination is the internal data type encoded in a CBitcoinAddress
|
|
|
|
*/
|
|
|
|
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
|
|
|
|
|
2011-11-08 19:20:29 +01:00
|
|
|
const char* GetTxnOutputType(txnouttype t);
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2012-03-26 16:48:23 +02:00
|
|
|
/** Script opcodes */
|
2010-08-29 18:58:15 +02:00
|
|
|
enum opcodetype
|
|
|
|
{
|
|
|
|
// push value
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_0 = 0x00,
|
|
|
|
OP_FALSE = OP_0,
|
|
|
|
OP_PUSHDATA1 = 0x4c,
|
|
|
|
OP_PUSHDATA2 = 0x4d,
|
|
|
|
OP_PUSHDATA4 = 0x4e,
|
|
|
|
OP_1NEGATE = 0x4f,
|
|
|
|
OP_RESERVED = 0x50,
|
|
|
|
OP_1 = 0x51,
|
2010-08-29 18:58:15 +02:00
|
|
|
OP_TRUE=OP_1,
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_2 = 0x52,
|
|
|
|
OP_3 = 0x53,
|
|
|
|
OP_4 = 0x54,
|
|
|
|
OP_5 = 0x55,
|
|
|
|
OP_6 = 0x56,
|
|
|
|
OP_7 = 0x57,
|
|
|
|
OP_8 = 0x58,
|
|
|
|
OP_9 = 0x59,
|
|
|
|
OP_10 = 0x5a,
|
|
|
|
OP_11 = 0x5b,
|
|
|
|
OP_12 = 0x5c,
|
|
|
|
OP_13 = 0x5d,
|
|
|
|
OP_14 = 0x5e,
|
|
|
|
OP_15 = 0x5f,
|
|
|
|
OP_16 = 0x60,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// control
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_NOP = 0x61,
|
|
|
|
OP_VER = 0x62,
|
|
|
|
OP_IF = 0x63,
|
|
|
|
OP_NOTIF = 0x64,
|
|
|
|
OP_VERIF = 0x65,
|
|
|
|
OP_VERNOTIF = 0x66,
|
|
|
|
OP_ELSE = 0x67,
|
|
|
|
OP_ENDIF = 0x68,
|
|
|
|
OP_VERIFY = 0x69,
|
|
|
|
OP_RETURN = 0x6a,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// stack ops
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_TOALTSTACK = 0x6b,
|
|
|
|
OP_FROMALTSTACK = 0x6c,
|
|
|
|
OP_2DROP = 0x6d,
|
|
|
|
OP_2DUP = 0x6e,
|
|
|
|
OP_3DUP = 0x6f,
|
|
|
|
OP_2OVER = 0x70,
|
|
|
|
OP_2ROT = 0x71,
|
|
|
|
OP_2SWAP = 0x72,
|
|
|
|
OP_IFDUP = 0x73,
|
|
|
|
OP_DEPTH = 0x74,
|
|
|
|
OP_DROP = 0x75,
|
|
|
|
OP_DUP = 0x76,
|
|
|
|
OP_NIP = 0x77,
|
|
|
|
OP_OVER = 0x78,
|
|
|
|
OP_PICK = 0x79,
|
|
|
|
OP_ROLL = 0x7a,
|
|
|
|
OP_ROT = 0x7b,
|
|
|
|
OP_SWAP = 0x7c,
|
|
|
|
OP_TUCK = 0x7d,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// splice ops
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_CAT = 0x7e,
|
|
|
|
OP_SUBSTR = 0x7f,
|
|
|
|
OP_LEFT = 0x80,
|
|
|
|
OP_RIGHT = 0x81,
|
|
|
|
OP_SIZE = 0x82,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// bit logic
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_INVERT = 0x83,
|
|
|
|
OP_AND = 0x84,
|
|
|
|
OP_OR = 0x85,
|
|
|
|
OP_XOR = 0x86,
|
|
|
|
OP_EQUAL = 0x87,
|
|
|
|
OP_EQUALVERIFY = 0x88,
|
|
|
|
OP_RESERVED1 = 0x89,
|
|
|
|
OP_RESERVED2 = 0x8a,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// numeric
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_1ADD = 0x8b,
|
|
|
|
OP_1SUB = 0x8c,
|
|
|
|
OP_2MUL = 0x8d,
|
|
|
|
OP_2DIV = 0x8e,
|
|
|
|
OP_NEGATE = 0x8f,
|
|
|
|
OP_ABS = 0x90,
|
|
|
|
OP_NOT = 0x91,
|
|
|
|
OP_0NOTEQUAL = 0x92,
|
|
|
|
|
|
|
|
OP_ADD = 0x93,
|
|
|
|
OP_SUB = 0x94,
|
|
|
|
OP_MUL = 0x95,
|
|
|
|
OP_DIV = 0x96,
|
|
|
|
OP_MOD = 0x97,
|
|
|
|
OP_LSHIFT = 0x98,
|
|
|
|
OP_RSHIFT = 0x99,
|
|
|
|
|
|
|
|
OP_BOOLAND = 0x9a,
|
|
|
|
OP_BOOLOR = 0x9b,
|
|
|
|
OP_NUMEQUAL = 0x9c,
|
|
|
|
OP_NUMEQUALVERIFY = 0x9d,
|
|
|
|
OP_NUMNOTEQUAL = 0x9e,
|
|
|
|
OP_LESSTHAN = 0x9f,
|
|
|
|
OP_GREATERTHAN = 0xa0,
|
|
|
|
OP_LESSTHANOREQUAL = 0xa1,
|
|
|
|
OP_GREATERTHANOREQUAL = 0xa2,
|
|
|
|
OP_MIN = 0xa3,
|
|
|
|
OP_MAX = 0xa4,
|
|
|
|
|
|
|
|
OP_WITHIN = 0xa5,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// crypto
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_RIPEMD160 = 0xa6,
|
|
|
|
OP_SHA1 = 0xa7,
|
|
|
|
OP_SHA256 = 0xa8,
|
|
|
|
OP_HASH160 = 0xa9,
|
|
|
|
OP_HASH256 = 0xaa,
|
|
|
|
OP_CODESEPARATOR = 0xab,
|
|
|
|
OP_CHECKSIG = 0xac,
|
|
|
|
OP_CHECKSIGVERIFY = 0xad,
|
|
|
|
OP_CHECKMULTISIG = 0xae,
|
|
|
|
OP_CHECKMULTISIGVERIFY = 0xaf,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// expansion
|
2012-04-21 10:10:48 +02:00
|
|
|
OP_NOP1 = 0xb0,
|
|
|
|
OP_NOP2 = 0xb1,
|
|
|
|
OP_NOP3 = 0xb2,
|
|
|
|
OP_NOP4 = 0xb3,
|
|
|
|
OP_NOP5 = 0xb4,
|
|
|
|
OP_NOP6 = 0xb5,
|
|
|
|
OP_NOP7 = 0xb6,
|
|
|
|
OP_NOP8 = 0xb7,
|
|
|
|
OP_NOP9 = 0xb8,
|
|
|
|
OP_NOP10 = 0xb9,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// template matching params
|
2013-06-24 21:09:50 +02:00
|
|
|
OP_SMALLDATA = 0xf9,
|
2011-10-03 19:05:43 +02:00
|
|
|
OP_SMALLINTEGER = 0xfa,
|
|
|
|
OP_PUBKEYS = 0xfb,
|
2010-09-07 03:12:53 +02:00
|
|
|
OP_PUBKEYHASH = 0xfd,
|
|
|
|
OP_PUBKEY = 0xfe,
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2010-09-07 03:12:53 +02:00
|
|
|
OP_INVALIDOPCODE = 0xff,
|
2010-08-29 18:58:15 +02:00
|
|
|
};
|
|
|
|
|
2011-10-03 19:05:43 +02:00
|
|
|
const char* GetOpName(opcodetype opcode);
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
inline std::string ValueString(const std::vector<unsigned char>& vch)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
if (vch.size() <= 4)
|
2014-03-26 20:55:35 +01:00
|
|
|
return strprintf("%d", CScriptNum(vch).getint());
|
2010-08-29 18:58:15 +02:00
|
|
|
else
|
2010-09-07 03:12:53 +02:00
|
|
|
return HexStr(vch);
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
inline std::string StackString(const std::vector<std::vector<unsigned char> >& vStack)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
2011-05-15 09:11:04 +02:00
|
|
|
std::string str;
|
|
|
|
BOOST_FOREACH(const std::vector<unsigned char>& vch, vStack)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
if (!str.empty())
|
|
|
|
str += " ";
|
|
|
|
str += ValueString(vch);
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-03-26 16:48:23 +02:00
|
|
|
/** Serialized script, used inside transaction inputs and outputs */
|
2011-05-15 09:11:04 +02:00
|
|
|
class CScript : public std::vector<unsigned char>
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
protected:
|
2013-04-13 07:13:08 +02:00
|
|
|
CScript& push_int64(int64_t n)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
if (n == -1 || (n >= 1 && n <= 16))
|
|
|
|
{
|
|
|
|
push_back(n + (OP_1 - 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-03-26 20:55:35 +01:00
|
|
|
*this << CScriptNum::serialize(n);
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
2010-09-07 03:12:53 +02:00
|
|
|
return *this;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
public:
|
|
|
|
CScript() { }
|
2011-05-15 09:11:04 +02:00
|
|
|
CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { }
|
|
|
|
CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { }
|
2010-08-29 18:58:15 +02:00
|
|
|
#ifndef _MSC_VER
|
2011-05-15 09:11:04 +02:00
|
|
|
CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { }
|
2010-08-29 18:58:15 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
CScript& operator+=(const CScript& b)
|
|
|
|
{
|
|
|
|
insert(end(), b.begin(), b.end());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend CScript operator+(const CScript& a, const CScript& b)
|
|
|
|
{
|
|
|
|
CScript ret = a;
|
|
|
|
ret += b;
|
2010-09-07 03:12:53 +02:00
|
|
|
return ret;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-26 20:55:35 +01:00
|
|
|
CScript(int64_t b) { operator<<(b); }
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
explicit CScript(opcodetype b) { operator<<(b); }
|
|
|
|
explicit CScript(const uint256& b) { operator<<(b); }
|
2014-03-26 20:55:35 +01:00
|
|
|
explicit CScript(const CScriptNum& b) { operator<<(b); }
|
2011-05-15 09:11:04 +02:00
|
|
|
explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); }
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
|
2014-03-26 20:55:35 +01:00
|
|
|
CScript& operator<<(int64_t b) { return push_int64(b); }
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
CScript& operator<<(opcodetype opcode)
|
|
|
|
{
|
2010-09-07 03:12:53 +02:00
|
|
|
if (opcode < 0 || opcode > 0xff)
|
2011-05-15 09:11:04 +02:00
|
|
|
throw std::runtime_error("CScript::operator<<() : invalid opcode");
|
2010-09-07 03:12:53 +02:00
|
|
|
insert(end(), (unsigned char)opcode);
|
|
|
|
return *this;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CScript& operator<<(const uint160& b)
|
|
|
|
{
|
|
|
|
insert(end(), sizeof(b));
|
|
|
|
insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b));
|
2010-09-07 03:12:53 +02:00
|
|
|
return *this;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CScript& operator<<(const uint256& b)
|
|
|
|
{
|
|
|
|
insert(end(), sizeof(b));
|
|
|
|
insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b));
|
2010-09-07 03:12:53 +02:00
|
|
|
return *this;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
2012-05-14 19:07:52 +02:00
|
|
|
CScript& operator<<(const CPubKey& key)
|
|
|
|
{
|
2013-04-30 21:56:04 +02:00
|
|
|
assert(key.size() < OP_PUSHDATA1);
|
|
|
|
insert(end(), (unsigned char)key.size());
|
|
|
|
insert(end(), key.begin(), key.end());
|
|
|
|
return *this;
|
2012-05-14 19:07:52 +02:00
|
|
|
}
|
|
|
|
|
2014-03-26 20:55:35 +01:00
|
|
|
CScript& operator<<(const CScriptNum& b)
|
|
|
|
{
|
|
|
|
*this << b.getvch();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
CScript& operator<<(const std::vector<unsigned char>& b)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
if (b.size() < OP_PUSHDATA1)
|
|
|
|
{
|
|
|
|
insert(end(), (unsigned char)b.size());
|
|
|
|
}
|
|
|
|
else if (b.size() <= 0xff)
|
|
|
|
{
|
|
|
|
insert(end(), OP_PUSHDATA1);
|
|
|
|
insert(end(), (unsigned char)b.size());
|
|
|
|
}
|
2010-09-07 03:12:53 +02:00
|
|
|
else if (b.size() <= 0xffff)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
insert(end(), OP_PUSHDATA2);
|
|
|
|
unsigned short nSize = b.size();
|
|
|
|
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
|
|
|
|
}
|
2010-09-07 03:12:53 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
insert(end(), OP_PUSHDATA4);
|
|
|
|
unsigned int nSize = b.size();
|
|
|
|
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
insert(end(), b.begin(), b.end());
|
2010-09-07 03:12:53 +02:00
|
|
|
return *this;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CScript& operator<<(const CScript& b)
|
|
|
|
{
|
|
|
|
// I'm not sure if this should push the script or concatenate scripts.
|
|
|
|
// If there's ever a use for pushing a script onto a script, delete this member fn
|
2012-07-27 08:36:43 +02:00
|
|
|
assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!");
|
2010-09-07 03:12:53 +02:00
|
|
|
return *this;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
// Wrapper so it can be called with either iterator or const_iterator
|
|
|
|
const_iterator pc2 = pc;
|
2010-09-07 03:12:53 +02:00
|
|
|
bool fRet = GetOp2(pc2, opcodeRet, &vchRet);
|
|
|
|
pc = begin() + (pc2 - begin());
|
|
|
|
return fRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GetOp(iterator& pc, opcodetype& opcodeRet)
|
|
|
|
{
|
|
|
|
const_iterator pc2 = pc;
|
|
|
|
bool fRet = GetOp2(pc2, opcodeRet, NULL);
|
2010-08-29 18:58:15 +02:00
|
|
|
pc = begin() + (pc2 - begin());
|
|
|
|
return fRet;
|
|
|
|
}
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
|
2010-09-07 03:12:53 +02:00
|
|
|
{
|
|
|
|
return GetOp2(pc, opcodeRet, &vchRet);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
|
|
|
|
{
|
|
|
|
return GetOp2(pc, opcodeRet, NULL);
|
|
|
|
}
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) const
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
opcodeRet = OP_INVALIDOPCODE;
|
2010-09-07 03:12:53 +02:00
|
|
|
if (pvchRet)
|
|
|
|
pvchRet->clear();
|
2010-08-29 18:58:15 +02:00
|
|
|
if (pc >= end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Read instruction
|
2010-09-07 03:12:53 +02:00
|
|
|
if (end() - pc < 1)
|
|
|
|
return false;
|
2010-08-29 18:58:15 +02:00
|
|
|
unsigned int opcode = *pc++;
|
|
|
|
|
|
|
|
// Immediate operand
|
|
|
|
if (opcode <= OP_PUSHDATA4)
|
|
|
|
{
|
2013-01-15 23:27:29 +01:00
|
|
|
unsigned int nSize = 0;
|
2010-09-07 03:12:53 +02:00
|
|
|
if (opcode < OP_PUSHDATA1)
|
|
|
|
{
|
|
|
|
nSize = opcode;
|
|
|
|
}
|
|
|
|
else if (opcode == OP_PUSHDATA1)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
2010-09-07 03:12:53 +02:00
|
|
|
if (end() - pc < 1)
|
2010-08-29 18:58:15 +02:00
|
|
|
return false;
|
|
|
|
nSize = *pc++;
|
|
|
|
}
|
|
|
|
else if (opcode == OP_PUSHDATA2)
|
|
|
|
{
|
2010-09-07 03:12:53 +02:00
|
|
|
if (end() - pc < 2)
|
2010-08-29 18:58:15 +02:00
|
|
|
return false;
|
|
|
|
nSize = 0;
|
|
|
|
memcpy(&nSize, &pc[0], 2);
|
|
|
|
pc += 2;
|
|
|
|
}
|
|
|
|
else if (opcode == OP_PUSHDATA4)
|
|
|
|
{
|
2010-09-07 03:12:53 +02:00
|
|
|
if (end() - pc < 4)
|
2010-08-29 18:58:15 +02:00
|
|
|
return false;
|
|
|
|
memcpy(&nSize, &pc[0], 4);
|
|
|
|
pc += 4;
|
|
|
|
}
|
2012-07-02 16:29:14 +02:00
|
|
|
if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize)
|
2010-08-29 18:58:15 +02:00
|
|
|
return false;
|
2010-09-07 03:12:53 +02:00
|
|
|
if (pvchRet)
|
|
|
|
pvchRet->assign(pc, pc + nSize);
|
2010-08-29 18:58:15 +02:00
|
|
|
pc += nSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
opcodeRet = (opcodetype)opcode;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-10-03 19:05:43 +02:00
|
|
|
// Encode/decode small integers:
|
2011-09-28 18:30:06 +02:00
|
|
|
static int DecodeOP_N(opcodetype opcode)
|
|
|
|
{
|
|
|
|
if (opcode == OP_0)
|
|
|
|
return 0;
|
|
|
|
assert(opcode >= OP_1 && opcode <= OP_16);
|
|
|
|
return (int)opcode - (int)(OP_1 - 1);
|
|
|
|
}
|
2011-10-03 19:05:43 +02:00
|
|
|
static opcodetype EncodeOP_N(int n)
|
|
|
|
{
|
|
|
|
assert(n >= 0 && n <= 16);
|
|
|
|
if (n == 0)
|
|
|
|
return OP_0;
|
|
|
|
return (opcodetype)(OP_1+n-1);
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2011-10-03 19:05:43 +02:00
|
|
|
int FindAndDelete(const CScript& b)
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
2011-10-03 19:05:43 +02:00
|
|
|
int nFound = 0;
|
2010-09-07 03:12:53 +02:00
|
|
|
if (b.empty())
|
2011-10-03 19:05:43 +02:00
|
|
|
return nFound;
|
2010-08-29 18:58:15 +02:00
|
|
|
iterator pc = begin();
|
|
|
|
opcodetype opcode;
|
|
|
|
do
|
|
|
|
{
|
2012-04-22 19:51:16 +02:00
|
|
|
while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0)
|
2011-10-03 19:05:43 +02:00
|
|
|
{
|
2010-08-29 18:58:15 +02:00
|
|
|
erase(pc, pc + b.size());
|
2011-10-03 19:05:43 +02:00
|
|
|
++nFound;
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
2010-09-07 03:12:53 +02:00
|
|
|
while (GetOp(pc, opcode));
|
2011-10-03 19:05:43 +02:00
|
|
|
return nFound;
|
|
|
|
}
|
|
|
|
int Find(opcodetype op) const
|
|
|
|
{
|
|
|
|
int nFound = 0;
|
|
|
|
opcodetype opcode;
|
|
|
|
for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);)
|
|
|
|
if (opcode == op)
|
|
|
|
++nFound;
|
|
|
|
return nFound;
|
2010-09-07 03:12:53 +02:00
|
|
|
}
|
|
|
|
|
2012-01-05 03:40:52 +01:00
|
|
|
// Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
|
|
|
|
// as 20 sigops. With pay-to-script-hash, that changed:
|
|
|
|
// CHECKMULTISIGs serialized in scriptSigs are
|
|
|
|
// counted more accurately, assuming they are of the form
|
|
|
|
// ... OP_N CHECKMULTISIG ...
|
2012-04-23 20:14:03 +02:00
|
|
|
unsigned int GetSigOpCount(bool fAccurate) const;
|
2012-01-05 03:40:52 +01:00
|
|
|
|
|
|
|
// Accurately count sigOps, including sigOps in
|
|
|
|
// pay-to-script-hash transactions:
|
2012-04-23 20:14:03 +02:00
|
|
|
unsigned int GetSigOpCount(const CScript& scriptSig) const;
|
2012-01-05 03:40:52 +01:00
|
|
|
|
|
|
|
bool IsPayToScriptHash() const;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2013-09-24 00:48:00 +02:00
|
|
|
// Called by IsStandardTx and P2SH VerifyScript (which makes it consensus-critical).
|
2013-09-24 00:45:18 +02:00
|
|
|
bool IsPushOnly() const;
|
2010-12-07 14:43:31 +01:00
|
|
|
|
2013-09-24 00:48:00 +02:00
|
|
|
// Called by IsStandardTx.
|
|
|
|
bool HasCanonicalPushes() const;
|
|
|
|
|
2013-06-24 20:51:08 +02:00
|
|
|
// Returns whether the script is guaranteed to fail at execution,
|
|
|
|
// regardless of the initial stack. This allows outputs to be pruned
|
|
|
|
// instantly when entering the UTXO set.
|
|
|
|
bool IsUnspendable() const
|
|
|
|
{
|
|
|
|
return (size() > 0 && *begin() == OP_RETURN);
|
|
|
|
}
|
2010-12-07 14:43:31 +01:00
|
|
|
|
2012-05-14 23:44:52 +02:00
|
|
|
void SetDestination(const CTxDestination& address);
|
2013-05-01 06:52:05 +02:00
|
|
|
void SetMultisig(int nRequired, const std::vector<CPubKey>& keys);
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
std::string ToString() const
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
2011-05-15 09:11:04 +02:00
|
|
|
std::string str;
|
2010-08-29 18:58:15 +02:00
|
|
|
opcodetype opcode;
|
2011-05-15 09:11:04 +02:00
|
|
|
std::vector<unsigned char> vch;
|
2010-09-07 03:12:53 +02:00
|
|
|
const_iterator pc = begin();
|
|
|
|
while (pc < end())
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
|
|
|
if (!str.empty())
|
|
|
|
str += " ";
|
2010-09-07 03:12:53 +02:00
|
|
|
if (!GetOp(pc, opcode, vch))
|
|
|
|
{
|
|
|
|
str += "[error]";
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
if (0 <= opcode && opcode <= OP_PUSHDATA4)
|
2010-08-29 18:58:15 +02:00
|
|
|
str += ValueString(vch);
|
|
|
|
else
|
|
|
|
str += GetOpName(opcode);
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2012-05-14 23:44:52 +02:00
|
|
|
CScriptID GetID() const
|
|
|
|
{
|
|
|
|
return CScriptID(Hash160(*this));
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
};
|
|
|
|
|
2012-06-15 18:52:19 +02:00
|
|
|
/** Compact serializer for scripts.
|
|
|
|
*
|
|
|
|
* It detects common cases and encodes them much more efficiently.
|
|
|
|
* 3 special cases are defined:
|
|
|
|
* * Pay to pubkey hash (encoded as 21 bytes)
|
|
|
|
* * Pay to script hash (encoded as 21 bytes)
|
|
|
|
* * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
|
|
|
|
*
|
|
|
|
* Other scripts up to 121 bytes require 1 byte + script length. Above
|
|
|
|
* that, scripts up to 16505 bytes require 2 bytes + script length.
|
|
|
|
*/
|
|
|
|
class CScriptCompressor
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
// make this static for now (there are only 6 special scripts defined)
|
|
|
|
// this can potentially be extended together with a new nVersion for
|
|
|
|
// transactions, in which case this value becomes dependent on nVersion
|
|
|
|
// and nHeight of the enclosing transaction.
|
|
|
|
static const unsigned int nSpecialScripts = 6;
|
|
|
|
|
|
|
|
CScript &script;
|
|
|
|
protected:
|
|
|
|
// These check for scripts for which a special case with a shorter encoding is defined.
|
|
|
|
// They are implemented separately from the CScript test, as these test for exact byte
|
|
|
|
// sequence correspondences, and are more strict. For example, IsToPubKey also verifies
|
|
|
|
// whether the public key is valid (as invalid ones cannot be represented in compressed
|
|
|
|
// form).
|
|
|
|
bool IsToKeyID(CKeyID &hash) const;
|
|
|
|
bool IsToScriptID(CScriptID &hash) const;
|
2013-05-01 06:52:05 +02:00
|
|
|
bool IsToPubKey(CPubKey &pubkey) const;
|
2012-06-15 18:52:19 +02:00
|
|
|
|
|
|
|
bool Compress(std::vector<unsigned char> &out) const;
|
|
|
|
unsigned int GetSpecialSize(unsigned int nSize) const;
|
|
|
|
bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
|
|
|
|
public:
|
|
|
|
CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
|
|
|
|
|
|
|
|
unsigned int GetSerializeSize(int nType, int nVersion) const {
|
|
|
|
std::vector<unsigned char> compr;
|
|
|
|
if (Compress(compr))
|
|
|
|
return compr.size();
|
|
|
|
unsigned int nSize = script.size() + nSpecialScripts;
|
|
|
|
return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion);
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2012-06-15 18:52:19 +02:00
|
|
|
template<typename Stream>
|
|
|
|
void Serialize(Stream &s, int nType, int nVersion) const {
|
|
|
|
std::vector<unsigned char> compr;
|
|
|
|
if (Compress(compr)) {
|
2014-06-05 10:10:52 +02:00
|
|
|
s << CFlatData(compr);
|
2012-06-15 18:52:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
unsigned int nSize = script.size() + nSpecialScripts;
|
|
|
|
s << VARINT(nSize);
|
2014-06-05 10:10:52 +02:00
|
|
|
s << CFlatData(script);
|
2012-06-15 18:52:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Stream>
|
|
|
|
void Unserialize(Stream &s, int nType, int nVersion) {
|
2013-01-15 23:27:29 +01:00
|
|
|
unsigned int nSize = 0;
|
2012-06-15 18:52:19 +02:00
|
|
|
s >> VARINT(nSize);
|
|
|
|
if (nSize < nSpecialScripts) {
|
|
|
|
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
|
2014-06-05 10:10:52 +02:00
|
|
|
s >> REF(CFlatData(vch));
|
2012-06-15 18:52:19 +02:00
|
|
|
Decompress(nSize, vch);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nSize -= nSpecialScripts;
|
|
|
|
script.resize(nSize);
|
2014-06-05 10:10:52 +02:00
|
|
|
s >> REF(CFlatData(script));
|
2012-06-15 18:52:19 +02:00
|
|
|
}
|
|
|
|
};
|
2010-08-29 18:58:15 +02:00
|
|
|
|
Only create signatures with even S, and verification mode to check.
To fix a minor malleability found by Sergio Lerner (reported here:
https://bitcointalk.org/index.php?topic=8392.msg1245898#msg1245898)
The problem is that if (R,S) is a valid ECDSA signature for a given
message and public key, (R,-S) is also valid. Modulo N (the order
of the secp256k1 curve), this means that both (R,S) and (R,N-S) are
valid. Given that N is odd, S and N-S have a different lowest bit.
We solve the problem by forcing signatures to have an even S value,
excluding one of the alternatives.
This commit just changes the signing code to always produce even S
values, and adds a verification mode to check it. This code is not
enabled anywhere yet. Existing tests in key_tests.cpp verify that
the produced signatures are still valid.
2012-12-26 21:10:49 +01:00
|
|
|
bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int flags);
|
|
|
|
bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags);
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2012-11-13 23:03:25 +01:00
|
|
|
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
|
2011-11-08 19:20:29 +01:00
|
|
|
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
2012-01-19 19:30:54 +01:00
|
|
|
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
|
2013-06-24 21:09:50 +02:00
|
|
|
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
|
CWallet class
* A new class CKeyStore manages private keys, and script.cpp depends on access to CKeyStore.
* A new class CWallet extends CKeyStore, and contains all former wallet-specific globals; CWallet depends on script.cpp, not the other way around.
* Wallet-specific functions in CTransaction/CTxIn/CTxOut (GetDebit, GetCredit, GetChange, IsMine, IsFromMe), are moved to CWallet, taking their former 'this' argument as an explicit parameter
* CWalletTx objects know which CWallet they belong to, for convenience, so they have their own direct (and caching) GetDebit/... functions.
* Some code was moved from CWalletDB to CWallet, such as handling of reserve keys.
* Main.cpp keeps a set of all 'registered' wallets, which should be informed about updates to the block chain, and does not have any notion about any 'main' wallet. Function in main.cpp that require a wallet (such as GenerateCoins), take an explicit CWallet* argument.
* The actual CWallet instance used by the application is defined in init.cpp as "CWallet* pwalletMain". rpc.cpp and ui.cpp use this variable.
* Functions in main.cpp and db.cpp that are not used by other modules are marked static.
* The code for handling the 'submitorder' message is removed, as it not really compatible with the idea that a node is independent from the wallet(s) connected to it, and obsolete anyway.
2011-06-01 18:28:20 +02:00
|
|
|
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
2012-05-14 23:44:52 +02:00
|
|
|
bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
|
2013-04-29 19:50:02 +02:00
|
|
|
void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
|
2012-05-14 23:44:52 +02:00
|
|
|
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
|
|
|
|
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
2014-06-07 13:53:27 +02:00
|
|
|
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
|
|
|
|
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
|
2012-09-08 17:33:10 +02:00
|
|
|
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
|
2011-05-15 09:11:04 +02:00
|
|
|
|
2012-05-31 22:01:16 +02:00
|
|
|
// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
|
|
|
|
// combine them intelligently and return the result.
|
|
|
|
CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
|
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
#endif
|