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) @@ -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)},

4
src/script/interpreter.cpp

@ -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()) {

19
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,23 +200,35 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const @@ -199,23 +200,35 @@ 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:
if (!allowKeva) {
return (this->size() == 23 &&
(*this)[0] == OP_HASH160 &&
(*this)[1] == 0x14 &&
(*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:
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
// followed by a data push between 2 and 40 bytes.
bool CScript::IsWitnessProgram(int& version, std::vector<unsigned char>& program) const

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)

2
src/wallet/rpcdump.cpp

@ -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