aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorLuke Dashjr <luke-jr+git@utopios.org>2016-01-15 05:17:15 +0000
committerLuke Dashjr <luke-jr+git@utopios.org>2016-01-15 05:17:15 +0000
commit5bc4fb7b602c420be1c746442edad6b2d8e333ab (patch)
tree32ce1458f7fafdf4f9a1dcb09091f1a6de416625 /src/script
parente8600c924d58f3ef0450fc269998452e5b17aecb (diff)
parentc079d79c9a9c726fff367abc2d21c528e37275b9 (diff)
Merge branch 'master' into 20150703_banlist_updates
Diffstat (limited to 'src/script')
-rw-r--r--src/script/bitcoinconsensus.cpp11
-rw-r--r--src/script/bitcoinconsensus.h9
-rw-r--r--src/script/interpreter.cpp23
-rw-r--r--src/script/interpreter.h2
-rw-r--r--src/script/script.cpp12
-rw-r--r--src/script/script.h29
-rw-r--r--src/script/sigcache.cpp93
-rw-r--r--src/script/sigcache.h6
-rw-r--r--src/script/sign.cpp6
-rw-r--r--src/script/sign.h2
-rw-r--r--src/script/standard.cpp3
-rw-r--r--src/script/standard.h5
12 files changed, 121 insertions, 80 deletions
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index b0d5faaf77..47ad1d0807 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -1,11 +1,12 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "bitcoinconsensus.h"
#include "primitives/transaction.h"
+#include "pubkey.h"
#include "script/interpreter.h"
#include "version.h"
@@ -60,7 +61,13 @@ inline int set_error(bitcoinconsensus_error* ret, bitcoinconsensus_error serror)
return 0;
}
-} // anon namespace
+struct ECCryptoClosure
+{
+ ECCVerifyHandle handle;
+};
+
+ECCryptoClosure instance_of_eccryptoclosure;
+}
int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
const unsigned char *txTo , unsigned int txToLen,
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 0320577797..5b8c33c6bf 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -44,9 +44,10 @@ typedef enum bitcoinconsensus_error_t
/** Script verification flags */
enum
{
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0,
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0,
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
};
/// Returns 1 if the input nIn of the serialized transaction pointed to by
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index d3aec26020..a928223268 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,7 +9,6 @@
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
-#include "eccryptoverify.h"
#include "pubkey.h"
#include "script/script.h"
#include "uint256.h"
@@ -165,16 +164,8 @@ bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
if (!IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
}
- unsigned int nLenR = vchSig[3];
- unsigned int nLenS = vchSig[5+nLenR];
- const unsigned char *S = &vchSig[6+nLenR];
- // If the S value is above the order of the curve divided by two, its
- // complement modulo the order could have been used instead, which is
- // one byte shorter when encoded correctly.
- if (!eccrypto::CheckSignatureElement(S, nLenS, true))
- return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
-
- return true;
+ std::vector<unsigned char> vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1);
+ return CPubKey::CheckLowS(vchSigCopy);
}
bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
@@ -273,7 +264,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
- if (opcode > OP_16 && ++nOpCount > 201)
+ if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
if (opcode == OP_CAT ||
@@ -869,10 +860,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
- if (nKeysCount < 0 || nKeysCount > 20)
+ if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
nOpCount += nKeysCount;
- if (nOpCount > 201)
+ if (nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
i += nKeysCount;
@@ -1032,7 +1023,7 @@ public:
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
- ::Serialize(s, CScript(), nType, nVersion);
+ ::Serialize(s, CScriptBase(), nType, nVersion);
else
SerializeScriptCode(s, nType, nVersion);
// Serialize the nSequence
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 213e8c7651..7b34547ffb 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 9a0c067a33..9f2809e593 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -131,7 +131,7 @@ const char* GetOpName(opcodetype opcode)
// expanson
case OP_NOP1 : return "OP_NOP1";
- case OP_NOP2 : return "OP_NOP2";
+ case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY";
case OP_NOP3 : return "OP_NOP3";
case OP_NOP4 : return "OP_NOP4";
case OP_NOP5 : return "OP_NOP5";
@@ -170,7 +170,7 @@ unsigned int CScript::GetSigOpCount(bool fAccurate) const
if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
n += DecodeOP_N(lastOpcode);
else
- n += 20;
+ n += MAX_PUBKEYS_PER_MULTISIG;
}
lastOpcode = opcode;
}
@@ -205,9 +205,9 @@ bool CScript::IsPayToScriptHash() const
{
// Extra-fast test for pay-to-script-hash CScripts:
return (this->size() == 23 &&
- this->at(0) == OP_HASH160 &&
- this->at(1) == 0x14 &&
- this->at(22) == OP_EQUAL);
+ (*this)[0] == OP_HASH160 &&
+ (*this)[1] == 0x14 &&
+ (*this)[22] == OP_EQUAL);
}
bool CScript::IsPushOnly(const_iterator pc) const
diff --git a/src/script/script.h b/src/script/script.h
index cdc9a71bb2..6551eea30d 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,6 +7,7 @@
#define BITCOIN_SCRIPT_SCRIPT_H
#include "crypto/common.h"
+#include "prevector.h"
#include <assert.h>
#include <climits>
@@ -17,7 +18,14 @@
#include <string>
#include <vector>
-static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
+// Maximum number of bytes pushable to the stack
+static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
+
+// Maximum number of non-push operations per script
+static const int MAX_OPS_PER_SCRIPT = 201;
+
+// Maximum number of public keys per multisig
+static const int MAX_PUBKEYS_PER_MULTISIG = 20;
// Threshold for nLockTime: below this value it is interpreted as block number,
// otherwise as UNIX timestamp.
@@ -154,8 +162,8 @@ enum opcodetype
// expansion
OP_NOP1 = 0xb0,
- OP_NOP2 = 0xb1,
- OP_CHECKLOCKTIMEVERIFY = OP_NOP2,
+ OP_CHECKLOCKTIMEVERIFY = 0xb1,
+ OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
OP_NOP3 = 0xb2,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
@@ -347,8 +355,10 @@ private:
int64_t m_value;
};
+typedef prevector<28, unsigned char> CScriptBase;
+
/** Serialized script, used inside transaction inputs and outputs */
-class CScript : public std::vector<unsigned char>
+class CScript : public CScriptBase
{
protected:
CScript& push_int64(int64_t n)
@@ -369,9 +379,10 @@ protected:
}
public:
CScript() { }
- 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) { }
- CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { }
+ CScript(const CScript& b) : CScriptBase(b.begin(), b.end()) { }
+ CScript(const_iterator pbegin, const_iterator pend) : CScriptBase(pbegin, pend) { }
+ CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { }
+ CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { }
CScript& operator+=(const CScript& b)
{
@@ -604,7 +615,7 @@ public:
void clear()
{
// The default std::vector::clear() does not release memory.
- std::vector<unsigned char>().swap(*this);
+ CScriptBase().swap(*this);
}
};
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 099b4ad0e3..bdc0bfdc1c 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -1,21 +1,34 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "sigcache.h"
+#include "memusage.h"
#include "pubkey.h"
#include "random.h"
#include "uint256.h"
#include "util.h"
#include <boost/thread.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/unordered_set.hpp>
namespace {
/**
+ * We're hashing a nonce into the entries themselves, so we don't need extra
+ * blinding in the set hash computation.
+ */
+class CSignatureCacheHasher
+{
+public:
+ size_t operator()(const uint256& key) const {
+ return key.GetCheapHash();
+ }
+};
+
+/**
* Valid signature cache, to avoid doing expensive ECDSA signature checking
* twice for every transaction (once when accepted into memory pool, and
* again when accepted into the block chain)
@@ -23,52 +36,54 @@ namespace {
class CSignatureCache
{
private:
- //! sigdata_type is (signature hash, signature, public key):
- typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
- std::set< sigdata_type> setValid;
+ //! Entries are SHA256(nonce || signature hash || public key || signature):
+ uint256 nonce;
+ typedef boost::unordered_set<uint256, CSignatureCacheHasher> map_type;
+ map_type setValid;
boost::shared_mutex cs_sigcache;
+
public:
+ CSignatureCache()
+ {
+ GetRandBytes(nonce.begin(), 32);
+ }
+
+ void
+ ComputeEntry(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey)
+ {
+ CSHA256().Write(nonce.begin(), 32).Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(&vchSig[0], vchSig.size()).Finalize(entry.begin());
+ }
+
bool
- Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
+ Get(const uint256& entry)
{
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
+ return setValid.count(entry);
+ }
- sigdata_type k(hash, vchSig, pubKey);
- std::set<sigdata_type>::iterator mi = setValid.find(k);
- if (mi != setValid.end())
- return true;
- return false;
+ void Erase(const uint256& entry)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
+ setValid.erase(entry);
}
- void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
+ void Set(const uint256& entry)
{
- // DoS prevention: limit cache size to less than 10MB
- // (~200 bytes per cache entry times 50,000 entries)
- // Since there are a maximum of 20,000 signature operations per block
- // 50,000 is a reasonable default.
- int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
+ size_t nMaxCacheSize = GetArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
if (nMaxCacheSize <= 0) return;
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
-
- while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize)
+ while (memusage::DynamicUsage(setValid) > nMaxCacheSize)
{
- // Evict a random entry. Random because that helps
- // foil would-be DoS attackers who might try to pre-generate
- // and re-use a set of valid signatures just-slightly-greater
- // than our cache size.
- uint256 randomHash = GetRandHash();
- std::vector<unsigned char> unused;
- std::set<sigdata_type>::iterator it =
- setValid.lower_bound(sigdata_type(randomHash, unused, unused));
- if (it == setValid.end())
- it = setValid.begin();
- setValid.erase(*it);
+ map_type::size_type s = GetRand(setValid.bucket_count());
+ map_type::local_iterator it = setValid.begin(s);
+ if (it != setValid.end(s)) {
+ setValid.erase(*it);
+ }
}
- sigdata_type k(hash, vchSig, pubKey);
- setValid.insert(k);
+ setValid.insert(entry);
}
};
@@ -78,13 +93,21 @@ bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsig
{
static CSignatureCache signatureCache;
- if (signatureCache.Get(sighash, vchSig, pubkey))
+ uint256 entry;
+ signatureCache.ComputeEntry(entry, sighash, vchSig, pubkey);
+
+ if (signatureCache.Get(entry)) {
+ if (!store) {
+ signatureCache.Erase(entry);
+ }
return true;
+ }
if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash))
return false;
- if (store)
- signatureCache.Set(sighash, vchSig, pubkey);
+ if (store) {
+ signatureCache.Set(entry);
+ }
return true;
}
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index b299038daa..be1df09c2a 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,6 +10,10 @@
#include <vector>
+// DoS prevention: limit cache size to less than 40MB (over 500000
+// entries on 64-bit systems).
+static const unsigned int DEFAULT_MAX_SIG_CACHE_SIZE = 40;
+
class CPubKey;
class CachingTransactionSignatureChecker : public TransactionSignatureChecker
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 8b43183b6d..2f4111f786 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,7 +16,7 @@
using namespace std;
-typedef vector<unsigned char> valtype;
+typedef std::vector<unsigned char> valtype;
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), checker(txTo, nIn) {}
@@ -118,7 +118,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
bool fSolved =
SignStep(creator, subscript, scriptSig, subType) && subType != TX_SCRIPTHASH;
// Append serialized subscript whether or not it is completely signed:
- scriptSig << static_cast<valtype>(subscript);
+ scriptSig << valtype(subscript.begin(), subscript.end());
if (!fSolved) return false;
}
diff --git a/src/script/sign.h b/src/script/sign.h
index 13f45007dd..47a9cde7f4 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index bfef8afa17..30935768ac 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,6 +16,7 @@ using namespace std;
typedef vector<unsigned char> valtype;
+bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
diff --git a/src/script/standard.h b/src/script/standard.h
index ae1bbecca0..6bac6e4097 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,6 +13,8 @@
#include <stdint.h>
+static const bool DEFAULT_ACCEPT_DATACARRIER = true;
+
class CKeyID;
class CScript;
@@ -26,6 +28,7 @@ public:
};
static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
+extern bool fAcceptDatacarrier;
extern unsigned nMaxDatacarrierBytes;
/**