-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
324 additions
and
283 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
// Copyright (c) 2009-2010 Satoshi Nakamoto | ||
// Copyright (c) 2009-2013 The Bitcoin developers | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#include "script/standard.h" | ||
|
||
#include "script/script.h" | ||
#include "util.h" | ||
|
||
#include <boost/foreach.hpp> | ||
|
||
using namespace std; | ||
|
||
typedef vector<unsigned char> valtype; | ||
|
||
const char* GetTxnOutputType(txnouttype t) | ||
{ | ||
switch (t) | ||
{ | ||
case TX_NONSTANDARD: return "nonstandard"; | ||
case TX_PUBKEY: return "pubkey"; | ||
case TX_PUBKEYHASH: return "pubkeyhash"; | ||
case TX_SCRIPTHASH: return "scripthash"; | ||
case TX_MULTISIG: return "multisig"; | ||
case TX_NULL_DATA: return "nulldata"; | ||
} | ||
return NULL; | ||
} | ||
|
||
// | ||
// Return public keys or hashes from scriptPubKey, for 'standard' transaction types. | ||
// | ||
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet) | ||
{ | ||
// Templates | ||
static multimap<txnouttype, CScript> mTemplates; | ||
if (mTemplates.empty()) | ||
{ | ||
// Standard tx, sender provides pubkey, receiver adds signature | ||
mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG)); | ||
|
||
// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey | ||
mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG)); | ||
|
||
// Sender provides N pubkeys, receivers provides M signatures | ||
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); | ||
|
||
// Empty, provably prunable, data-carrying output | ||
if (GetBoolArg("-datacarrier", true)) | ||
mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA)); | ||
mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN)); | ||
} | ||
|
||
// 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 (scriptPubKey.IsPayToScriptHash()) | ||
{ | ||
typeRet = TX_SCRIPTHASH; | ||
vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22); | ||
vSolutionsRet.push_back(hashBytes); | ||
return true; | ||
} | ||
|
||
// Scan templates | ||
const CScript& script1 = scriptPubKey; | ||
BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates) | ||
{ | ||
const CScript& script2 = tplate.second; | ||
vSolutionsRet.clear(); | ||
|
||
opcodetype opcode1, opcode2; | ||
vector<unsigned char> vch1, vch2; | ||
|
||
// Compare | ||
CScript::const_iterator pc1 = script1.begin(); | ||
CScript::const_iterator pc2 = script2.begin(); | ||
while (true) | ||
{ | ||
if (pc1 == script1.end() && pc2 == script2.end()) | ||
{ | ||
// Found a match | ||
typeRet = tplate.first; | ||
if (typeRet == TX_MULTISIG) | ||
{ | ||
// Additional checks for TX_MULTISIG: | ||
unsigned char m = vSolutionsRet.front()[0]; | ||
unsigned char n = vSolutionsRet.back()[0]; | ||
if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n) | ||
return false; | ||
} | ||
return true; | ||
} | ||
if (!script1.GetOp(pc1, opcode1, vch1)) | ||
break; | ||
if (!script2.GetOp(pc2, opcode2, vch2)) | ||
break; | ||
|
||
// Template matching opcodes: | ||
if (opcode2 == OP_PUBKEYS) | ||
{ | ||
while (vch1.size() >= 33 && vch1.size() <= 65) | ||
{ | ||
vSolutionsRet.push_back(vch1); | ||
if (!script1.GetOp(pc1, opcode1, vch1)) | ||
break; | ||
} | ||
if (!script2.GetOp(pc2, opcode2, vch2)) | ||
break; | ||
// Normal situation is to fall through | ||
// to other if/else statements | ||
} | ||
|
||
if (opcode2 == OP_PUBKEY) | ||
{ | ||
if (vch1.size() < 33 || vch1.size() > 65) | ||
break; | ||
vSolutionsRet.push_back(vch1); | ||
} | ||
else if (opcode2 == OP_PUBKEYHASH) | ||
{ | ||
if (vch1.size() != sizeof(uint160)) | ||
break; | ||
vSolutionsRet.push_back(vch1); | ||
} | ||
else if (opcode2 == OP_SMALLINTEGER) | ||
{ // Single-byte small integer pushed onto vSolutions | ||
if (opcode1 == OP_0 || | ||
(opcode1 >= OP_1 && opcode1 <= OP_16)) | ||
{ | ||
char n = (char)CScript::DecodeOP_N(opcode1); | ||
vSolutionsRet.push_back(valtype(1, n)); | ||
} | ||
else | ||
break; | ||
} | ||
else if (opcode2 == OP_SMALLDATA) | ||
{ | ||
// small pushdata, <= MAX_OP_RETURN_RELAY bytes | ||
if (vch1.size() > MAX_OP_RETURN_RELAY) | ||
break; | ||
} | ||
else if (opcode1 != opcode2 || vch1 != vch2) | ||
{ | ||
// Others must match exactly | ||
break; | ||
} | ||
} | ||
} | ||
|
||
vSolutionsRet.clear(); | ||
typeRet = TX_NONSTANDARD; | ||
return false; | ||
} | ||
|
||
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions) | ||
{ | ||
switch (t) | ||
{ | ||
case TX_NONSTANDARD: | ||
case TX_NULL_DATA: | ||
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, txnouttype& whichType) | ||
{ | ||
vector<valtype> vSolutions; | ||
if (!Solver(scriptPubKey, whichType, vSolutions)) | ||
return false; | ||
|
||
if (whichType == TX_MULTISIG) | ||
{ | ||
unsigned char m = vSolutions.front()[0]; | ||
unsigned char n = vSolutions.back()[0]; | ||
// Support up to x-of-3 multisig txns as standard | ||
if (n < 1 || n > 3) | ||
return false; | ||
if (m < 1 || m > n) | ||
return false; | ||
} | ||
|
||
return whichType != TX_NONSTANDARD; | ||
} | ||
|
||
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) | ||
{ | ||
vector<valtype> vSolutions; | ||
txnouttype whichType; | ||
if (!Solver(scriptPubKey, whichType, vSolutions)) | ||
return false; | ||
|
||
if (whichType == TX_PUBKEY) | ||
{ | ||
addressRet = CPubKey(vSolutions[0]).GetID(); | ||
return true; | ||
} | ||
else if (whichType == TX_PUBKEYHASH) | ||
{ | ||
addressRet = CKeyID(uint160(vSolutions[0])); | ||
return true; | ||
} | ||
else if (whichType == TX_SCRIPTHASH) | ||
{ | ||
addressRet = CScriptID(uint160(vSolutions[0])); | ||
return true; | ||
} | ||
// Multisig txns have more than one address... | ||
return false; | ||
} | ||
|
||
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet) | ||
{ | ||
addressRet.clear(); | ||
typeRet = TX_NONSTANDARD; | ||
vector<valtype> vSolutions; | ||
if (!Solver(scriptPubKey, typeRet, vSolutions)) | ||
return false; | ||
if (typeRet == TX_NULL_DATA){ | ||
// This is data, not addresses | ||
return false; | ||
} | ||
|
||
if (typeRet == TX_MULTISIG) | ||
{ | ||
nRequiredRet = vSolutions.front()[0]; | ||
for (unsigned int i = 1; i < vSolutions.size()-1; i++) | ||
{ | ||
CTxDestination address = CPubKey(vSolutions[i]).GetID(); | ||
addressRet.push_back(address); | ||
} | ||
} | ||
else | ||
{ | ||
nRequiredRet = 1; | ||
CTxDestination address; | ||
if (!ExtractDestination(scriptPubKey, address)) | ||
return false; | ||
addressRet.push_back(address); | ||
} | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright (c) 2009-2010 Satoshi Nakamoto | ||
// Copyright (c) 2009-2013 The Bitcoin developers | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#ifndef H_BITCOIN_SCRIPT_STANDARD | ||
#define H_BITCOIN_SCRIPT_STANDARD | ||
|
||
#include "script/script.h" | ||
#include "script/interpreter.h" | ||
|
||
#include <stdint.h> | ||
|
||
class CScript; | ||
|
||
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes | ||
|
||
// Mandatory script verification flags that all new blocks must comply with for | ||
// them to be valid. (but old blocks may not comply with) Currently just P2SH, | ||
// but in the future other flags may be added, such as a soft-fork to enforce | ||
// strict DER encoding. | ||
// | ||
// Failing one of these tests may trigger a DoS ban - see CheckInputs() for | ||
// details. | ||
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; | ||
|
||
// Standard script verification flags that standard transactions will comply | ||
// with. However scripts violating these flags may still be present in valid | ||
// blocks and we must accept those blocks. | ||
static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | | ||
SCRIPT_VERIFY_STRICTENC | | ||
SCRIPT_VERIFY_NULLDUMMY; | ||
|
||
// 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; | ||
|
||
enum txnouttype | ||
{ | ||
TX_NONSTANDARD, | ||
// 'standard' transaction types: | ||
TX_PUBKEY, | ||
TX_PUBKEYHASH, | ||
TX_SCRIPTHASH, | ||
TX_MULTISIG, | ||
TX_NULL_DATA, | ||
}; | ||
|
||
const char* GetTxnOutputType(txnouttype t); | ||
|
||
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, txnouttype& whichType); | ||
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); | ||
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet); | ||
|
||
#endif |
Oops, something went wrong.