commit
cf40f0fb30
|
@ -90,7 +90,7 @@ bool static IsCompressedOrUncompressedPubKey(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.
|
||||
|
@ -130,7 +130,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;
|
||||
|
||||
|
@ -1190,6 +1190,13 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||
flags |= SCRIPT_VERIFY_STRICTENC;
|
||||
}
|
||||
|
||||
// Do not allow spends of P2WPKH-P2SH and P2WSH-P2SH UTXOs
|
||||
// To a non-segwit aware node these outputs are trivially spendable
|
||||
// Detect them here and evaluate to false
|
||||
// TODO: remove this block post-segwit implementation
|
||||
if( scriptPubKey.IsPayToWitnessPubKeyHash() || scriptPubKey.IsPayToWitnessScriptHash())
|
||||
return set_error(serror, SCRIPT_ERR_SEGWIT_LOCKED);
|
||||
|
||||
vector<vector<unsigned char> > stack, stackCopy;
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, serror))
|
||||
// serror is set
|
||||
|
@ -1223,6 +1230,10 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
|
||||
popstack(stack);
|
||||
|
||||
// See TODO above
|
||||
if(pubKey2.IsPayToWitnessPubKeyHash() || pubKey2.IsPayToWitnessScriptHash())
|
||||
return set_error(serror, SCRIPT_ERR_SEGWIT_LOCKED);
|
||||
|
||||
if (!EvalScript(stack, pubKey2, flags, checker, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
|
|
|
@ -220,6 +220,22 @@ bool CScript::IsPayToScriptHash() const
|
|||
this->at(22) == OP_EQUAL);
|
||||
}
|
||||
|
||||
bool CScript::IsPayToWitnessScriptHash() const
|
||||
{
|
||||
// Extra-fast test for pay-to-witness-script-hash CScripts:
|
||||
return (this->size() == 34 &&
|
||||
(*this)[0] == OP_0 &&
|
||||
(*this)[1] == 0x20);
|
||||
}
|
||||
|
||||
bool CScript::IsPayToWitnessPubKeyHash() const
|
||||
{
|
||||
// Extra-fast test for pay-to-witness-pubkey-hash CScripts:
|
||||
return (this->size() == 22 &&
|
||||
(*this)[0] == OP_0 &&
|
||||
(*this)[1] == 0x14);
|
||||
}
|
||||
|
||||
bool CScript::IsPushOnly() const
|
||||
{
|
||||
const_iterator pc = begin();
|
||||
|
|
|
@ -566,6 +566,9 @@ public:
|
|||
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
|
||||
bool IsPushOnly() const;
|
||||
|
||||
bool IsPayToWitnessScriptHash() const;
|
||||
bool IsPayToWitnessPubKeyHash() const;
|
||||
|
||||
/**
|
||||
* Returns whether the script is guaranteed to fail at execution,
|
||||
* regardless of the initial stack. This allows outputs to be pruned
|
||||
|
|
|
@ -67,6 +67,8 @@ const char* ScriptErrorString(const ScriptError serror)
|
|||
return "NOPx reserved for soft-fork upgrades";
|
||||
case SCRIPT_ERR_PUBKEYTYPE:
|
||||
return "Public key is neither compressed or uncompressed";
|
||||
case SCRIPT_ERR_SEGWIT_LOCKED:
|
||||
return "Segwit fork outputs are currently locked pending full implementation";
|
||||
case SCRIPT_ERR_UNKNOWN_ERROR:
|
||||
case SCRIPT_ERR_ERROR_COUNT:
|
||||
default: break;
|
||||
|
|
|
@ -55,6 +55,9 @@ typedef enum ScriptError_t
|
|||
/* SIGHASH_FORKID */
|
||||
SCRIPT_ERR_ILLEGAL_FORKID,
|
||||
|
||||
/* SEGWIT LOCKED */
|
||||
SCRIPT_ERR_SEGWIT_LOCKED,
|
||||
|
||||
SCRIPT_ERR_ERROR_COUNT
|
||||
} ScriptError;
|
||||
|
||||
|
|
|
@ -124,6 +124,41 @@ BOOST_AUTO_TEST_CASE(sign)
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(segwitlock)
|
||||
{
|
||||
ScriptError err;
|
||||
|
||||
// any scriptSig will do here
|
||||
CScript scriptSig;
|
||||
scriptSig << ToByteVector(uint256());
|
||||
|
||||
uint160 hash20;
|
||||
CScript p2wpkh;
|
||||
p2wpkh << OP_0 << ToByteVector(hash20);
|
||||
BOOST_CHECK(!Verify(scriptSig, p2wpkh, true, err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SEGWIT_LOCKED, ScriptErrorString(err));
|
||||
|
||||
CScript p2shp2wpkh = GetScriptForDestination(CScriptID(p2wpkh));
|
||||
CScript p2shp2wpkhsig = scriptSig;
|
||||
p2shp2wpkhsig << Serialize(p2wpkh);
|
||||
|
||||
BOOST_CHECK(!Verify(p2shp2wpkhsig, p2shp2wpkh, true, err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SEGWIT_LOCKED, ScriptErrorString(err));
|
||||
|
||||
uint256 hash32;
|
||||
CScript p2wsh;
|
||||
p2wsh << OP_0 << ToByteVector(hash32);
|
||||
BOOST_CHECK(!Verify(scriptSig, p2wsh, true, err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SEGWIT_LOCKED, ScriptErrorString(err));
|
||||
|
||||
CScript p2shp2wsh = GetScriptForDestination(CScriptID(p2wsh));
|
||||
CScript p2shp2wshsig = scriptSig;
|
||||
p2shp2wshsig << Serialize(p2wsh);
|
||||
|
||||
BOOST_CHECK(!Verify(p2shp2wshsig, p2shp2wsh, true, err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SEGWIT_LOCKED, ScriptErrorString(err));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(norecurse)
|
||||
{
|
||||
ScriptError err;
|
||||
|
@ -216,6 +251,15 @@ BOOST_AUTO_TEST_CASE(is)
|
|||
p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL;
|
||||
BOOST_CHECK(p2sh.IsPayToScriptHash());
|
||||
|
||||
CScript p2wpkh;
|
||||
p2wpkh << OP_0 << ToByteVector(dummy);
|
||||
BOOST_CHECK(p2wpkh.IsPayToWitnessPubKeyHash());
|
||||
|
||||
uint256 dummy256;
|
||||
CScript p2wsh;
|
||||
p2wsh << OP_0 << ToByteVector(dummy256);
|
||||
BOOST_CHECK(p2wsh.IsPayToWitnessScriptHash());
|
||||
|
||||
// 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());
|
||||
|
|
Loading…
Reference in New Issue