Browse Source

Handled keva script with getAddress.

cn
Jianping Wu 6 years ago
parent
commit
2ba7b82896
  1. 2
      src/bitcoin-tx.cpp
  2. 2
      src/consensus/tx_verify.cpp
  3. 2
      src/policy/policy.cpp
  4. 2
      src/rpc/rawtransaction.cpp
  5. 10
      src/script/interpreter.cpp
  6. 23
      src/script/script.cpp
  7. 4
      src/script/script.h
  8. 2
      src/script/standard.cpp
  9. 18
      src/test/script_P2SH_tests.cpp
  10. 4
      src/wallet/rpcdump.cpp
  11. 2
      src/wallet/rpcwallet.cpp

2
src/bitcoin-tx.cpp

@ -621,7 +621,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) @@ -621,7 +621,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
// if redeemScript given and private keys given,
// add redeemScript to the tempKeystore so it can be signed:
if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) &&
if ((scriptPubKey.IsPayToScriptHash(true) || scriptPubKey.IsPayToWitnessScriptHash(true)) &&
prevOut.exists("redeemScript")) {
UniValue v = prevOut["redeemScript"];
std::vector<unsigned char> rsData(ParseHexUV(v, "redeemScript"));

2
src/consensus/tx_verify.cpp

@ -130,7 +130,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in @@ -130,7 +130,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
assert(!coin.IsSpent());
const CTxOut &prevout = coin.out;
if (prevout.scriptPubKey.IsPayToScriptHash())
if (prevout.scriptPubKey.IsPayToScriptHash(true))
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
}
return nSigOps;

2
src/policy/policy.cpp

@ -210,7 +210,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) @@ -210,7 +210,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// get the scriptPubKey corresponding to this input:
CScript prevScript = prev.scriptPubKey;
if (prevScript.IsPayToScriptHash()) {
if (prevScript.IsPayToScriptHash(true)) {
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.

2
src/rpc/rawtransaction.cpp

@ -840,7 +840,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) @@ -840,7 +840,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
// if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed:
if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash())) {
if (fGivenKeys && (scriptPubKey.IsPayToScriptHash(true) || scriptPubKey.IsPayToWitnessScriptHash(true))) {
RPCTypeCheckObj(prevOut,
{
{"txid", UniValueType(UniValue::VSTR)},

10
src/script/interpreter.cpp

@ -99,7 +99,7 @@ bool static IsCompressedPubKey(const valtype &vchPubKey) { @@ -99,7 +99,7 @@ bool static IsCompressedPubKey(const valtype &vchPubKey) {
* Where R and S are not negative (their first byte has its highest bit not set), and not
* excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
* in which case a single 0 byte is necessary and even required).
*
*
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
*
* This function is consensus-critical since BIP66.
@ -139,7 +139,7 @@ bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) { @@ -139,7 +139,7 @@ bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
// Verify that the length of the signature matches the sum of the length
// of the elements.
if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
// Check whether the R element is an integer.
if (sig[2] != 0x02) return false;
@ -869,7 +869,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& @@ -869,7 +869,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
popstack(stack);
stack.push_back(vchHash);
}
break;
break;
case OP_CODESEPARATOR:
{
@ -1465,7 +1465,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C @@ -1465,7 +1465,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
}
// Additional validation for spend-to-script-hash transactions:
if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash(true))
{
// scriptSig must be literals-only or validation fails
if (!scriptSig.IsPushOnly())
@ -1567,7 +1567,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, @@ -1567,7 +1567,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags);
}
if (scriptPubKey.IsPayToScriptHash() && scriptSig.IsPushOnly()) {
if (scriptPubKey.IsPayToScriptHash(true) && scriptSig.IsPushOnly()) {
CScript::const_iterator pc = scriptSig.begin();
std::vector<unsigned char> data;
while (pc < scriptSig.end()) {

23
src/script/script.cpp

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#include <script/script.h>
#include <script/keva.h>
#include <tinyformat.h>
#include <utilstrencodings.h>
@ -177,7 +178,7 @@ unsigned int CScript::GetSigOpCount(bool fAccurate) const @@ -177,7 +178,7 @@ unsigned int CScript::GetSigOpCount(bool fAccurate) const
unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
{
if (!IsPayToScriptHash())
if (!IsPayToScriptHash(true))
return GetSigOpCount(true);
// This is a pay-to-script-hash scriptPubKey;
@ -199,21 +200,33 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const @@ -199,21 +200,33 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
return subscript.GetSigOpCount(true);
}
bool CScript::IsPayToScriptHash() const
bool CScript::IsPayToScriptHash(bool allowKeva) const
{
// Extra-fast test for pay-to-script-hash CScripts:
return (this->size() == 23 &&
if (!allowKeva) {
return (this->size() == 23 &&
(*this)[0] == OP_HASH160 &&
(*this)[1] == 0x14 &&
(*this)[22] == OP_EQUAL);
}
// Strip off a keva prefix if present.
const CKevaScript kevaOp(*this);
return kevaOp.getAddress().IsPayToScriptHash(false);
}
bool CScript::IsPayToWitnessScriptHash() const
bool CScript::IsPayToWitnessScriptHash(bool allowKeva) const
{
// Extra-fast test for pay-to-witness-script-hash CScripts:
return (this->size() == 34 &&
if (!allowKeva) {
return (this->size() == 34 &&
(*this)[0] == OP_0 &&
(*this)[1] == 0x20);
}
// Strip off a keva prefix if present.
const CKevaScript kevaOp(*this);
return kevaOp.getAddress().IsPayToWitnessScriptHash(false);
}
// A witness program is any valid CScript that consists of a 1-byte push opcode

4
src/script/script.h

@ -646,8 +646,8 @@ public: @@ -646,8 +646,8 @@ public:
*/
unsigned int GetSigOpCount(const CScript& scriptSig) const;
bool IsPayToScriptHash() const;
bool IsPayToWitnessScriptHash() const;
bool IsPayToScriptHash(bool allowKeva) const;
bool IsPayToWitnessScriptHash(bool allowKeva) const;
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */

2
src/script/standard.cpp

@ -60,7 +60,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v @@ -60,7 +60,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if (script1.IsPayToScriptHash())
if (script1.IsPayToScriptHash(false))
{
typeRet = TX_SCRIPTHASH;
std::vector<unsigned char> hashBytes(script1.begin()+2, script1.begin()+22);

18
src/test/script_P2SH_tests.cpp

@ -210,29 +210,29 @@ BOOST_AUTO_TEST_CASE(is) @@ -210,29 +210,29 @@ BOOST_AUTO_TEST_CASE(is)
uint160 dummy;
CScript p2sh;
p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL;
BOOST_CHECK(p2sh.IsPayToScriptHash());
BOOST_CHECK(p2sh.IsPayToScriptHash(true));
// Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes:
static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash());
BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash(false));
static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash());
BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash(true));
static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash());
BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash(false));
static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash());
BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash(true));
CScript not_p2sh;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
BOOST_CHECK(!not_p2sh.IsPayToScriptHash(true));
not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << ToByteVector(dummy) << OP_EQUAL;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
BOOST_CHECK(!not_p2sh.IsPayToScriptHash(true));
not_p2sh.clear(); not_p2sh << OP_NOP << ToByteVector(dummy) << OP_EQUAL;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
BOOST_CHECK(!not_p2sh.IsPayToScriptHash(true));
not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << OP_CHECKSIG;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
BOOST_CHECK(!not_p2sh.IsPayToScriptHash(true));
}
BOOST_AUTO_TEST_CASE(switchover)

4
src/wallet/rpcdump.cpp

@ -62,7 +62,7 @@ std::string DecodeDumpString(const std::string &str) { @@ -62,7 +62,7 @@ std::string DecodeDumpString(const std::string &str) {
for (unsigned int pos = 0; pos < str.length(); pos++) {
unsigned char c = str[pos];
if (c == '%' && pos+2 < str.length()) {
c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
pos += 2;
}
@ -874,7 +874,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 @@ -874,7 +874,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
CScript redeemScript = CScript(vData.begin(), vData.end());
// Invalid P2SH address
if (!script.IsPayToScriptHash()) {
if (!script.IsPayToScriptHash(true)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script");
}

2
src/wallet/rpcwallet.cpp

@ -3068,7 +3068,7 @@ UniValue listunspent(const JSONRPCRequest& request) @@ -3068,7 +3068,7 @@ UniValue listunspent(const JSONRPCRequest& request)
entry.push_back(Pair("account", pwallet->mapAddressBook[address].name));
}
if (scriptPubKey.IsPayToScriptHash()) {
if (scriptPubKey.IsPayToScriptHash(true)) {
const CScriptID& hash = boost::get<CScriptID>(address);
CScript redeemScript;
if (pwallet->GetCScript(hash, redeemScript)) {

Loading…
Cancel
Save