Merge all Komodo changes, including proof of stake, crypto conditions, passport, etc.

This commit is contained in:
miketout
2018-05-02 03:24:21 -07:00
483 changed files with 62307 additions and 3553 deletions

137
src/script/cc.cpp Normal file
View 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
View 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 */

View File

@@ -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)

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}

View 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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -64,6 +64,7 @@ enum txnouttype
TX_PUBKEYHASH,
TX_SCRIPTHASH,
TX_MULTISIG,
TX_CRYPTOCONDITION,
TX_NULL_DATA,
};