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. 4
      src/script/interpreter.cpp
  6. 19
      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. 2
      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)
// if redeemScript given and private keys given, // if redeemScript given and private keys given,
// add redeemScript to the tempKeystore so it can be signed: // 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")) { prevOut.exists("redeemScript")) {
UniValue v = prevOut["redeemScript"]; UniValue v = prevOut["redeemScript"];
std::vector<unsigned char> rsData(ParseHexUV(v, "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
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout); const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
assert(!coin.IsSpent()); assert(!coin.IsSpent());
const CTxOut &prevout = coin.out; const CTxOut &prevout = coin.out;
if (prevout.scriptPubKey.IsPayToScriptHash()) if (prevout.scriptPubKey.IsPayToScriptHash(true))
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig); nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
} }
return nSigOps; return nSigOps;

2
src/policy/policy.cpp

@ -210,7 +210,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
// get the scriptPubKey corresponding to this input: // get the scriptPubKey corresponding to this input:
CScript prevScript = prev.scriptPubKey; CScript prevScript = prev.scriptPubKey;
if (prevScript.IsPayToScriptHash()) { if (prevScript.IsPayToScriptHash(true)) {
std::vector <std::vector<unsigned char> > stack; std::vector <std::vector<unsigned char> > stack;
// If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig // 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. // 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)
// if redeemScript given and not using the local wallet (private keys // if redeemScript given and not using the local wallet (private keys
// given), add redeemScript to the tempKeystore so it can be signed: // 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, RPCTypeCheckObj(prevOut,
{ {
{"txid", UniValueType(UniValue::VSTR)}, {"txid", UniValueType(UniValue::VSTR)},

4
src/script/interpreter.cpp

@ -1465,7 +1465,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
} }
// Additional validation for spend-to-script-hash transactions: // 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 // scriptSig must be literals-only or validation fails
if (!scriptSig.IsPushOnly()) if (!scriptSig.IsPushOnly())
@ -1567,7 +1567,7 @@ size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey,
return WitnessSigOps(witnessversion, witnessprogram, witness ? *witness : witnessEmpty, flags); 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(); CScript::const_iterator pc = scriptSig.begin();
std::vector<unsigned char> data; std::vector<unsigned char> data;
while (pc < scriptSig.end()) { while (pc < scriptSig.end()) {

19
src/script/script.cpp

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

4
src/script/script.h

@ -646,8 +646,8 @@ public:
*/ */
unsigned int GetSigOpCount(const CScript& scriptSig) const; unsigned int GetSigOpCount(const CScript& scriptSig) const;
bool IsPayToScriptHash() const; bool IsPayToScriptHash(bool allowKeva) const;
bool IsPayToWitnessScriptHash() const; bool IsPayToWitnessScriptHash(bool allowKeva) const;
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const; bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ /** 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
// Shortcut for pay-to-script-hash, which are more constrained than the other types: // 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 // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if (script1.IsPayToScriptHash()) if (script1.IsPayToScriptHash(false))
{ {
typeRet = TX_SCRIPTHASH; typeRet = TX_SCRIPTHASH;
std::vector<unsigned char> hashBytes(script1.begin()+2, script1.begin()+22); 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)
uint160 dummy; uint160 dummy;
CScript p2sh; CScript p2sh;
p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL; 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: // 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 }; 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 }; 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 }; 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 }; 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; 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; 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; 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; 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) BOOST_AUTO_TEST_CASE(switchover)

2
src/wallet/rpcdump.cpp

@ -874,7 +874,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
CScript redeemScript = CScript(vData.begin(), vData.end()); CScript redeemScript = CScript(vData.begin(), vData.end());
// Invalid P2SH address // Invalid P2SH address
if (!script.IsPayToScriptHash()) { if (!script.IsPayToScriptHash(true)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid P2SH address / script"); 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)
entry.push_back(Pair("account", pwallet->mapAddressBook[address].name)); entry.push_back(Pair("account", pwallet->mapAddressBook[address].name));
} }
if (scriptPubKey.IsPayToScriptHash()) { if (scriptPubKey.IsPayToScriptHash(true)) {
const CScriptID& hash = boost::get<CScriptID>(address); const CScriptID& hash = boost::get<CScriptID>(address);
CScript redeemScript; CScript redeemScript;
if (pwallet->GetCScript(hash, redeemScript)) { if (pwallet->GetCScript(hash, redeemScript)) {

Loading…
Cancel
Save