Merge all Komodo changes, including proof of stake, crypto conditions, passport, etc.
This commit is contained in:
137
src/script/cc.cpp
Normal file
137
src/script/cc.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "cryptoconditions/include/cryptoconditions.h"
|
||||
#include "script/cc.h"
|
||||
|
||||
|
||||
bool IsCryptoConditionsEnabled()
|
||||
{
|
||||
return 0 != ASSETCHAINS_CC;
|
||||
}
|
||||
|
||||
|
||||
bool IsSupportedCryptoCondition(const CC *cond)
|
||||
{
|
||||
int mask = cc_typeMask(cond);
|
||||
|
||||
if (mask & ~CCEnabledTypes) return false;
|
||||
|
||||
// Also require that the condition have at least one signable node
|
||||
if (!(mask & CCSigningNodes)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IsSignedCryptoCondition(const CC *cond)
|
||||
{
|
||||
if (!cc_isFulfilled(cond)) return false;
|
||||
if (1 << cc_typeId(cond) & CCSigningNodes) return true;
|
||||
if (cc_typeId(cond) == CC_Threshold)
|
||||
for (int i=0; i<cond->size; i++)
|
||||
if (IsSignedCryptoCondition(cond->subconditions[i])) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char* CopyPubKey(CPubKey pkIn)
|
||||
{
|
||||
unsigned char* pk = (unsigned char*) malloc(33);
|
||||
memcpy(pk, pkIn.begin(), 33); // TODO: compressed?
|
||||
return pk;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewThreshold(int t, std::vector<CC*> v)
|
||||
{
|
||||
CC *cond = cc_new(CC_Threshold);
|
||||
cond->threshold = t;
|
||||
cond->size = v.size();
|
||||
cond->subconditions = (CC**) calloc(v.size(), sizeof(CC*));
|
||||
memcpy(cond->subconditions, v.data(), v.size() * sizeof(CC*));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewSecp256k1(CPubKey k)
|
||||
{
|
||||
CC *cond = cc_new(CC_Secp256k1);
|
||||
cond->publicKey = CopyPubKey(k);
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewEval(std::vector<unsigned char> code)
|
||||
{
|
||||
CC *cond = cc_new(CC_Eval);
|
||||
cond->code = (unsigned char*) malloc(code.size());
|
||||
memcpy(cond->code, code.data(), code.size());
|
||||
cond->codeLength = code.size();
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CScript CCPubKey(const CC *cond)
|
||||
{
|
||||
unsigned char buf[1000];
|
||||
size_t len = cc_conditionBinary(cond, buf);
|
||||
return CScript() << std::vector<unsigned char>(buf, buf+len) << OP_CHECKCRYPTOCONDITION;
|
||||
}
|
||||
|
||||
|
||||
CScript CCSig(const CC *cond)
|
||||
{
|
||||
unsigned char buf[10000];
|
||||
size_t len = cc_fulfillmentBinary(cond, buf, 10000);
|
||||
auto ffill = std::vector<unsigned char>(buf, buf+len);
|
||||
ffill.push_back(1); // SIGHASH_ALL
|
||||
return CScript() << ffill;
|
||||
}
|
||||
|
||||
|
||||
std::string CCShowStructure(CC *cond)
|
||||
{
|
||||
std::string out;
|
||||
if (cc_isAnon(cond)) {
|
||||
out = "A" + std::to_string(cc_typeId(cond));
|
||||
}
|
||||
else if (cc_typeId(cond) == CC_Threshold) {
|
||||
out += "(" + std::to_string(cond->threshold) + " of ";
|
||||
for (int i=0; i<cond->size; i++) {
|
||||
out += CCShowStructure(cond->subconditions[i]);
|
||||
if (i < cond->size - 1) out += ",";
|
||||
}
|
||||
out += ")";
|
||||
}
|
||||
else {
|
||||
out = std::to_string(cc_typeId(cond));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
CC* CCPrune(CC *cond)
|
||||
{
|
||||
std::vector<unsigned char> ffillBin;
|
||||
GetPushData(CCSig(cond), ffillBin);
|
||||
return cc_readFulfillmentBinary(ffillBin.data(), ffillBin.size()-1);
|
||||
}
|
||||
|
||||
|
||||
bool GetPushData(const CScript &sig, std::vector<unsigned char> &data)
|
||||
{
|
||||
opcodetype opcode;
|
||||
auto pc = sig.begin();
|
||||
if (sig.GetOp(pc, opcode, data)) return opcode > OP_0 && opcode <= OP_PUSHDATA4;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GetOpReturnData(const CScript &sig, std::vector<unsigned char> &data)
|
||||
{
|
||||
auto pc = sig.begin();
|
||||
opcodetype opcode;
|
||||
if (sig.GetOp2(pc, opcode, NULL))
|
||||
if (opcode == OP_RETURN)
|
||||
if (sig.GetOp(pc, opcode, data))
|
||||
return opcode > OP_0 && opcode <= OP_PUSHDATA4;
|
||||
return false;
|
||||
}
|
||||
83
src/script/cc.h
Normal file
83
src/script/cc.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef SCRIPT_CC_H
|
||||
#define SCRIPT_CC_H
|
||||
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "cryptoconditions/include/cryptoconditions.h"
|
||||
|
||||
|
||||
extern uint32_t ASSETCHAINS_CC;
|
||||
bool IsCryptoConditionsEnabled();
|
||||
|
||||
// Limit acceptable condition types
|
||||
// Prefix not enabled because no current use case, ambiguity on how to combine with secp256k1
|
||||
// RSA not enabled because no current use case, not implemented
|
||||
const int CCEnabledTypes = 1 << CC_Secp256k1 | \
|
||||
1 << CC_Threshold | \
|
||||
1 << CC_Eval | \
|
||||
1 << CC_Preimage | \
|
||||
1 << CC_Ed25519;
|
||||
|
||||
const int CCSigningNodes = 1 << CC_Ed25519 | 1 << CC_Secp256k1;
|
||||
|
||||
|
||||
/*
|
||||
* Check if the server can accept the condition based on it's structure / types
|
||||
*/
|
||||
bool IsSupportedCryptoCondition(const CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Check if crypto condition is signed. Can only accept signed conditions.
|
||||
*/
|
||||
bool IsSignedCryptoCondition(const CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Construct crypto conditions
|
||||
*/
|
||||
CC* CCNewPreimage(std::vector<unsigned char> preimage);
|
||||
CC* CCNewEval(std::vector<unsigned char> code);
|
||||
CC* CCNewSecp256k1(CPubKey k);
|
||||
CC* CCNewThreshold(int t, std::vector<CC*> v);
|
||||
|
||||
|
||||
/*
|
||||
* Turn a condition into a scriptPubKey
|
||||
*/
|
||||
CScript CCPubKey(const CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Turn a condition into a scriptSig
|
||||
*
|
||||
* Note: This will fail in undefined ways if the condition is missing signatures
|
||||
*/
|
||||
CScript CCSig(const CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Produces a string showing the structure of a CC condition
|
||||
*/
|
||||
std::string CCShowStructure(CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Take a signed CC, encode it, and decode it again. This has the effect
|
||||
* of removing branches unneccesary for fulfillment.
|
||||
*/
|
||||
CC* CCPrune(CC *cond);
|
||||
|
||||
|
||||
/*
|
||||
* Get PUSHDATA from a script
|
||||
*/
|
||||
bool GetPushData(const CScript &sig, std::vector<unsigned char> &data);
|
||||
|
||||
/*
|
||||
* Get OP_RETURN data from a script
|
||||
*/
|
||||
bool GetOpReturnData(const CScript &sig, std::vector<unsigned char> &data);
|
||||
|
||||
|
||||
#endif /* SCRIPT_CC_H */
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "uint256.h"
|
||||
#include "cryptoconditions/include/cryptoconditions.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -938,6 +940,37 @@ bool EvalScript(
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_CHECKCRYPTOCONDITION:
|
||||
case OP_CHECKCRYPTOCONDITIONVERIFY:
|
||||
{
|
||||
if (!IsCryptoConditionsEnabled()) {
|
||||
goto INTERPRETER_DEFAULT;
|
||||
}
|
||||
|
||||
if (stack.size() < 2)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
int fResult = checker.CheckCryptoCondition(stacktop(-1), stacktop(-2), script, consensusBranchId);
|
||||
if (fResult == -1) {
|
||||
return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT);
|
||||
}
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
|
||||
stack.push_back(fResult == 1 ? vchTrue : vchFalse);
|
||||
|
||||
if (opcode == OP_CHECKCRYPTOCONDITIONVERIFY)
|
||||
{
|
||||
if (fResult == 1)
|
||||
popstack(stack);
|
||||
else
|
||||
return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_VERIFY);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
INTERPRETER_DEFAULT:
|
||||
default:
|
||||
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
|
||||
}
|
||||
@@ -1253,6 +1286,49 @@ bool TransactionSignatureChecker::CheckSig(
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int TransactionSignatureChecker::CheckCryptoCondition(
|
||||
const std::vector<unsigned char>& condBin,
|
||||
const std::vector<unsigned char>& ffillBin,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const
|
||||
{
|
||||
// Hash type is one byte tacked on to the end of the fulfillment
|
||||
if (ffillBin.empty())
|
||||
return false;
|
||||
|
||||
CC *cond = cc_readFulfillmentBinary((unsigned char*)ffillBin.data(), ffillBin.size()-1);
|
||||
if (!cond) return -1;
|
||||
|
||||
if (!IsSupportedCryptoCondition(cond)) return 0;
|
||||
if (!IsSignedCryptoCondition(cond)) return 0;
|
||||
|
||||
uint256 sighash;
|
||||
int nHashType = ffillBin.back();
|
||||
try {
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId, this->txdata);
|
||||
} catch (logic_error ex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
VerifyEval eval = [] (CC *cond, void *checker) {
|
||||
return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond);
|
||||
};
|
||||
|
||||
int out = cc_verify(cond, (const unsigned char*)&sighash, 32, 0,
|
||||
condBin.data(), condBin.size(), eval, (void*)this);
|
||||
cc_free(cond);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int TransactionSignatureChecker::CheckEvalCondition(const CC *cond) const
|
||||
{
|
||||
fprintf(stderr, "Cannot check crypto-condition Eval outside of server\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
|
||||
{
|
||||
// There are two times of nLockTime: lock-by-blockheight
|
||||
@@ -1296,6 +1372,37 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allow larger opcode in case of crypto condition scriptSig
|
||||
*/
|
||||
bool EvalCryptoConditionSig(
|
||||
vector<vector<unsigned char> >& stack,
|
||||
const CScript& scriptSig,
|
||||
ScriptError* serror)
|
||||
{
|
||||
CScript::const_iterator pc = scriptSig.begin();
|
||||
opcodetype opcode;
|
||||
valtype vchPushValue;
|
||||
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
|
||||
|
||||
if (!scriptSig.GetOp(pc, opcode, vchPushValue))
|
||||
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
|
||||
|
||||
if (opcode == 0 || opcode > OP_PUSHDATA4)
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
if (pc != scriptSig.end())
|
||||
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
|
||||
|
||||
if (vchPushValue.size() > MAX_SCRIPT_CRYPTOCONDITION_FULFILLMENT_SIZE)
|
||||
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
|
||||
|
||||
stack.push_back(vchPushValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool VerifyScript(
|
||||
const CScript& scriptSig,
|
||||
const CScript& scriptPubKey,
|
||||
@@ -1311,7 +1418,12 @@ bool VerifyScript(
|
||||
}
|
||||
|
||||
vector<vector<unsigned char> > stack, stackCopy;
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, consensusBranchId, serror))
|
||||
if (IsCryptoConditionsEnabled() && scriptPubKey.IsPayToCryptoCondition()) {
|
||||
if (!EvalCryptoConditionSig(stack, scriptSig, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
}
|
||||
else if (!EvalScript(stack, scriptSig, flags, checker, consensusBranchId, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (flags & SCRIPT_VERIFY_P2SH)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "script_error.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "script/cc.h"
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
@@ -127,18 +128,26 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int CheckCryptoCondition(
|
||||
const std::vector<unsigned char>& condBin,
|
||||
const std::vector<unsigned char>& ffillBin,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ~BaseSignatureChecker() {}
|
||||
};
|
||||
|
||||
class TransactionSignatureChecker : public BaseSignatureChecker
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
const CTransaction* txTo;
|
||||
unsigned int nIn;
|
||||
const CAmount amount;
|
||||
const PrecomputedTransactionData* txdata;
|
||||
|
||||
protected:
|
||||
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
|
||||
public:
|
||||
@@ -146,6 +155,12 @@ public:
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
bool CheckLockTime(const CScriptNum& nLockTime) const;
|
||||
int CheckCryptoCondition(
|
||||
const std::vector<unsigned char>& condBin,
|
||||
const std::vector<unsigned char>& ffillBin,
|
||||
const CScript& scriptCode,
|
||||
uint32_t consensusBranchId) const;
|
||||
virtual int CheckEvalCondition(const CC *cond) const;
|
||||
};
|
||||
|
||||
class MutableTransactionSignatureChecker : public TransactionSignatureChecker
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "tinyformat.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "script/cc.h"
|
||||
#include "cryptoconditions/include/cryptoconditions.h"
|
||||
|
||||
namespace {
|
||||
inline std::string ValueString(const std::vector<unsigned char>& vch)
|
||||
@@ -138,6 +140,9 @@ const char* GetOpName(opcodetype opcode)
|
||||
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
|
||||
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
|
||||
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
|
||||
case OP_CHECKCRYPTOCONDITION : return "OP_CHECKCRYPTOCONDITION";
|
||||
case OP_CHECKCRYPTOCONDITIONVERIFY
|
||||
: return "OP_CHECKCRYPTOCONDITIONVERIFY";
|
||||
|
||||
// expansion
|
||||
case OP_NOP1 : return "OP_NOP1";
|
||||
@@ -211,6 +216,17 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
|
||||
return subscript.GetSigOpCount(true);
|
||||
}
|
||||
|
||||
bool CScript::IsPayToPublicKeyHash() const
|
||||
{
|
||||
// Extra-fast test for pay-to-pubkey-hash CScripts:
|
||||
return (this->size() == 25 &&
|
||||
(*this)[0] == OP_DUP &&
|
||||
(*this)[1] == OP_HASH160 &&
|
||||
(*this)[2] == 0x14 &&
|
||||
(*this)[23] == OP_EQUALVERIFY &&
|
||||
(*this)[24] == OP_CHECKSIG);
|
||||
}
|
||||
|
||||
bool CScript::IsPayToScriptHash() const
|
||||
{
|
||||
// Extra-fast test for pay-to-script-hash CScripts:
|
||||
@@ -220,6 +236,36 @@ bool CScript::IsPayToScriptHash() const
|
||||
this->at(22) == OP_EQUAL);
|
||||
}
|
||||
|
||||
bool CScript::IsPayToCryptoCondition() const
|
||||
{
|
||||
const_iterator pc = this->begin();
|
||||
vector<unsigned char> data;
|
||||
opcodetype opcode;
|
||||
if (this->GetOp(pc, opcode, data))
|
||||
// Sha256 conditions are <76 bytes
|
||||
if (opcode > OP_0 && opcode < OP_PUSHDATA1)
|
||||
if (this->GetOp(pc, opcode, data))
|
||||
if (opcode == OP_CHECKCRYPTOCONDITION)
|
||||
if (pc == this->end())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CScript::MayAcceptCryptoCondition() const
|
||||
{
|
||||
// Get the type mask of the condition
|
||||
const_iterator pc = this->begin();
|
||||
vector<unsigned char> data;
|
||||
opcodetype opcode;
|
||||
if (!this->GetOp(pc, opcode, data)) return false;
|
||||
if (!(opcode > OP_0 && opcode < OP_PUSHDATA1)) return false;
|
||||
CC *cond = cc_readConditionBinary(data.data(), data.size());
|
||||
if (!cond) return false;
|
||||
bool out = IsSupportedCryptoCondition(cond);
|
||||
cc_free(cond);
|
||||
return out;
|
||||
}
|
||||
|
||||
bool CScript::IsPushOnly() const
|
||||
{
|
||||
const_iterator pc = begin();
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
||||
|
||||
// Max size of pushdata in a CC sig in bytes
|
||||
static const unsigned int MAX_SCRIPT_CRYPTOCONDITION_FULFILLMENT_SIZE = 2048;
|
||||
|
||||
// Maximum script length in bytes
|
||||
static const int MAX_SCRIPT_SIZE = 10000;
|
||||
|
||||
@@ -154,6 +157,8 @@ enum opcodetype
|
||||
OP_CHECKSIGVERIFY = 0xad,
|
||||
OP_CHECKMULTISIG = 0xae,
|
||||
OP_CHECKMULTISIGVERIFY = 0xaf,
|
||||
OP_CHECKCRYPTOCONDITION = 0xcc,
|
||||
OP_CHECKCRYPTOCONDITIONVERIFY = 0xcd,
|
||||
|
||||
// expansion
|
||||
OP_NOP1 = 0xb0,
|
||||
@@ -168,13 +173,13 @@ enum opcodetype
|
||||
OP_NOP9 = 0xb8,
|
||||
OP_NOP10 = 0xb9,
|
||||
|
||||
|
||||
// template matching params
|
||||
OP_SMALLDATA = 0xf9,
|
||||
OP_SMALLINTEGER = 0xfa,
|
||||
OP_PUBKEYS = 0xfb,
|
||||
OP_PUBKEYHASH = 0xfd,
|
||||
OP_PUBKEY = 0xfe,
|
||||
OP_CRYPTOCONDITION = 0xfc,
|
||||
|
||||
OP_INVALIDOPCODE = 0xff,
|
||||
};
|
||||
@@ -561,7 +566,11 @@ public:
|
||||
*/
|
||||
unsigned int GetSigOpCount(const CScript& scriptSig) const;
|
||||
|
||||
bool IsPayToPublicKeyHash() const;
|
||||
|
||||
bool IsPayToScriptHash() const;
|
||||
bool IsPayToCryptoCondition() const;
|
||||
bool MayAcceptCryptoCondition() const;
|
||||
|
||||
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
|
||||
bool IsPushOnly() const;
|
||||
|
||||
@@ -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_CRYPTOCONDITION_INVALID_FULFILLMENT:
|
||||
return "Crypto-Condition payload is invalid";
|
||||
case SCRIPT_ERR_UNKNOWN_ERROR:
|
||||
case SCRIPT_ERR_ERROR_COUNT:
|
||||
default: break;
|
||||
|
||||
@@ -52,7 +52,11 @@ typedef enum ScriptError_t
|
||||
/* softfork safeness */
|
||||
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS,
|
||||
|
||||
SCRIPT_ERR_ERROR_COUNT
|
||||
SCRIPT_ERR_ERROR_COUNT,
|
||||
|
||||
/* crypto-condition script errors */
|
||||
SCRIPT_ERR_CRYPTOCONDITION_VERIFY,
|
||||
SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT
|
||||
} ScriptError;
|
||||
|
||||
#define SCRIPT_ERR_LAST SCRIPT_ERR_ERROR_COUNT
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "sigcache.h"
|
||||
#include "serverchecker.h"
|
||||
#include "script/cc.h"
|
||||
#include "cc/eval.h"
|
||||
|
||||
#include "pubkey.h"
|
||||
#include "random.h"
|
||||
@@ -26,13 +28,13 @@ private:
|
||||
//! sigdata_type is (signature hash, signature, public key):
|
||||
typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
|
||||
std::set< sigdata_type> setValid;
|
||||
boost::shared_mutex cs_sigcache;
|
||||
boost::shared_mutex cs_serverchecker;
|
||||
|
||||
public:
|
||||
bool
|
||||
Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
|
||||
boost::shared_lock<boost::shared_mutex> lock(cs_serverchecker);
|
||||
|
||||
sigdata_type k(hash, vchSig, pubKey);
|
||||
std::set<sigdata_type>::iterator mi = setValid.find(k);
|
||||
@@ -47,10 +49,10 @@ public:
|
||||
// (~200 bytes per cache entry times 50,000 entries)
|
||||
// Since there can be no more than 20,000 signature operations per block
|
||||
// 50,000 is a reasonable default.
|
||||
int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
|
||||
int64_t nMaxCacheSize = GetArg("-maxservercheckersize", 50000);
|
||||
if (nMaxCacheSize <= 0) return;
|
||||
|
||||
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
|
||||
boost::unique_lock<boost::shared_mutex> lock(cs_serverchecker);
|
||||
|
||||
while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize)
|
||||
{
|
||||
@@ -74,7 +76,7 @@ public:
|
||||
|
||||
}
|
||||
|
||||
bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
|
||||
bool ServerTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
|
||||
{
|
||||
static CSignatureCache signatureCache;
|
||||
|
||||
@@ -88,3 +90,17 @@ bool CachingTransactionSignatureChecker::VerifySignature(const std::vector<unsig
|
||||
signatureCache.Set(sighash, vchSig, pubkey);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The reason that these functions are here is that the what used to be the
|
||||
* CachingTransactionSignatureChecker, now the ServerTransactionSignatureChecker,
|
||||
* is an entry point that the server uses to validate signatures and which is not
|
||||
* included as part of bitcoin common libs. Since Crypto-Condtions eval methods
|
||||
* may call server code (GetTransaction etc), the best way to get it to run this
|
||||
* code without pulling the whole bitcoin server code into bitcoin common was
|
||||
* using this class. Thus it has been renamed to ServerTransactionSignatureChecker.
|
||||
*/
|
||||
int ServerTransactionSignatureChecker::CheckEvalCondition(const CC *cond) const
|
||||
{
|
||||
return RunCCEval(cond, *txTo, nIn);
|
||||
}
|
||||
27
src/script/serverchecker.h
Normal file
27
src/script/serverchecker.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_SCRIPT_SERVERCHECKER_H
|
||||
#define BITCOIN_SCRIPT_SERVERCHECKER_H
|
||||
|
||||
#include "script/interpreter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class CPubKey;
|
||||
|
||||
class ServerTransactionSignatureChecker : public TransactionSignatureChecker
|
||||
{
|
||||
private:
|
||||
bool store;
|
||||
|
||||
public:
|
||||
ServerTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nIn, amount, txdataIn), store(storeIn) {}
|
||||
|
||||
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
int CheckEvalCondition(const CC *cond) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_SCRIPT_SERVERCHECKER_H
|
||||
@@ -1,26 +0,0 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_SCRIPT_SIGCACHE_H
|
||||
#define BITCOIN_SCRIPT_SIGCACHE_H
|
||||
|
||||
#include "script/interpreter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class CPubKey;
|
||||
|
||||
class CachingTransactionSignatureChecker : public TransactionSignatureChecker
|
||||
{
|
||||
private:
|
||||
bool store;
|
||||
|
||||
public:
|
||||
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, txdataIn), store(storeIn) {}
|
||||
|
||||
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_SCRIPT_SIGCACHE_H
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "script/script.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "script/cc.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
@@ -68,6 +69,17 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsCryptoConditionsEnabled()) {
|
||||
// Shortcut for pay-to-crypto-condition
|
||||
if (scriptPubKey.IsPayToCryptoCondition()) {
|
||||
if (scriptPubKey.MayAcceptCryptoCondition()) {
|
||||
typeRet = TX_CRYPTOCONDITION;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan templates
|
||||
const CScript& script1 = scriptPubKey;
|
||||
BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
|
||||
@@ -179,6 +191,8 @@ int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned c
|
||||
return vSolutions[0][0] + 1;
|
||||
case TX_SCRIPTHASH:
|
||||
return 1; // doesn't include args needed by the script
|
||||
case TX_CRYPTOCONDITION:
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ enum txnouttype
|
||||
TX_PUBKEYHASH,
|
||||
TX_SCRIPTHASH,
|
||||
TX_MULTISIG,
|
||||
TX_CRYPTOCONDITION,
|
||||
TX_NULL_DATA,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user