mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Require compressed keys in segwit as policy and disable signing with uncompressed keys for segwit scripts
This commit is contained in:
parent
3ade2f64cf
commit
4c0c25a604
@ -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.
|
||||
|
||||
@ -54,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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user