diff --git a/src/Makefile.am b/src/Makefile.am index 89ee8ec74..affa61fc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,7 +43,7 @@ LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la -LIBCRYPTOCONDITIONS=cryptoconditions/cryptoconditions_core.a +LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a -lcurl @@ -135,6 +135,7 @@ BITCOIN_CORE_H = \ asyncrpcqueue.h \ base58.h \ bloom.h \ + cc/eval.h \ chain.h \ chainparams.h \ chainparamsbase.h \ @@ -162,7 +163,7 @@ BITCOIN_CORE_H = \ init.h \ key.h \ keystore.h \ - komodo_cryptoconditions.h \ + komodo_cc.h \ leveldbwrapper.h \ limitedmap.h \ main.h \ @@ -191,7 +192,7 @@ BITCOIN_CORE_H = \ script/interpreter.h \ script/script.h \ script/script_error.h \ - script/sigcache.h \ + script/serverchecker.h \ script/sign.h \ script/standard.h \ serialize.h \ @@ -249,13 +250,14 @@ libbitcoin_server_a_SOURCES = \ asyncrpcoperation.cpp \ asyncrpcqueue.cpp \ bloom.cpp \ + cc/eval.cpp \ + cc/importpayout.cpp \ chain.cpp \ checkpoints.cpp \ deprecation.cpp \ httprpc.cpp \ httpserver.cpp \ init.cpp \ - komodo_cryptoconditions.cpp \ leveldbwrapper.cpp \ main.cpp \ merkleblock.cpp \ @@ -274,7 +276,7 @@ libbitcoin_server_a_SOURCES = \ rpcnet.cpp \ rpcrawtransaction.cpp \ rpcserver.cpp \ - script/sigcache.cpp \ + script/serverchecker.cpp \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ @@ -378,7 +380,6 @@ libbitcoin_common_a_SOURCES = \ hash.cpp \ key.cpp \ keystore.cpp \ - komodo_cryptoconditions.cpp \ netbase.cpp \ primitives/block.cpp \ primitives/transaction.cpp \ diff --git a/src/Makefile.zcash.include b/src/Makefile.zcash.include index 177931c88..e6730623a 100644 --- a/src/Makefile.zcash.include +++ b/src/Makefile.zcash.include @@ -25,4 +25,6 @@ zcash_CreateJoinSplit_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) \ $(BOOST_LIBS) \ - $(LIBZCASH_LIBS) + $(LIBZCASH_LIBS) \ + $(LIBCRYPTOCONDITIONS) \ + $(LIBSECP256K1) diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp new file mode 100644 index 000000000..0291d1e3f --- /dev/null +++ b/src/cc/eval.cpp @@ -0,0 +1,23 @@ +#include "primitives/transaction.h" +#include "komodo_cc.h" +#include "cc/eval.h" +#include + + +/* + * Test the validity of an Eval node + */ +bool EvalConditionValidity(const CC *cond, const CTransaction *txTo, int nIn) +{ + if (strcmp(cond->method, "testEval") == 0) { + return cond->paramsBinLength == 8 && + memcmp(cond->paramsBin, "testEval", 8) == 0; + } + + if (strcmp(cond->method, "ImportPayout") == 0) { + return CheckImportPayout(cond, txTo, nIn); + } + + fprintf(stderr, "no defined behaviour for method: %s\n", cond->method); + return 0; +} diff --git a/src/cc/eval.h b/src/cc/eval.h new file mode 100644 index 000000000..8aa797f99 --- /dev/null +++ b/src/cc/eval.h @@ -0,0 +1,18 @@ +#ifndef CC_EVAL_H +#define CC_EVAL_H + +#include "cryptoconditions/include/cryptoconditions.h" +#include "primitives/transaction.h" + +/* + * Test validity of a CC_Eval node + */ +bool EvalConditionValidity(const CC *cond, const CTransaction *tx, int nIn); + +/* + * Test an ImportPayout CC Eval condition + */ +bool CheckImportPayout(const CC *cond, const CTransaction *payoutTx, int nIn); + + +#endif /* CC_EVAL_H */ diff --git a/src/cc/importpayout.cpp b/src/cc/importpayout.cpp new file mode 100644 index 000000000..d0a8c2fb0 --- /dev/null +++ b/src/cc/importpayout.cpp @@ -0,0 +1,191 @@ +#include "primitives/transaction.h" +#include "streams.h" +#include "chain.h" +#include "main.h" +#include "cryptoconditions/include/cryptoconditions.h" + + +bool GetPushData(const CScript &sig, std::vector &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 &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; +} + + +class MomProof +{ +public: + uint256 notaryHash; + int nPos; // Position of imported tx in MoM + std::vector branch; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(notaryHash); + READWRITE(VARINT(nPos)); + READWRITE(branch); + } +}; + + +extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); + +bool DerefNotaryPubkey(const COutPoint &prevout, char *pk33) +{ + CTransaction tx; + uint256 hashBlock; + if (!GetTransaction(prevout.hash, tx, hashBlock, false)) return false; + if (tx.vout.size() < prevout.n) return false; + const unsigned char *script = tx.vout[prevout.n].scriptPubKey.data(); + if (script[0] != 33) return false; + memcpy(pk33, script+1, 33); + return true; +} + +bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) +{ + if (tx.vin.size() < 11) return false; + + uint8_t notaries[64][33]; + uint8_t seenNotaries[64]; + int nNotaries = komodo_notaries(notaries, height, timestamp); + char *pk; + + BOOST_FOREACH(const CTxIn &txIn, tx.vin) + { + if (!DerefNotaryPubkey(txIn.prevout, pk)) return false; + + for (int i=0; inHeight, blockindex->nTime)) { + return false; + } + if (!notarisationTx.vout.size() < 1) return 0; + std::vector opret; + if (!GetOpReturnData(notarisationTx.vout[0].scriptPubKey, opret)) return 0; + if (opret.size() < 36) return 0; // In reality it is more than 36, but at the moment I + // only know where it is relative to the end, and this + // is enough to prevent a memory fault. In the case that + // the assumption about the presence of a MoM at this + // offset fails, we will return random other data that is + // not more likely to generate a false positive. + memcpy(mom.begin(), opret.data()+opret.size()-36, 32); + return 1; +} + + +uint256 ExecMerkle(uint256 hash, const std::vector& vMerkleBranch, int nIndex) +{ + return CBlock::CheckMerkleBranch(hash, vMerkleBranch, nIndex); +} + + +/* + * Crypto-Condition EVAL method that verifies a payout against a transaction + * notarised on another chain. + * + * IN: cond - CC EVAL node + * IN: payoutTx - Payout transaction on value chain (KMD) + * IN: nIn - index of input of stake + * + * payoutTx: Spends stakeTx with payouts from asset chain + * + * in 0: Spends Stake TX and contains ImportPayout CC + * out 0: OP_RETURN MomProof + * out 1: OP_RETURN serialized exportTx from other chain + * out 2-: arbitrary payouts + * + * exportTx: Spends sessionTx.0 (opener on asset chain) + * + * in 0: spends sessionTx.0 + * in 1-: anything + * out 0: OP_RETURN hash of payouts + * out 1-: anything + */ +bool CheckImportPayout(const CC *cond, const CTransaction *payoutTx, int nIn) +{ + // TODO: Error messages! + if (payoutTx->vin.size() != 1) return 0; + if (payoutTx->vout.size() < 2) return 0; + + // Get hash of payouts + std::vector payouts(payoutTx->vout.begin() + 2, payoutTx->vout.end()); + uint256 payoutsHash = SerializeHash(payouts); + std::vector vPayoutsHash(payoutsHash.begin(), payoutsHash.end()); + + // load exportTx from vout[1] + CTransaction exportTx; + { + std::vector exportData; + if (!GetOpReturnData(payoutTx->vout[1].scriptPubKey, exportData)) return 0; + CDataStream(exportData, SER_DISK, PROTOCOL_VERSION) >> exportTx; + // TODO: end of stream? exception? + } + + // Check exportTx.0 is vPayoutsHash + std::vector exportPayoutsHash; + if (!GetOpReturnData(exportTx.vout[0].scriptPubKey, exportPayoutsHash)) return 0; + if (exportPayoutsHash != vPayoutsHash) return 0; + + // Check exportTx spends sessionTx.0 + // condition ImportPayout params is session ID from other chain + { + if (cond->paramsBinLength != 32) return 0; + COutPoint prevout = exportTx.vin[0].prevout; + if (memcmp(prevout.hash.begin(), cond->paramsBin, 32) != 0 || + prevout.n != 0) return 0; + } + + // Check exportTx solves momproof from vout[0] + { + std::vector vchMomProof; + if (!GetOpReturnData(payoutTx->vout[0].scriptPubKey, vchMomProof)) return 0; + + MomProof momProof; + CDataStream(vchMomProof, SER_DISK, PROTOCOL_VERSION) >> momProof; + + uint256 mom; + if (!GetMoM(momProof.notaryHash, mom)) return 0; + + uint256 proofResult = ExecMerkle(exportTx.GetHash(), momProof.branch, momProof.nPos); + if (proofResult != mom) return 0; + } + + return 1; +} diff --git a/src/cryptoconditions/Makefile.am b/src/cryptoconditions/Makefile.am index 9469acdbf..eed285064 100644 --- a/src/cryptoconditions/Makefile.am +++ b/src/cryptoconditions/Makefile.am @@ -2,6 +2,8 @@ lib_LTLIBRARIES=libcryptoconditions.la noinst_LTLIBRARIES=$(CRYPTOCONDITIONS_CORE) SUBDIRS = src/include/secp256k1 +include_HEADERS = include/cryptoconditions.h + # Have a separate build target for cryptoconditions that does not contain secp256k1 libcryptoconditions_la_SOURCES = include/cryptoconditions.h diff --git a/src/cryptoconditions/include/cryptoconditions.h b/src/cryptoconditions/include/cryptoconditions.h index c434a486b..88a3a6560 100644 --- a/src/cryptoconditions/include/cryptoconditions.h +++ b/src/cryptoconditions/include/cryptoconditions.h @@ -84,9 +84,9 @@ unsigned char* cc_conditionUri(const CC *cond); unsigned char* cc_jsonRPC(unsigned char *request); unsigned long cc_getCost(const CC *cond); enum CCTypeId cc_typeId(const CC *cond); +uint32_t cc_typeMask(const CC *cond); void cc_free(struct CC *cond); - #ifdef __cplusplus } #endif diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 147cbb334..805c66236 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -42,8 +42,8 @@ void appendUriSubtypes(uint32_t mask, unsigned char *buf) { } else { strcat(buf, "&subtypes="); strcat(buf, typeRegistry[i]->name); + append = 1; } - append = 1; } } } @@ -70,7 +70,7 @@ unsigned char *cc_conditionUri(const CC *cond) { } -static uint32_t getSubtypes(CC *cond) { +uint32_t cc_typeMask(const CC *cond) { uint32_t mask = 1 << cond->type->typeId; if (cond->type->hasSubtypes) { mask |= cond->type->getSubtypes(cond); diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index bd0e6376a..bfcc6bd14 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -49,7 +49,6 @@ static CC *mkAnon(const Condition_t *asnCond); static void asnCondition(const CC *cond, Condition_t *asn); static Condition_t *asnConditionNew(const CC *cond); static Fulfillment_t *asnFulfillmentNew(const CC *cond); -static uint32_t getSubtypes(CC *cond); static cJSON *jsonEncodeCondition(cJSON *params, unsigned char *err); static struct CC *fulfillmentToCC(Fulfillment_t *ffill); static struct CCType *getTypeByAsnEnum(Condition_PR present); diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index 8fdd0a483..527115709 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -71,7 +71,7 @@ static Fulfillment_t *prefixToFulfillment(const CC *cond) { static uint32_t prefixSubtypes(const CC *cond) { - return getSubtypes(cond->subcondition) & ~(1 << cc_prefixType.typeId); + return cc_typeMask(cond->subcondition) & ~(1 << cc_prefixType.typeId); } diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index 895e91b32..be8fbd761 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -98,7 +98,7 @@ int secp256k1Verify(CC *cond, CCVisitor visitor) { static int cc_secp256k1VerifyTreeMsg32(const CC *cond, const unsigned char *msg32) { - int subtypes = getSubtypes(cond); + int subtypes = cc_typeMask(cond); if (subtypes & (1 << cc_prefixType.typeId) && subtypes & (1 << cc_secp256k1Type.typeId)) { // No support for prefix currently, due to pending protocol decision on @@ -148,7 +148,7 @@ static int secp256k1Sign(CC *cond, CCVisitor visitor) { * Sign secp256k1 conditions in a tree */ int cc_signTreeSecp256k1Msg32(CC *cond, const unsigned char *privateKey, const unsigned char *msg32) { - if (getSubtypes(cond) & (1 << cc_preimageType.typeId)) { + if (cc_typeMask(cond) & (1 << cc_preimageType.typeId)) { // No support for prefix currently, due to pending protocol decision on // how to combine message and prefix into 32 byte hash return 0; diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 68f4c557d..d3f4d3e63 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -14,7 +14,7 @@ struct CCType cc_thresholdType; static uint32_t thresholdSubtypes(const CC *cond) { uint32_t mask = 0; for (int i=0; isize; i++) { - mask |= getSubtypes(cond->subconditions[i]); + mask |= cc_typeMask(cond->subconditions[i]); } mask &= ~(1 << cc_thresholdType.typeId); return mask; diff --git a/src/komodo_cc.h b/src/komodo_cc.h new file mode 100644 index 000000000..fe05d3fc0 --- /dev/null +++ b/src/komodo_cc.h @@ -0,0 +1,40 @@ +#ifndef KOMODO_CC_H +#define KOMODO_CC_H + +#include "cryptoconditions/include/cryptoconditions.h" +#include "primitives/transaction.h" + + +/* + * Check if CryptoConditions is enabled based on chain or cmd flag + */ +extern int32_t ASSETCHAINS_CC; +static bool IsCryptoConditionsEnabled() +{ + return 0 != ASSETCHAINS_CC; +} + + +/* + * Check if the server can accept the condition based on it's structure / types + */ +static bool IsAcceptableCryptoCondition(const CC *cond) +{ + int32_t typeMask = cc_typeMask(cond); + + // Require a signature to prevent transaction malleability + if (0 == typeMask & (1 << CC_Secp256k1) || + 0 == typeMask & (1 << CC_Ed25519)) return false; + + // 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 + int enabledTypes = 1 << CC_Secp256k1 | 1 << CC_Threshold | 1 << CC_Eval | \ + 1 << CC_Preimage | 1 << CC_Ed25519; + if (typeMask & ~enabledTypes) return false; + + return true; +} + + +#endif /* KOMODO_CC_H */ diff --git a/src/komodo_cryptoconditions.cpp b/src/komodo_cryptoconditions.cpp deleted file mode 100644 index 4ebbebbeb..000000000 --- a/src/komodo_cryptoconditions.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "komodo_cryptoconditions.h" -#include "cryptoconditions/include/cryptoconditions.h" - - -/* - * Evaluate the validity of an Eval node - */ -bool EvalConditionValidity(const CC *cond, const CTransaction *txTo) -{ - if (strcmp(cond->method, "testEval") == 0) { - return cond->paramsBinLength == 8 && - memcmp(cond->paramsBin, "testEval", 8) == 0; - } - fprintf(stderr, "no defined behaviour for method: %s\n", cond->method); - return 0; -} - - -bool GetOpReturnData(const CScript &sig, std::vector &data) -{ - auto pc = sig.begin(); - opcodetype opcode; - if (sig.GetOp(pc, opcode)) - if (opcode == OP_RETURN) - if (sig.GetOp(pc, opcode, data)) - return opcode > OP_0 && opcode <= OP_PUSHDATA4; - return false; -} diff --git a/src/komodo_cryptoconditions.h b/src/komodo_cryptoconditions.h deleted file mode 100644 index 4edc2bedc..000000000 --- a/src/komodo_cryptoconditions.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef KOMODO_CRYPTOCONDITIONS_H -#define KOMODO_CRYPTOCONDITIONS_H - -#include "cryptoconditions/include/cryptoconditions.h" -#include "primitives/transaction.h" -#include "script/script.h" - - -extern int32_t ASSETCHAINS_CC; - -static bool IsCryptoConditionsEnabled() { - return 0 != ASSETCHAINS_CC; -} - -bool EvalConditionValidity(const CC *cond, const CTransaction *tx); - -bool GetOpReturnData(const CScript &sig, std::vector &data); - -#endif /* KOMODO_CRYPTOCONDITIONS_H */ diff --git a/src/main.cpp b/src/main.cpp index 151c42383..9fb8402d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1931,7 +1931,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, nFlags, ServerTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) { return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error)); } return true; diff --git a/src/main.h b/src/main.h index 14513b730..1c864de20 100644 --- a/src/main.h +++ b/src/main.h @@ -20,7 +20,7 @@ #include "primitives/block.h" #include "primitives/transaction.h" #include "script/script.h" -#include "script/sigcache.h" +#include "script/serverchecker.h" #include "script/standard.h" #include "sync.h" #include "tinyformat.h" diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 6ae466e65..20027ea41 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -13,7 +13,7 @@ #include "pubkey.h" #include "script/script.h" #include "uint256.h" -#include "komodo_cryptoconditions.h" +#include "cryptoconditions/include/cryptoconditions.h" using namespace std; @@ -1295,20 +1295,10 @@ bool TransactionSignatureChecker::CheckSig( } -bool TransactionSignatureChecker::CheckEvalCondition(const CC *cond) const -{ - return EvalConditionValidity(cond, txTo); -} - - -static int komodoCCEval(CC *cond, void *checker) -{ - return ((TransactionSignatureChecker*)checker)->CheckEvalCondition(cond); -} - - bool TransactionSignatureChecker::CheckCryptoCondition(const CC *cond, const std::vector& condBin, const CScript& scriptCode, uint32_t consensusBranchId) const { + if (!IsAcceptableCryptoCondition(cond)) return false; + uint256 sighash; try { sighash = SignatureHash(scriptCode, *txTo, nIn, SIGHASH_ALL, amount, consensusBranchId, this->txdata); @@ -1316,7 +1306,15 @@ bool TransactionSignatureChecker::CheckCryptoCondition(const CC *cond, const std return false; } return cc_verify(cond, (const unsigned char*)&sighash, 32, 0, - condBin.data(), condBin.size(), komodoCCEval, (void*)this); + condBin.data(), condBin.size(), GetCCEval(), (void*)this); +} + + +VerifyEval TransactionSignatureChecker::GetCCEval() const { + return [] (CC *cond, void *checker) { + fprintf(stderr, "Cannot check crypto-condition Eval outside of server\n"); + return 0; + }; } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 86d792e0a..86ab8dac3 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -8,7 +8,7 @@ #include "script_error.h" #include "primitives/transaction.h" -#include "komodo_cryptoconditions.h" +#include "komodo_cc.h" #include #include @@ -153,7 +153,7 @@ public: bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckCryptoCondition(const CC *cond, const std::vector& condBin, const CScript& scriptCode, uint32_t consensusBranchId) const; - bool CheckEvalCondition(const CC *cond) const; + VerifyEval GetCCEval() const; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker diff --git a/src/script/script.cpp b/src/script/script.cpp index a4446a0df..d885146a2 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -7,6 +7,8 @@ #include "tinyformat.h" #include "utilstrencodings.h" +#include "komodo_cc.h" +#include "cryptoconditions/include/cryptoconditions.h" namespace { inline std::string ValueString(const std::vector& vch) @@ -238,6 +240,20 @@ bool CScript::IsPayToCryptoCondition() const return 0; } +bool CScript::MayAcceptCryptoCondition() const +{ + // Get the type mask of the condition + const_iterator pc = this->begin(); + vector 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 accept = IsAcceptableCryptoCondition(cond); + return accept; +} + bool CScript::IsPushOnly() const { const_iterator pc = begin(); diff --git a/src/script/script.h b/src/script/script.h index 800289a15..b7442a419 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -565,6 +565,7 @@ public: bool IsPayToScriptHash() const; bool IsPayToCryptoCondition() const; + bool MayAcceptCryptoCondition() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ bool IsPushOnly() const; diff --git a/src/script/sigcache.cpp b/src/script/serverchecker.cpp similarity index 65% rename from src/script/sigcache.cpp rename to src/script/serverchecker.cpp index 35b9f0e03..852895305 100644 --- a/src/script/sigcache.cpp +++ b/src/script/serverchecker.cpp @@ -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 "komodo_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, 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& vchSig, const CPubKey& pubKey) { - boost::shared_lock lock(cs_sigcache); + boost::shared_lock lock(cs_serverchecker); sigdata_type k(hash, vchSig, pubKey); std::set::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 lock(cs_sigcache); + boost::unique_lock lock(cs_serverchecker); while (static_cast(setValid.size()) > nMaxCacheSize) { @@ -74,7 +76,7 @@ public: } -bool CachingTransactionSignatureChecker::VerifySignature(const std::vector& vchSig, const CPubKey& pubkey, const uint256& sighash) const +bool ServerTransactionSignatureChecker::VerifySignature(const std::vector& vchSig, const CPubKey& pubkey, const uint256& sighash) const { static CSignatureCache signatureCache; @@ -88,3 +90,24 @@ bool CachingTransactionSignatureChecker::VerifySignature(const std::vectorCheckEvalCondition(cond); + }; +} + +int ServerTransactionSignatureChecker::CheckEvalCondition(CC *cond) const +{ + return EvalConditionValidity(cond, txTo, nIn); +} diff --git a/src/script/serverchecker.h b/src/script/serverchecker.h new file mode 100644 index 000000000..c680da7ce --- /dev/null +++ b/src/script/serverchecker.h @@ -0,0 +1,30 @@ +// 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 + +class CPubKey; + +class ServerTransactionSignatureChecker : public TransactionSignatureChecker +{ +private: + bool store; + const CTransaction* txTo; + unsigned int nIn; + +public: + ServerTransactionSignatureChecker(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& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; + int CheckEvalCondition(CC *cond) const; + VerifyEval GetCCEval() const; +}; + +#endif // BITCOIN_SCRIPT_SERVERCHECKER_H diff --git a/src/script/sigcache.h b/src/script/sigcache.h deleted file mode 100644 index 134b72a2d..000000000 --- a/src/script/sigcache.h +++ /dev/null @@ -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 - -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& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; -}; - -#endif // BITCOIN_SCRIPT_SIGCACHE_H diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 60f059ac3..ee96581fe 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -9,7 +9,7 @@ #include "script/script.h" #include "util.h" #include "utilstrencodings.h" -#include "komodo_cryptoconditions.h" +#include "komodo_cc.h" #include @@ -72,9 +72,11 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector