aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/addrman.cpp8
-rw-r--r--src/addrman.h3
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/chainparams.cpp20
-rw-r--r--src/chainparams.h3
-rw-r--r--src/consensus/params.h2
-rw-r--r--src/main.cpp21
-rw-r--r--src/net.cpp7
-rw-r--r--src/net.h6
-rw-r--r--src/netbase.cpp4
-rw-r--r--src/policy/fees.cpp2
-rw-r--r--src/policy/fees.h2
-rw-r--r--src/policy/policy.cpp54
-rw-r--r--src/policy/policy.h17
-rw-r--r--src/qt/forms/debugwindow.ui27
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/peertablemodel.cpp6
-rw-r--r--src/qt/receivecoinsdialog.cpp39
-rw-r--r--src/qt/receivecoinsdialog.h2
-rw-r--r--src/qt/rpcconsole.cpp1
-rw-r--r--src/random.cpp11
-rw-r--r--src/random.h35
-rw-r--r--src/rpc/mining.cpp2
-rw-r--r--src/rpc/misc.cpp2
-rw-r--r--src/rpc/net.cpp4
-rw-r--r--src/rpc/rawtransaction.cpp12
-rw-r--r--src/script/interpreter.cpp28
-rw-r--r--src/script/interpreter.h6
-rw-r--r--src/script/ismine.cpp62
-rw-r--r--src/script/ismine.h11
-rw-r--r--src/script/script_error.cpp2
-rw-r--r--src/script/script_error.h1
-rw-r--r--src/script/sign.cpp6
-rw-r--r--src/test/addrman_tests.cpp2
-rw-r--r--src/test/coins_tests.cpp2
-rw-r--r--src/test/crypto_tests.cpp2
-rw-r--r--src/test/data/script_tests.json368
-rw-r--r--src/test/merkle_tests.cpp2
-rw-r--r--src/test/net_tests.cpp2
-rw-r--r--src/test/pmt_tests.cpp2
-rw-r--r--src/test/prevector_tests.cpp14
-rw-r--r--src/test/scheduler_tests.cpp4
-rw-r--r--src/test/script_tests.cpp94
-rw-r--r--src/test/sighash_tests.cpp2
-rw-r--r--src/test/skiplist_tests.cpp2
-rw-r--r--src/test/test_bitcoin.cpp1
-rw-r--r--src/test/test_random.h23
-rw-r--r--src/test/transaction_tests.cpp36
-rw-r--r--src/test/util_tests.cpp2
-rw-r--r--src/test/versionbits_tests.cpp2
-rw-r--r--src/txmempool.cpp2
-rw-r--r--src/txmempool.h1
-rw-r--r--src/wallet/rpcwallet.cpp17
-rw-r--r--src/wallet/test/crypto_tests.cpp2
-rw-r--r--src/wallet/wallet.cpp4
55 files changed, 836 insertions, 160 deletions
diff --git a/src/addrman.cpp b/src/addrman.cpp
index bfb8e9457..201652321 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -358,8 +358,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
while (vvTried[nKBucket][nKBucketPos] == -1) {
- nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT;
- nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE;
+ nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT;
+ nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE;
}
int nId = vvTried[nKBucket][nKBucketPos];
assert(mapInfo.count(nId) == 1);
@@ -375,8 +375,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
while (vvNew[nUBucket][nUBucketPos] == -1) {
- nUBucket = (nUBucket + insecure_rand()) % ADDRMAN_NEW_BUCKET_COUNT;
- nUBucketPos = (nUBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE;
+ nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT;
+ nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE;
}
int nId = vvNew[nUBucket][nUBucketPos];
assert(mapInfo.count(nId) == 1);
diff --git a/src/addrman.h b/src/addrman.h
index 9bab39049..e9e137c97 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -211,6 +211,9 @@ protected:
//! secret key to randomize bucket select with
uint256 nKey;
+ //! Source of random numbers for randomization in inner loops
+ FastRandomContext insecure_rand;
+
//! Find an entry.
CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL);
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index cb863bda1..e09afd632 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -164,7 +164,7 @@ static void RegisterLoad(const string& strInput)
static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newVersion = atoi64(cmdVal);
- if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION)
+ if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
throw runtime_error("Invalid TX version requested");
tx.nVersion = (int) newVersion;
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index e6be1b5d5..5850016ae 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -91,10 +91,10 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
- // Deployment of SegWit (BIP141 and BIP143)
+ // Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
- consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 0;
- consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 0; // Never / undefined
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016.
+ consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -113,12 +113,13 @@ public:
assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille
- vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me")); // Matt Corallo
+ // Note that of those with the service bits flag, most only support a subset of possible options
+ vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be", true)); // Pieter Wuille, only supports x1, x5, x9, and xd
+ vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me", true)); // Matt Corallo, only supports x9
vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr
- vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker
+ vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com", true)); // Christian Decker, supports x1 - xf
vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik
- vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli
+ vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli, only supports x1, x5, x9, and xd
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
@@ -132,7 +133,6 @@ public:
fDefaultConsistencyChecks = false;
fRequireStandard = true;
fMineBlocksOnDemand = false;
- fTestnetToBeDeprecatedFieldRPC = false;
checkpointData = (CCheckpointData) {
boost::assign::map_list_of
@@ -186,7 +186,7 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
- // Deployment of SegWit (BIP141 and BIP143)
+ // Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1462060800; // May 1st 2016
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017
@@ -223,7 +223,6 @@ public:
fDefaultConsistencyChecks = false;
fRequireStandard = false;
fMineBlocksOnDemand = false;
- fTestnetToBeDeprecatedFieldRPC = true;
checkpointData = (CCheckpointData) {
boost::assign::map_list_of
@@ -285,7 +284,6 @@ public:
fDefaultConsistencyChecks = true;
fRequireStandard = false;
fMineBlocksOnDemand = true;
- fTestnetToBeDeprecatedFieldRPC = false;
checkpointData = (CCheckpointData){
boost::assign::map_list_of
diff --git a/src/chainparams.h b/src/chainparams.h
index 0c3820b7c..633fbd512 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -67,8 +67,6 @@ public:
uint64_t PruneAfterHeight() const { return nPruneAfterHeight; }
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
- /** In the future use NetworkIDString() for RPC fields */
- bool TestnetToBeDeprecatedFieldRPC() const { return fTestnetToBeDeprecatedFieldRPC; }
/** Return the BIP70 network string (main, test or regtest) */
std::string NetworkIDString() const { return strNetworkID; }
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
@@ -91,7 +89,6 @@ protected:
bool fDefaultConsistencyChecks;
bool fRequireStandard;
bool fMineBlocksOnDemand;
- bool fTestnetToBeDeprecatedFieldRPC;
CCheckpointData checkpointData;
};
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 5b2f49184..0e73cace8 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -16,7 +16,7 @@ enum DeploymentPos
{
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
- DEPLOYMENT_SEGWIT, // Deployment of BIP141 and BIP143
+ DEPLOYMENT_SEGWIT, // Deployment of BIP141, BIP143, and BIP147.
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
diff --git a/src/main.cpp b/src/main.cpp
index f3b0e3c22..d14a1bed3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1273,6 +1273,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (fRequireStandard && !AreInputsStandard(tx, view))
return state.Invalid(false, REJECT_NONSTANDARD, "bad-txns-nonstandard-inputs");
+ // Check for non-standard witness in P2WSH
+ if (!tx.wit.IsNull() && fRequireStandard && !IsWitnessStandard(tx, view))
+ return state.DoS(0, false, REJECT_NONSTANDARD, "bad-witness-nonstandard", true);
+
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
CAmount nValueOut = tx.GetValueOut();
@@ -4758,6 +4762,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
uint64_t hashAddr = addr.GetHash();
std::multimap<uint64_t, CNode*> mapMix;
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
+ FastRandomContext insecure_rand;
auto sortfunc = [&mapMix, &hasher](CNode* pnode) {
if (pnode->nVersion >= CADDR_TIME_VERSION) {
@@ -4766,9 +4771,9 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
}
};
- auto pushfunc = [&addr, &mapMix, &nRelayNodes] {
+ auto pushfunc = [&addr, &mapMix, &nRelayNodes, &insecure_rand] {
for (auto mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
- mi->second->PushAddress(addr);
+ mi->second->PushAddress(addr, insecure_rand);
};
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
@@ -5078,14 +5083,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (fListen && !IsInitialBlockDownload())
{
CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices());
+ FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString());
- pfrom->PushAddress(addr);
+ pfrom->PushAddress(addr, insecure_rand);
} else if (IsPeerAddrLocalGood(pfrom)) {
addr.SetIP(pfrom->addrLocal);
LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString());
- pfrom->PushAddress(addr);
+ pfrom->PushAddress(addr, insecure_rand);
}
}
@@ -6008,8 +6014,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = connman.GetAddresses();
+ FastRandomContext insecure_rand;
BOOST_FOREACH(const CAddress &addr, vAddr)
- pfrom->PushAddress(addr);
+ pfrom->PushAddress(addr, insecure_rand);
}
@@ -6842,7 +6849,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
// until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY.
else if (timeNow + MAX_FEEFILTER_CHANGE_DELAY * 1000000 < pto->nextSendTimeFeeFilter &&
(currentFilter < 3 * pto->lastSentFeeFilter / 4 || currentFilter > 4 * pto->lastSentFeeFilter / 3)) {
- pto->nextSendTimeFeeFilter = timeNow + (insecure_rand() % MAX_FEEFILTER_CHANGE_DELAY) * 1000000;
+ pto->nextSendTimeFeeFilter = timeNow + GetRandInt(MAX_FEEFILTER_CHANGE_DELAY) * 1000000;
}
}
}
diff --git a/src/net.cpp b/src/net.cpp
index 19dd04099..34dc67eb4 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -187,7 +187,8 @@ void AdvertiseLocal(CNode *pnode)
if (addrLocal.IsRoutable())
{
LogPrint("net", "AdvertiseLocal: advertising address %s\n", addrLocal.ToString());
- pnode->PushAddress(addrLocal);
+ FastRandomContext insecure_rand;
+ pnode->PushAddress(addrLocal, insecure_rand);
}
}
}
@@ -659,7 +660,7 @@ void CNode::copyStats(CNodeStats &stats)
// Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
stats.dPingTime = (((double)nPingUsecTime) / 1e6);
- stats.dPingMin = (((double)nMinPingUsecTime) / 1e6);
+ stats.dMinPing = (((double)nMinPingUsecTime) / 1e6);
stats.dPingWait = (((double)nPingUsecWait) / 1e6);
// Leave string empty if addrLocal invalid (not filled in yet)
@@ -1454,6 +1455,7 @@ static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredSe
return data.host;
}
+ // See chainparams.cpp, most dnsseeds only support one or two possible servicebits hostnames
return strprintf("x%x.%s", *requiredServiceBits, data.host);
}
@@ -1621,7 +1623,6 @@ void CConnman::ThreadOpenConnections()
}
}
}
- assert(nOutbound <= (nMaxOutbound + nMaxFeeler));
// Feeler Connections
//
diff --git a/src/net.h b/src/net.h
index 67f0abe4b..58b492e59 100644
--- a/src/net.h
+++ b/src/net.h
@@ -503,7 +503,7 @@ public:
bool fWhitelisted;
double dPingTime;
double dPingWait;
- double dPingMin;
+ double dMinPing;
std::string addrLocal;
CAddress addr;
};
@@ -735,14 +735,14 @@ public:
addrKnown.insert(_addr.GetKey());
}
- void PushAddress(const CAddress& _addr)
+ void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
{
// Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added
// after addresses were pushed.
if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) {
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
- vAddrToSend[insecure_rand() % vAddrToSend.size()] = _addr;
+ vAddrToSend[insecure_rand.rand32() % vAddrToSend.size()] = _addr;
} else {
vAddrToSend.push_back(_addr);
}
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 7d7f1b678..9fe34108f 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -596,8 +596,8 @@ static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDe
// do socks negotiation
if (proxy.randomize_credentials) {
ProxyCredentials random_auth;
- random_auth.username = strprintf("%i", insecure_rand());
- random_auth.password = strprintf("%i", insecure_rand());
+ static std::atomic_int counter;
+ random_auth.username = random_auth.password = strprintf("%i", counter++);
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
return false;
} else {
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 7b0e8b7d0..c07cd2eff 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -594,7 +594,7 @@ FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
CAmount FeeFilterRounder::round(CAmount currentMinFee)
{
std::set<double>::iterator it = feeset.lower_bound(currentMinFee);
- if ((it != feeset.begin() && insecure_rand() % 3 != 0) || it == feeset.end()) {
+ if ((it != feeset.begin() && insecure_rand.rand32() % 3 != 0) || it == feeset.end()) {
it--;
}
return *it;
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 463f62f71..2c1ac3b93 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -7,6 +7,7 @@
#include "amount.h"
#include "uint256.h"
+#include "random.h"
#include <map>
#include <string>
@@ -298,5 +299,6 @@ public:
private:
std::set<double> feeset;
+ FastRandomContext insecure_rand;
};
#endif /*BITCOIN_POLICYESTIMATOR_H */
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 48080abc7..ae42b2bd7 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin developers
+// Copyright (c) 2009-2016 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -154,6 +154,58 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true;
}
+bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
+{
+ if (tx.IsCoinBase())
+ return true; // Coinbases are skipped
+
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ // We don't care if witness for this input is empty, since it must not be bloated.
+ // If the script is invalid without witness, it would be caught sooner or later during validation.
+ if (tx.wit.vtxinwit[i].IsNull())
+ continue;
+
+ const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]);
+
+ // get the scriptPubKey corresponding to this input:
+ CScript prevScript = prev.scriptPubKey;
+
+ if (prevScript.IsPayToScriptHash()) {
+ std::vector <std::vector<unsigned char> > stack;
+ // If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig
+ // into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
+ // If the check fails at this stage, we know that this txid must be a bad one.
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
+ return false;
+ if (stack.empty())
+ return false;
+ prevScript = CScript(stack.back().begin(), stack.back().end());
+ }
+
+ int witnessversion = 0;
+ std::vector<unsigned char> witnessprogram;
+
+ // Non-witness program must not be associated with any witness
+ if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram))
+ return false;
+
+ // Check P2WSH standard limits
+ if (witnessversion == 0 && witnessprogram.size() == 32) {
+ if (tx.wit.vtxinwit[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
+ return false;
+ size_t sizeWitnessStack = tx.wit.vtxinwit[i].scriptWitness.stack.size() - 1;
+ if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
+ return false;
+ for (unsigned int j = 0; j < sizeWitnessStack; j++) {
+ if (tx.wit.vtxinwit[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 9d6ff1233..814e6c0b6 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin developers
+// Copyright (c) 2009-2016 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -30,6 +30,12 @@ static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5;
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
/** Default for -bytespersigop */
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
+/** The maximum number of witness stack items in a standard P2WSH script */
+static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100;
+/** The maximum size of each witness stack item in a standard P2WSH script */
+static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80;
+/** The maximum size of a standard witnessScript */
+static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
/**
* Standard script verification flags that standard transactions will comply
* with. However scripts violating these flags may still be present in valid
@@ -48,7 +54,8 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
SCRIPT_VERIFY_LOW_S |
SCRIPT_VERIFY_WITNESS |
- SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
+ SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
/** 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;
@@ -69,6 +76,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
* @return True if all inputs (scriptSigs) use only standard transaction forms
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
+ /**
+ * Check if the transaction is over standard P2WSH resources limit:
+ * 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
+ * These limits are adequate for multi-signature up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL,
+ */
+bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
extern unsigned int nBytesPerSigOp;
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index 9dc641979..8be4a955b 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -1353,13 +1353,36 @@
</widget>
</item>
<item row="16" column="0">
+ <widget class="QLabel" name="peerMinPingLabel">
+ <property name="text">
+ <string>Min Ping</string>
+ </property>
+ </widget>
+ </item>
+ <item row="16" column="2">
+ <widget class="QLabel" name="peerMinPing">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="17" column="0">
<widget class="QLabel" name="label_timeoffset">
<property name="text">
<string>Time Offset</string>
</property>
</widget>
</item>
- <item row="16" column="2">
+ <item row="17" column="2">
<widget class="QLabel" name="timeoffset">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -1375,7 +1398,7 @@
</property>
</widget>
</item>
- <item row="17" column="1">
+ <item row="18" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 0beaddf99..42dafa117 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -947,7 +947,7 @@ QString formatServicesStr(quint64 mask)
QString formatPingTime(double dPingTime)
{
- return dPingTime == 0 ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10));
+ return (dPingTime == std::numeric_limits<int64_t>::max()/1e6 || dPingTime == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(dPingTime * 1000), 10));
}
QString formatTimeOffset(int64_t nTimeOffset)
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index a820bd791..a2f9471fc 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -31,7 +31,7 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine
case PeerTableModel::Subversion:
return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
case PeerTableModel::Ping:
- return pLeft->dPingTime < pRight->dPingTime;
+ return pLeft->dMinPing < pRight->dMinPing;
}
return false;
@@ -113,7 +113,7 @@ PeerTableModel::PeerTableModel(ClientModel *parent) :
clientModel(parent),
timer(0)
{
- columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping Time");
+ columns << tr("NodeId") << tr("Node/Service") << tr("User Agent") << tr("Ping");
priv = new PeerTablePriv();
// default to unsorted
priv->sortColumn = -1;
@@ -166,7 +166,7 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
case Subversion:
return QString::fromStdString(rec->nodeStats.cleanSubVer);
case Ping:
- return GUIUtil::formatPingTime(rec->nodeStats.dPingTime);
+ return GUIUtil::formatPingTime(rec->nodeStats.dMinPing);
}
} else if (role == Qt::TextAlignmentRole) {
if (index.column() == Ping)
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 5c6dc97b2..b50cad497 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -43,18 +43,21 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWid
}
// context menu actions
+ QAction *copyURIAction = new QAction(tr("Copy URI"), this);
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
QAction *copyMessageAction = new QAction(tr("Copy message"), this);
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
// context menu
contextMenu = new QMenu();
+ contextMenu->addAction(copyURIAction);
contextMenu->addAction(copyLabelAction);
contextMenu->addAction(copyMessageAction);
contextMenu->addAction(copyAmountAction);
// context menu signals
connect(ui->recentRequestsView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint)));
+ connect(copyURIAction, SIGNAL(triggered()), this, SLOT(copyURI()));
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
@@ -228,30 +231,50 @@ void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event)
this->QDialog::keyPressEvent(event);
}
-// copy column of selected row to clipboard
-void ReceiveCoinsDialog::copyColumnToClipboard(int column)
+QModelIndex ReceiveCoinsDialog::selectedRow()
{
if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
- return;
+ return QModelIndex();
QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
if(selection.empty())
- return;
+ return QModelIndex();
// correct for selection mode ContiguousSelection
QModelIndex firstIndex = selection.at(0);
+ return firstIndex;
+}
+
+// copy column of selected row to clipboard
+void ReceiveCoinsDialog::copyColumnToClipboard(int column)
+{
+ QModelIndex firstIndex = selectedRow();
+ if (!firstIndex.isValid()) {
+ return;
+ }
GUIUtil::setClipboard(model->getRecentRequestsTableModel()->data(firstIndex.child(firstIndex.row(), column), Qt::EditRole).toString());
}
// context menu
void ReceiveCoinsDialog::showMenu(const QPoint &point)
{
- if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
- return;
- QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
- if(selection.empty())
+ if (!selectedRow().isValid()) {
return;
+ }
contextMenu->exec(QCursor::pos());
}
+// context menu action: copy URI
+void ReceiveCoinsDialog::copyURI()
+{
+ QModelIndex sel = selectedRow();
+ if (!sel.isValid()) {
+ return;
+ }
+
+ const RecentRequestsTableModel * const submodel = model->getRecentRequestsTableModel();
+ const QString uri = GUIUtil::formatBitcoinURI(submodel->entry(sel.row()).recipient);
+ GUIUtil::setClipboard(uri);
+}
+
// context menu action: copy label
void ReceiveCoinsDialog::copyLabel()
{
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index 226fd65cf..d137f1616 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -60,6 +60,7 @@ private:
QMenu *contextMenu;
const PlatformStyle *platformStyle;
+ QModelIndex selectedRow();
void copyColumnToClipboard(int column);
virtual void resizeEvent(QResizeEvent *event);
@@ -71,6 +72,7 @@ private Q_SLOTS:
void recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void updateDisplayUnit();
void showMenu(const QPoint &point);
+ void copyURI();
void copyLabel();
void copyMessage();
void copyAmount();
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index b6ed75535..a1017e6c1 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -895,6 +895,7 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nTimeConnected));
ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime));
ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingWait));
+ ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.dMinPing));
ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion)));
ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
diff --git a/src/random.cpp b/src/random.cpp
index d9a8cc145..aa027e49c 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -178,22 +178,21 @@ uint256 GetRandHash()
return hash;
}
-uint32_t insecure_rand_Rz = 11;
-uint32_t insecure_rand_Rw = 11;
-void seed_insecure_rand(bool fDeterministic)
+FastRandomContext::FastRandomContext(bool fDeterministic)
{
// The seed values have some unlikely fixed points which we avoid.
if (fDeterministic) {
- insecure_rand_Rz = insecure_rand_Rw = 11;
+ Rz = Rw = 11;
} else {
uint32_t tmp;
do {
GetRandBytes((unsigned char*)&tmp, 4);
} while (tmp == 0 || tmp == 0x9068ffffU);
- insecure_rand_Rz = tmp;
+ Rz = tmp;
do {
GetRandBytes((unsigned char*)&tmp, 4);
} while (tmp == 0 || tmp == 0x464fffffU);
- insecure_rand_Rw = tmp;
+ Rw = tmp;
}
}
+
diff --git a/src/random.h b/src/random.h
index 31b80bd56..e97d2d1fb 100644
--- a/src/random.h
+++ b/src/random.h
@@ -28,25 +28,22 @@ uint256 GetRandHash();
void GetStrongRandBytes(unsigned char* buf, int num);
/**
- * Seed insecure_rand using the random pool.
- * @param Deterministic Use a deterministic seed
+ * Fast randomness source. This is seeded once with secure random data, but
+ * is completely deterministic and insecure after that.
+ * This class is not thread-safe.
*/
-void seed_insecure_rand(bool fDeterministic = false);
-
-/**
- * MWC RNG of George Marsaglia
- * This is intended to be fast. It has a period of 2^59.3, though the
- * least significant 16 bits only have a period of about 2^30.1.
- *
- * @return random value
- */
-extern uint32_t insecure_rand_Rz;
-extern uint32_t insecure_rand_Rw;
-static inline uint32_t insecure_rand(void)
-{
- insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
- insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
- return (insecure_rand_Rw << 16) + insecure_rand_Rz;
-}
+class FastRandomContext {
+public:
+ explicit FastRandomContext(bool fDeterministic=false);
+
+ uint32_t rand32() {
+ Rz = 36969 * (Rz & 65535) + (Rz >> 16);
+ Rw = 18000 * (Rw & 65535) + (Rw >> 16);
+ return (Rw << 16) + Rz;
+ }
+
+ uint32_t Rz;
+ uint32_t Rw;
+};
#endif // BITCOIN_RANDOM_H
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 6b13aa5ba..fa64ce8fa 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -230,7 +230,6 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
" \"errors\": \"...\" (string) Current errors\n"
" \"networkhashps\": nnn, (numeric) The network hashes per second\n"
" \"pooledtx\": n (numeric) The size of the mem pool\n"
- " \"testnet\": true|false (boolean) If using testnet or not\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
"}\n"
"\nExamples:\n"
@@ -250,7 +249,6 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("errors", GetWarnings("statusbar")));
obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
- obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
obj.push_back(Pair("chain", Params().NetworkIDString()));
return obj;
}
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index f0b7e0a07..6bbb3925d 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -93,7 +93,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
+ obj.push_back(Pair("testnet", Params().NetworkIDString() == CBaseChainParams::TESTNET));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index b011029f5..a8442d869 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -141,8 +141,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("timeoffset", stats.nTimeOffset));
if (stats.dPingTime > 0.0)
obj.push_back(Pair("pingtime", stats.dPingTime));
- if (stats.dPingMin < std::numeric_limits<int64_t>::max()/1e6)
- obj.push_back(Pair("minping", stats.dPingMin));
+ if (stats.dMinPing < std::numeric_limits<int64_t>::max()/1e6)
+ obj.push_back(Pair("minping", stats.dMinPing));
if (stats.dPingWait > 0.0)
obj.push_back(Pair("pingwait", stats.dPingWait));
obj.push_back(Pair("version", stats.nVersion));
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index d2ad0a52b..e48fe2565 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -535,7 +535,7 @@ UniValue decodescript(const UniValue& params, bool fHelp)
" \"address\" (string) bitcoin address\n"
" ,...\n"
" ],\n"
- " \"p2sh\",\"address\" (string) script address\n"
+ " \"p2sh\",\"address\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("decodescript", "\"hexstring\"")
@@ -554,7 +554,15 @@ UniValue decodescript(const UniValue& params, bool fHelp)
}
ScriptPubKeyToJSON(script, r, false);
- r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
+ UniValue type;
+ type = find_value(r, "type");
+
+ if (type.isStr() && type.get_str() != "scripthash") {
+ // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
+ // don't return the address for a P2SH of the P2SH.
+ r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
+ }
+
return r;
}
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 41756ea71..836cf9ee3 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -79,8 +79,20 @@ bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
return false;
}
} else {
- // Non-canonical public key: neither compressed nor uncompressed
- return false;
+ // Non-canonical public key: neither compressed nor uncompressed
+ return false;
+ }
+ return true;
+}
+
+bool static IsCompressedPubKey(const valtype &vchPubKey) {
+ if (vchPubKey.size() != 33) {
+ // Non-canonical public key: invalid length for compressed key
+ return false;
+ }
+ if (vchPubKey[0] != 0x02 && vchPubKey[0] != 0x03) {
+ // Non-canonical public key: invalid prefix for compressed key
+ return false;
}
return true;
}
@@ -199,10 +211,14 @@ bool CheckSignatureEncoding(const vector<unsigned char> &vchSig, unsigned int fl
return true;
}
-bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
- if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) {
+bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) {
+ if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) {
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
}
+ // Only compressed keys are accepted in segwit
+ if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) {
+ return set_error(serror, SCRIPT_ERR_WITNESS_PUBKEYTYPE);
+ }
return true;
}
@@ -879,7 +895,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
scriptCode.FindAndDelete(CScript(vchSig));
}
- if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
+ if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
//serror is set
return false;
}
@@ -953,7 +969,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// Note how this makes the exact order of pubkey/signature evaluation
// distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set.
// See the script_(in)valid tests for details.
- if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
+ if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
// serror is set
return false;
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 0adc9482f..79894c530 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -102,6 +102,10 @@ enum
// Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
//
SCRIPT_VERIFY_NULLFAIL = (1U << 14),
+
+ // Public keys in segregated witness scripts must be compressed
+ //
+ SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1U << 15),
};
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 0bf180341..7467d23b2 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -29,13 +29,25 @@ unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
return nResult;
}
-isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
+{
+ bool isInvalid = false;
+ return IsMine(keystore, scriptPubKey, isInvalid, sigversion);
+}
+
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion)
+{
+ bool isInvalid = false;
+ return IsMine(keystore, dest, isInvalid, sigversion);
+}
+
+isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion)
{
CScript script = GetScriptForDestination(dest);
- return IsMine(keystore, script);
+ return IsMine(keystore, script, isInvalid, sigversion);
}
-isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
+isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
{
vector<valtype> vSolutions;
txnouttype whichType;
@@ -53,12 +65,35 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
break;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
+ if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) {
+ isInvalid = true;
+ return ISMINE_NO;
+ }
if (keystore.HaveKey(keyID))
return ISMINE_SPENDABLE;
break;
- case TX_PUBKEYHASH:
case TX_WITNESS_V0_KEYHASH:
+ {
+ if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
+ // We do not support bare witness outputs unless the P2SH version of it would be
+ // acceptable as well. This protects against matching before segwit activates.
+ // This also applies to the P2WSH case.
+ break;
+ }
+ isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0);
+ if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
+ return ret;
+ break;
+ }
+ case TX_PUBKEYHASH:
keyID = CKeyID(uint160(vSolutions[0]));
+ if (sigversion != SIGVERSION_BASE) {
+ CPubKey pubkey;
+ if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
+ isInvalid = true;
+ return ISMINE_NO;
+ }
+ }
if (keystore.HaveKey(keyID))
return ISMINE_SPENDABLE;
break;
@@ -67,21 +102,24 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript);
- if (ret == ISMINE_SPENDABLE)
+ isminetype ret = IsMine(keystore, subscript, isInvalid);
+ if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
}
break;
}
case TX_WITNESS_V0_SCRIPTHASH:
{
+ if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
+ break;
+ }
uint160 hash;
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
CScriptID scriptID = CScriptID(hash);
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript);
- if (ret == ISMINE_SPENDABLE)
+ isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0);
+ if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
return ret;
}
break;
@@ -95,6 +133,14 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
// them) enable spend-out-from-under-you attacks, especially
// in shared-wallet situations.
vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
+ if (sigversion != SIGVERSION_BASE) {
+ for (size_t i = 0; i < keys.size(); i++) {
+ if (keys[i].size() != 33) {
+ isInvalid = true;
+ return ISMINE_NO;
+ }
+ }
+ }
if (HaveKeys(keys, keystore) == keys.size())
return ISMINE_SPENDABLE;
break;
diff --git a/src/script/ismine.h b/src/script/ismine.h
index 4b7db8802..ec7a620e3 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -28,7 +28,14 @@ enum isminetype
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
+/* isInvalid becomes true when the script is found invalid by consensus or policy. This will terminate the recursion
+ * and return a ISMINE_NO immediately, as an invalid script should never be considered as "mine". This is needed as
+ * different SIGVERSION may have different network rules. Currently the only use of isInvalid is indicate uncompressed
+ * keys in SIGVERSION_WITNESS_V0 script, but could also be used in similar cases in the future
+ */
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion = SIGVERSION_BASE);
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion = SIGVERSION_BASE);
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, bool& isInvalid, SigVersion = SIGVERSION_BASE);
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion = SIGVERSION_BASE);
#endif // BITCOIN_SCRIPT_ISMINE_H
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
index e27b715c2..2c5359fe8 100644
--- a/src/script/script_error.cpp
+++ b/src/script/script_error.cpp
@@ -85,6 +85,8 @@ const char* ScriptErrorString(const ScriptError serror)
return "Witness requires only-redeemscript scriptSig";
case SCRIPT_ERR_WITNESS_UNEXPECTED:
return "Witness provided for non-witness script";
+ case SCRIPT_ERR_WITNESS_PUBKEYTYPE:
+ return "Using non-compressed keys in segwit";
case SCRIPT_ERR_UNKNOWN_ERROR:
case SCRIPT_ERR_ERROR_COUNT:
default: break;
diff --git a/src/script/script_error.h b/src/script/script_error.h
index bccfdb99e..430836991 100644
--- a/src/script/script_error.h
+++ b/src/script/script_error.h
@@ -62,6 +62,7 @@ typedef enum ScriptError_t
SCRIPT_ERR_WITNESS_MALLEATED,
SCRIPT_ERR_WITNESS_MALLEATED_P2SH,
SCRIPT_ERR_WITNESS_UNEXPECTED,
+ SCRIPT_ERR_WITNESS_PUBKEYTYPE,
SCRIPT_ERR_ERROR_COUNT
} ScriptError;
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 87f38d9c7..f552ad5bb 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -26,6 +26,10 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
if (!keystore->GetKey(address, key))
return false;
+ // Signing with uncompressed keys is disabled in witness scripts
+ if (sigversion == SIGVERSION_WITNESS_V0 && !key.IsCompressed())
+ return false;
+
uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
if (!key.Sign(hash, vchSig))
return false;
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 5ccaeb57b..adff09f75 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -26,7 +26,7 @@ public:
void MakeDeterministic()
{
nKey.SetNull();
- seed_insecure_rand(true);
+ insecure_rand = FastRandomContext(true);
}
int RandomInt(int nMax)
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index e69232655..b48768613 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "coins.h"
-#include "random.h"
+#include "test_random.h"
#include "script/standard.h"
#include "uint256.h"
#include "utilstrencodings.h"
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index ff0adae1d..c7b4fb240 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -9,7 +9,7 @@
#include "crypto/sha512.h"
#include "crypto/hmac_sha256.h"
#include "crypto/hmac_sha512.h"
-#include "random.h"
+#include "test_random.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
index 06103ea5b..5c054ed3e 100644
--- a/src/test/data/script_tests.json
+++ b/src/test/data/script_tests.json
@@ -1855,6 +1855,8 @@
"OK",
"P2SH with CLEANSTACK"
],
+
+["Testing with uncompressed keys in witness v0 without WITNESS_PUBKEYTYPE"],
[
[
"304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101",
@@ -2139,7 +2141,371 @@
"P2PK with witness"
],
-["CHECKSEQUENCEVERIFY tests"],
+["Testing with compressed keys in witness v0 with WITNESS_PUBKEYTYPE"],
+[
+ [
+ "304402204256146fcf8e73b0fd817ffa2a4e408ff0418ff987dd08a4f485b62546f6c43c02203f3c8c3e2febc051e1222867f5f9d0eaf039d6792911c10940aa3cc74123378e01",
+ "210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2WSH with compressed key"
+],
+[
+ [
+ "304402204edf27486f11432466b744df533e1acac727e0c83e5f912eb289a3df5bf8035f022075809fdd876ede40ad21667eba8b7e96394938f9c9c50f11b6a1280cce2cea8601",
+ "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
+ 0.00000001
+ ],
+ "",
+ "0 0x14 0x751e76e8199196d454941c45d1b3a323f1433bd6",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2WPKH with compressed key"
+],
+[
+ [
+ "304402203a549090cc46bce1e5e95c4922ea2c12747988e0207b04c42f81cdbe87bb1539022050f57a245b875fd5119c419aaf050bcdf41384f0765f04b809e5bced1fe7093d01",
+ "210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ 0.00000001
+ ],
+ "0x22 0x00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ "HASH160 0x14 0xe4300531190587e3880d4c3004f5355d88ff928d EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2SH(P2WSH) with compressed key"
+],
+[
+ [
+ "304402201bc0d53046827f4a35a3166e33e3b3366c4085540dc383b95d21ed2ab11e368a0220333e78c6231214f5f8e59621e15d7eeab0d4e4d0796437e00bfbd2680c5f9c1701",
+ "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
+ 0.00000001
+ ],
+ "0x16 0x0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ "HASH160 0x14 0xbcfeb728b584253d5f3f70bcb780e9ef218a68f4 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2SH(P2WPKH) with compressed key"
+],
+
+["Testing with uncompressed keys in witness v0 with WITNESS_PUBKEYTYPE"],
+[
+ [
+ "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2WSH"
+],
+[
+ [
+ "304402201e7216e5ccb3b61d46946ec6cc7e8c4e0117d13ac2fd4b152197e4805191c74202203e9903e33e84d9ee1dd13fb057afb7ccfb47006c23f6a067185efbc9dd780fc501",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2WPKH"
+],
+[
+ [
+ "3044022066e02c19a513049d49349cf5311a1b012b7c4fae023795a18ab1d91c23496c22022025e216342c8e07ce8ef51e8daee88f84306a9de66236cab230bb63067ded1ad301",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2SH(P2WSH)"
+],
+[
+ [
+ "304402200929d11561cd958460371200f82e9cae64c727a495715a31828e27a7ad57b36d0220361732ced04a6f97351ecca21a56d0b8cd4932c1da1f8f569a2b68e5e48aed7801",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5",
+ "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2SH(P2WPKH)"
+],
+
+["Testing P2WSH multisig with compressed keys"],
+[
+ [
+ "",
+ "304402207eb8a59b5c65fc3f6aeef77066556ed5c541948a53a3ba7f7c375b8eed76ee7502201e036a7a9a98ff919ff94dc905d67a1ec006f79ef7cff0708485c8bb79dce38e01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x06c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2WSH CHECKMULTISIG with compressed keys"
+],
+[
+ [
+ "",
+ "3044022033706aed33b8155d5486df3b9bca8cdd3bd4bdb5436dce46d72cdaba51d22b4002203626e94fe53a178af46624f17315c6931f20a30b103f5e044e1eda0c3fe185c601",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x002006c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "HASH160 0x14 0x26282aad7c29369d15fed062a778b6100d31a340 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys"
+],
+[
+ [
+ "",
+ "304402204048b7371ab1c544362efb89af0c80154747d665aa4fcfb2edfd2d161e57b42e02207e043748e96637080ffc3acbd4dcc6fee1e58d30f6d1269535f32188e5ddae7301",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x06c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2WSH CHECKMULTISIG with compressed keys"
+],
+[
+ [
+ "",
+ "3044022073902ef0b8a554c36c44cc03c1b64df96ce2914ebcf946f5bb36078fd5245cdf02205b148f1ba127065fb8c83a5a9576f2dcd111739788ed4bb3ee08b2bd3860c91c01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x002006c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "HASH160 0x14 0x26282aad7c29369d15fed062a778b6100d31a340 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys"
+],
+
+["Testing P2WSH multisig with compressed and uncompressed keys (first key being the key closer to the top of stack)"],
+[
+ [
+ "",
+ "304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "3044022046f5367a261fd8f8d7de6eb390491344f8ec2501638fb9a1095a0599a21d3f4c02205c1b3b51d20091c5f1020841bbca87b44ebe25405c64e4acf758f2eae8665f8401",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "3044022053e210e4fb1881e6092fd75c3efc5163105599e246ded661c0ee2b5682cc2d6c02203a26b7ada8682a095b84c6d1b881637000b47d761fc837c4cee33555296d63f101",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "3044022046f5367a261fd8f8d7de6eb390491344f8ec2501638fb9a1095a0599a21d3f4c02205c1b3b51d20091c5f1020841bbca87b44ebe25405c64e4acf758f2eae8665f8401",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used"
+],
+[
+ [
+ "",
+ "3044022053e210e4fb1881e6092fd75c3efc5163105599e246ded661c0ee2b5682cc2d6c02203a26b7ada8682a095b84c6d1b881637000b47d761fc837c4cee33555296d63f101",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used"
+],
+[
+ [
+ "",
+ "304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+
+["CHECKSEQUENCEVERIFY tests"],
["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index b40ab848d..66ca381ea 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -4,7 +4,7 @@
#include "consensus/merkle.h"
#include "test/test_bitcoin.h"
-#include "random.h"
+#include "test_random.h"
#include <boost/test/unit_test.hpp>
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 4a7d6e778..f4b576869 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -23,7 +23,7 @@ public:
void MakeDeterministic()
{
nKey.SetNull();
- seed_insecure_rand(true);
+ insecure_rand = FastRandomContext(true);
}
};
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index e9c869174..b7f83d38f 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -9,7 +9,7 @@
#include "uint256.h"
#include "arith_uint256.h"
#include "version.h"
-#include "random.h"
+#include "test_random.h"
#include "test/test_bitcoin.h"
#include <vector>
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
index b8c45ca56..6cad02e73 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -4,7 +4,7 @@
#include <vector>
#include "prevector.h"
-#include "random.h"
+#include "test_random.h"
#include "serialize.h"
#include "streams.h"
@@ -27,8 +27,7 @@ class prevector_tester {
typedef typename pretype::size_type Size;
bool passed = true;
- uint32_t insecure_rand_Rz_cache;
- uint32_t insecure_rand_Rw_cache;
+ FastRandomContext rand_cache;
template <typename A, typename B>
@@ -171,15 +170,14 @@ public:
test();
}
~prevector_tester() {
- BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: "
- << insecure_rand_Rz_cache
+ BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: "
+ << rand_cache.Rz
<< ", insecure_rand_Rw: "
- << insecure_rand_Rw_cache);
+ << rand_cache.Rw);
}
prevector_tester() {
seed_insecure_rand();
- insecure_rand_Rz_cache = insecure_rand_Rz;
- insecure_rand_Rw_cache = insecure_rand_Rw;
+ rand_cache = insecure_rand_ctx;
}
};
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
index aa12dfbd5..891ecf501 100644
--- a/src/test/scheduler_tests.cpp
+++ b/src/test/scheduler_tests.cpp
@@ -42,8 +42,6 @@ static void MicroSleep(uint64_t n)
BOOST_AUTO_TEST_CASE(manythreads)
{
- seed_insecure_rand(false);
-
// Stress test: hundreds of microsecond-scheduled tasks,
// serviced by 10 threads.
//
@@ -58,7 +56,7 @@ BOOST_AUTO_TEST_CASE(manythreads)
boost::mutex counterMutex[10];
int counter[10] = { 0 };
- boost::random::mt19937 rng(insecure_rand());
+ boost::random::mt19937 rng(42);
boost::random::uniform_int_distribution<> zeroToNine(0, 9);
boost::random::uniform_int_distribution<> randomMsec(-11, 1000);
boost::random::uniform_int_distribution<> randomDelta(-1000, 1000);
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 7971b5122..561adb8ea 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -99,6 +99,7 @@ static ScriptErrorDesc script_errors[]={
{SCRIPT_ERR_WITNESS_MALLEATED, "WITNESS_MALLEATED"},
{SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"},
{SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"},
+ {SCRIPT_ERR_WITNESS_PUBKEYTYPE, "WITNESS_PUBKEYTYPE"},
};
const char *FormatScriptError(ScriptError_t err)
@@ -825,6 +826,99 @@ BOOST_AUTO_TEST_CASE(script_build)
"P2PK with witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH
).PushSig(keys.key0).Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_UNEXPECTED));
+ // Compressed keys should pass SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "Basic P2WSH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C),
+ "Basic P2WPKH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_PKH,
+ 0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C),
+ "Basic P2SH(P2WPKH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_PKH,
+ 0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit().PushRedeem());
+
+ // Testing uncompressed key in witness with SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+
+ // P2WSH 1-of-2 multisig with compressed keys
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem());
+
+ // P2WSH 1-of-2 multisig with first key uncompressed
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ // P2WSH 1-of-2 multisig with second key uncompressed
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WITNESS_SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+
std::set<std::string> tests_set;
{
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 4a48347b7..0b1050d02 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -6,7 +6,7 @@
#include "data/sighash.json.h"
#include "hash.h"
#include "main.h" // For CheckTransaction
-#include "random.h"
+#include "test_random.h"
#include "script/interpreter.h"
#include "script/script.h"
#include "serialize.h"
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index f14b902fe..b19f8fbff 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chain.h"
-#include "random.h"
+#include "test_random.h"
#include "util.h"
#include "test/test_bitcoin.h"
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 02843d852..27ea837fb 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -27,6 +27,7 @@
#include <boost/thread.hpp>
std::unique_ptr<CConnman> g_connman;
+FastRandomContext insecure_rand_ctx(true);
extern bool fPrintToConsole;
extern void noui_connect();
diff --git a/src/test/test_random.h b/src/test/test_random.h
new file mode 100644
index 000000000..e61b92b7b
--- /dev/null
+++ b/src/test/test_random.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_RANDOM_H
+#define BITCOIN_TEST_RANDOM_H
+
+#include "random.h"
+
+extern FastRandomContext insecure_rand_ctx;
+
+static inline void seed_insecure_rand(bool fDeterministic = false)
+{
+ insecure_rand_ctx = FastRandomContext(fDeterministic);
+}
+
+static inline uint32_t insecure_rand(void)
+{
+ return insecure_rand_ctx.rand32();
+}
+
+#endif
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 6163d2f63..34d9547f3 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2015 The Bitcoin Core developers
+// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -55,7 +55,8 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
(string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
(string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
(string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS)
- (string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
+ (string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
+ (string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE);
unsigned int ParseScriptFlags(string strFlags)
{
@@ -429,7 +430,7 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
mtx.nVersion = 1;
CKey key;
- key.MakeNewKey(false);
+ key.MakeNewKey(true); // Need to use compressed keys in segwit or the signing will fail
CBasicKeyStore keystore;
keystore.AddKeyPubKey(key, key.GetPubKey());
CKeyID hash = key.GetPubKey().GetID();
@@ -625,30 +626,13 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
- // Witness pay-to-uncompressed-pubkey (v1).
- CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1);
- CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2);
- CheckWithFlag(output1, input1, 0, true);
- CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
- CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
- CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
- CheckWithFlag(output1, input2, 0, true);
- CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
- CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
- CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+ // Signing disabled for witness pay-to-uncompressed-pubkey (v1).
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2, false);
- // P2SH witness pay-to-uncompressed-pubkey (v1).
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1);
- CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2);
- ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1L));
- CheckWithFlag(output1, input1, 0, true);
- CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
- CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
- CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
- CheckWithFlag(output1, input2, 0, true);
- CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
- CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
- CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+ // Signing disabled for P2SH witness pay-to-uncompressed-pubkey (v1).
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2, false);
// Normal 2-of-2 multisig
CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false);
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index efd449874..0f1c7ab22 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -6,7 +6,7 @@
#include "clientversion.h"
#include "primitives/transaction.h"
-#include "random.h"
+#include "test_random.h"
#include "sync.h"
#include "utilstrencodings.h"
#include "utilmoneystr.h"
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 1f86a06a3..ffc0ff6f8 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chain.h"
-#include "random.h"
+#include "test_random.h"
#include "versionbits.h"
#include "test/test_bitcoin.h"
#include "chainparams.h"
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 15fa6fbca..0f1c166ab 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -647,7 +647,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
if (nCheckFrequency == 0)
return;
- if (insecure_rand() >= nCheckFrequency)
+ if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency)
return;
LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
diff --git a/src/txmempool.h b/src/txmempool.h
index 941644b2b..1763930ba 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -15,6 +15,7 @@
#include "indirectmap.h"
#include "primitives/transaction.h"
#include "sync.h"
+#include "random.h"
#undef foreach
#include "boost/multi_index_container.hpp"
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 3eb7e5d9b..8e95426d1 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1025,9 +1025,12 @@ public:
bool operator()(const CKeyID &keyID) {
CPubKey pubkey;
- if (pwalletMain && pwalletMain->GetPubKey(keyID, pubkey)) {
- CScript basescript;
- basescript << ToByteVector(pubkey) << OP_CHECKSIG;
+ if (pwalletMain) {
+ CScript basescript = GetScriptForDestination(keyID);
+ isminetype typ;
+ typ = IsMine(*pwalletMain, basescript, SIGVERSION_WITNESS_V0);
+ if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
+ return false;
CScript witscript = GetScriptForWitness(basescript);
pwalletMain->AddCScript(witscript);
result = CScriptID(witscript);
@@ -1045,6 +1048,10 @@ public:
result = scriptID;
return true;
}
+ isminetype typ;
+ typ = IsMine(*pwalletMain, subscript, SIGVERSION_WITNESS_V0);
+ if (typ != ISMINE_SPENDABLE && typ != ISMINE_WATCH_SOLVABLE)
+ return false;
CScript witscript = GetScriptForWitness(subscript);
pwalletMain->AddCScript(witscript);
result = CScriptID(witscript);
@@ -1090,7 +1097,7 @@ UniValue addwitnessaddress(const UniValue& params, bool fHelp)
CTxDestination dest = address.Get();
bool ret = boost::apply_visitor(w, dest);
if (!ret) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet");
+ throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
}
pwalletMain->SetAddressBook(w.result, "", "receive");
diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp
index 05387f5f2..c5f55ef5f 100644
--- a/src/wallet/test/crypto_tests.cpp
+++ b/src/wallet/test/crypto_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "random.h"
+#include "test/test_random.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
#include "wallet/crypter.h"
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index a1f69dd94..687d84e77 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1907,7 +1907,7 @@ static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,uns
vfBest.assign(vValue.size(), true);
nBest = nTotalLower;
- seed_insecure_rand();
+ FastRandomContext insecure_rand;
for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
{
@@ -1924,7 +1924,7 @@ static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,uns
//that the rng is fast. We do not use a constant random sequence,
//because there may be some privacy improvement by making
//the selection random.
- if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
+ if (nPass == 0 ? insecure_rand.rand32()&1 : !vfIncluded[i])
{
nTotal += vValue[i].first;
vfIncluded[i] = true;