Merge branch 'standardScriptSigs' of github.com:gavinandresen/bitcoin-git
This commit is contained in:
commit
0b452dff5e
5 changed files with 67 additions and 11 deletions
25
src/main.cpp
25
src/main.cpp
|
@ -295,18 +295,33 @@ bool CTransaction::AreInputsStandard(const MapPrevTx& mapInputs) const
|
||||||
const CScript& prevScript = prev.scriptPubKey;
|
const CScript& prevScript = prev.scriptPubKey;
|
||||||
if (!Solver(prevScript, whichType, vSolutions))
|
if (!Solver(prevScript, whichType, vSolutions))
|
||||||
return false;
|
return false;
|
||||||
|
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
|
||||||
|
|
||||||
|
// Transactions with extra stuff in their scriptSigs are
|
||||||
|
// non-standard. Note that this EvalScript() call will
|
||||||
|
// be quick, because if there are any operations
|
||||||
|
// beside "push data" in the scriptSig the
|
||||||
|
// IsStandard() call returns false
|
||||||
|
vector<vector<unsigned char> > stack;
|
||||||
|
if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (whichType == TX_SCRIPTHASH)
|
if (whichType == TX_SCRIPTHASH)
|
||||||
{
|
{
|
||||||
vector<vector<unsigned char> > stack;
|
|
||||||
|
|
||||||
if (!EvalScript(stack, vin[i].scriptSig, *this, i, 0))
|
|
||||||
return false;
|
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
return false;
|
return false;
|
||||||
CScript subscript(stack.back().begin(), stack.back().end());
|
CScript subscript(stack.back().begin(), stack.back().end());
|
||||||
if (!::IsStandard(subscript))
|
vector<vector<unsigned char> > vSolutions2;
|
||||||
|
txnouttype whichType2;
|
||||||
|
if (!Solver(subscript, whichType2, vSolutions2))
|
||||||
return false;
|
return false;
|
||||||
|
if (whichType2 == TX_SCRIPTHASH)
|
||||||
|
return false;
|
||||||
|
nArgsExpected += ScriptSigArgsExpected(whichType2, vSolutions2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stack.size() != nArgsExpected)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1312,6 +1312,25 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case TX_NONSTANDARD:
|
||||||
|
return -1;
|
||||||
|
case TX_PUBKEY:
|
||||||
|
return 1;
|
||||||
|
case TX_PUBKEYHASH:
|
||||||
|
return 2;
|
||||||
|
case TX_MULTISIG:
|
||||||
|
if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
|
||||||
|
return -1;
|
||||||
|
return vSolutions[0][0] + 1;
|
||||||
|
case TX_SCRIPTHASH:
|
||||||
|
return 1; // doesn't include args needed by the script
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsStandard(const CScript& scriptPubKey)
|
bool IsStandard(const CScript& scriptPubKey)
|
||||||
{
|
{
|
||||||
|
|
|
@ -560,6 +560,7 @@ public:
|
||||||
|
|
||||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||||
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
||||||
|
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
|
||||||
bool IsStandard(const CScript& scriptPubKey);
|
bool IsStandard(const CScript& scriptPubKey);
|
||||||
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
||||||
bool ExtractAddress(const CScript& scriptPubKey, CBitcoinAddress& addressRet);
|
bool ExtractAddress(const CScript& scriptPubKey, CBitcoinAddress& addressRet);
|
||||||
|
|
|
@ -300,6 +300,15 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
||||||
BOOST_CHECK(txTo.AreInputsStandard(mapInputs));
|
BOOST_CHECK(txTo.AreInputsStandard(mapInputs));
|
||||||
BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(mapInputs), 1);
|
BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(mapInputs), 1);
|
||||||
|
|
||||||
|
// Make sure adding crap to the scriptSigs makes them non-standard:
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
CScript t = txTo.vin[i].scriptSig;
|
||||||
|
txTo.vin[i].scriptSig = (CScript() << 11) + t;
|
||||||
|
BOOST_CHECK(!txTo.AreInputsStandard(mapInputs));
|
||||||
|
txTo.vin[i].scriptSig = t;
|
||||||
|
}
|
||||||
|
|
||||||
CTransaction txToNonStd;
|
CTransaction txToNonStd;
|
||||||
txToNonStd.vout.resize(1);
|
txToNonStd.vout.resize(1);
|
||||||
txToNonStd.vout[0].scriptPubKey.SetBitcoinAddress(key[1].GetPubKey());
|
txToNonStd.vout[0].scriptPubKey.SetBitcoinAddress(key[1].GetPubKey());
|
||||||
|
|
|
@ -24,8 +24,9 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Helper: create two dummy transactions, each with
|
// Helper: create two dummy transactions, each with
|
||||||
// two outputs. The first has 11 and 50 CENT outputs,
|
// two outputs. The first has 11 and 50 CENT outputs
|
||||||
// the second 21 and 22 CENT outputs.
|
// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
|
||||||
|
// paid to a TX_PUBKEYHASH.
|
||||||
//
|
//
|
||||||
static std::vector<CTransaction>
|
static std::vector<CTransaction>
|
||||||
SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
|
SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
|
||||||
|
@ -44,9 +45,9 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
|
||||||
// Create some dummy input transactions
|
// Create some dummy input transactions
|
||||||
dummyTransactions[0].vout.resize(2);
|
dummyTransactions[0].vout.resize(2);
|
||||||
dummyTransactions[0].vout[0].nValue = 11*CENT;
|
dummyTransactions[0].vout[0].nValue = 11*CENT;
|
||||||
dummyTransactions[0].vout[0].scriptPubKey.SetBitcoinAddress(key[0].GetPubKey());
|
dummyTransactions[0].vout[0].scriptPubKey << key[0].GetPubKey() << OP_CHECKSIG;
|
||||||
dummyTransactions[0].vout[1].nValue = 50*CENT;
|
dummyTransactions[0].vout[1].nValue = 50*CENT;
|
||||||
dummyTransactions[0].vout[1].scriptPubKey.SetBitcoinAddress(key[1].GetPubKey());
|
dummyTransactions[0].vout[1].scriptPubKey << key[1].GetPubKey() << OP_CHECKSIG;
|
||||||
inputsRet[dummyTransactions[0].GetHash()] = make_pair(CTxIndex(), dummyTransactions[0]);
|
inputsRet[dummyTransactions[0].GetHash()] = make_pair(CTxIndex(), dummyTransactions[0]);
|
||||||
|
|
||||||
dummyTransactions[1].vout.resize(2);
|
dummyTransactions[1].vout.resize(2);
|
||||||
|
@ -69,16 +70,27 @@ BOOST_AUTO_TEST_CASE(test_Get)
|
||||||
t1.vin.resize(3);
|
t1.vin.resize(3);
|
||||||
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
||||||
t1.vin[0].prevout.n = 1;
|
t1.vin[0].prevout.n = 1;
|
||||||
t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();;
|
t1.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
|
||||||
|
t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();
|
||||||
t1.vin[1].prevout.n = 0;
|
t1.vin[1].prevout.n = 0;
|
||||||
t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();;
|
t1.vin[1].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
|
||||||
|
t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();
|
||||||
t1.vin[2].prevout.n = 1;
|
t1.vin[2].prevout.n = 1;
|
||||||
|
t1.vin[2].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
|
||||||
t1.vout.resize(2);
|
t1.vout.resize(2);
|
||||||
t1.vout[0].nValue = 90*CENT;
|
t1.vout[0].nValue = 90*CENT;
|
||||||
t1.vout[0].scriptPubKey << OP_1;
|
t1.vout[0].scriptPubKey << OP_1;
|
||||||
|
|
||||||
BOOST_CHECK(t1.AreInputsStandard(dummyInputs));
|
BOOST_CHECK(t1.AreInputsStandard(dummyInputs));
|
||||||
BOOST_CHECK_EQUAL(t1.GetValueIn(dummyInputs), (50+21+22)*CENT);
|
BOOST_CHECK_EQUAL(t1.GetValueIn(dummyInputs), (50+21+22)*CENT);
|
||||||
|
|
||||||
|
// Adding extra junk to the scriptSig should make it non-standard:
|
||||||
|
t1.vin[0].scriptSig << OP_11;
|
||||||
|
BOOST_CHECK(!t1.AreInputsStandard(dummyInputs));
|
||||||
|
|
||||||
|
// ... as should not having enough:
|
||||||
|
t1.vin[0].scriptSig = CScript();
|
||||||
|
BOOST_CHECK(!t1.AreInputsStandard(dummyInputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_GetThrow)
|
BOOST_AUTO_TEST_CASE(test_GetThrow)
|
||||||
|
|
Loading…
Reference in a new issue