diff --git a/qa/cryptoconditions/test_integration.py b/qa/cryptoconditions/test_integration.py index bd72b961d..1f6746b69 100644 --- a/qa/cryptoconditions/test_integration.py +++ b/qa/cryptoconditions/test_integration.py @@ -4,6 +4,7 @@ import json import logging import binascii import struct +import base64 from testsupport import * @@ -91,20 +92,19 @@ def test_oversize_fulfillment(inp): @fanout_input(6) -def test_aux_basic(inp): - aux_cond = { - 'type': 'aux-sha-256', - 'method': 'equals', - 'conditionAux': 'LTE', - 'fulfillmentAux': 'LTE' +def test_eval_basic(inp): + eval_cond = { + 'type': 'eval-sha-256', + 'method': 'testEval', + 'params': encode_base64('testEval') } - # Setup some aux outputs + # Setup some eval outputs spend0 = { 'inputs': [inp], 'outputs': [ - {'amount': 500, 'script': {'condition': aux_cond}}, - {'amount': 500, 'script': {'condition': aux_cond}} + {'amount': 500, 'script': {'condition': eval_cond}}, + {'amount': 500, 'script': {'condition': eval_cond}} ] } spend0_txid = submit(sign(spend0)) @@ -112,17 +112,17 @@ def test_aux_basic(inp): # Test a good fulfillment spend1 = { - 'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': aux_cond}}], - 'outputs': [{'amount': 500, 'script': {'condition': aux_cond}}] + 'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': eval_cond}}], + 'outputs': [{'amount': 500, 'script': {'condition': eval_cond}}] } spend1_txid = submit(sign(spend1)) assert rpc.getrawtransaction(spend1_txid) # Test a bad fulfillment - aux_cond['fulfillmentAux'] = 'WYW' + eval_cond['params'] = '' spend2 = { - 'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': aux_cond}}], - 'outputs': [{'amount': 500, 'script': {'condition': aux_cond}}] + 'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': eval_cond}}], + 'outputs': [{'amount': 500, 'script': {'condition': eval_cond}}] } try: assert not submit(sign(spend2)), 'should raise an error' @@ -131,50 +131,6 @@ def test_aux_basic(inp): @fanout_input(7) -def test_aux_complex(inp): - aux_cond = { - 'type': 'aux-sha-256', - 'method': 'inputIsReturn', - 'conditionAux': '', - 'fulfillmentAux': 'AQ' # \1 (tx.vout[1]) - } - - # Setup some aux outputs - spend0 = { - 'inputs': [inp], - 'outputs': [ - {'amount': 500, 'script': {'condition': aux_cond}}, - {'amount': 500, 'script': {'condition': aux_cond}} - ] - } - spend0_txid = submit(sign(spend0)) - assert rpc.getrawtransaction(spend0_txid) - - # Test a good fulfillment - spend1 = { - 'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': aux_cond}}], - 'outputs': [ - {'amount': 250, 'script': {'condition': aux_cond}}, - {'amount': 250, 'script': "6A0B68656C6C6F207468657265"} # OP_RETURN somedata - ] - } - spend1_txid = submit(sign(spend1)) - assert rpc.getrawtransaction(spend1_txid) - - # Test a bad fulfillment - spend2 = { - 'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': aux_cond}}], - 'outputs': [ - {'amount': 500, 'script': "6A0B68656C6C6F207468657265"} # OP_RETURN somedata - ] - } - try: - assert not submit(sign(spend2)), 'should raise an error' - except RPCError as e: - assert SCRIPT_FALSE in str(e), str(e) - - -@fanout_input(8) def test_secp256k1_condition(inp): ec_cond = { 'type': 'secp256k1-sha-256', @@ -214,6 +170,60 @@ def test_secp256k1_condition(inp): assert SCRIPT_FALSE in str(e), str(e) +@fanout_input(20) +def test_eval_replacement(inp): + eval_cond = { + 'type': 'eval-sha-256', + 'method': 'testReplace', + 'params': '', + } + + # Setup replaceable output + spend0 = { + 'inputs': [inp], + 'outputs': [ + {'amount': 1000, 'script': {'condition': eval_cond}}, + ] + } + spend0_txid = submit(sign(spend0)) + assert rpc.getrawtransaction(spend0_txid) + + b64_1 = 'AQ==' + spend1 = { + 'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': eval_cond}}], + 'outputs': [{'amount': 1000, 'script': {'op_return': b64_1}}] + } + + b64_2 = 'Ag==' + spend2 = { + 'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': eval_cond}}], + 'outputs': [{'amount': 1000, 'script': {'op_return': b64_2}}] + } + + # If spend2 is already registered, return true, as this test has already been performed + spend2_txid = hoek.encodeTx(sign(spend2))['txid'] + try: + rpc.getrawtransaction(spend2_txid) + return + except RPCError: + pass + + # Send replaceable + spend1_txid = submit(sign(spend1)) + assert rpc.getrawtransaction(spend1_txid) + + + # Send replacement (higher OP_RETURN data) + spend2_txid = submit(sign(spend2)) + assert rpc.getrawtransaction(spend2_txid) + + # Now the first transaction has gone + try: + assert not rpc.getrawtransaction(spend1_txid), "should raise an error" + except RPCError as e: + assert 'No information available about transaction' in str(e), str(e) + + if __name__ == '__main__': logging.basicConfig(level=logging.INFO) for name, f in globals().items(): diff --git a/qa/cryptoconditions/testsupport.py b/qa/cryptoconditions/testsupport.py index e22520f3f..a127379f6 100644 --- a/qa/cryptoconditions/testsupport.py +++ b/qa/cryptoconditions/testsupport.py @@ -97,7 +97,7 @@ def get_fanout_txid(): reward_tx = hoek.decodeTx({'hex': reward_tx_raw}) balance = reward_tx['outputs'][0]['amount'] - n_outs = 16 + n_outs = 40 remainder = balance - n_outs * 1000 fanout = { @@ -109,7 +109,9 @@ def get_fanout_txid(): ] + [{"amount": remainder, 'script': {'address': notary_addr}}]) } - return submit(sign(fanout)) + txid = submit(sign(fanout)) + rpc.getrawtransaction(txid) + return txid def fanout_input(n): diff --git a/src/Makefile.am b/src/Makefile.am index 4ec21614d..865960ec6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -137,6 +137,7 @@ BITCOIN_CORE_H = \ init.h \ key.h \ keystore.h \ + komodo_cryptoconditions.h \ leveldbwrapper.h \ limitedmap.h \ main.h \ @@ -155,6 +156,7 @@ BITCOIN_CORE_H = \ protocol.h \ pubkey.h \ random.h \ + replacementpool.h \ reverselock.h \ rpcclient.h \ rpcprotocol.h \ @@ -223,6 +225,7 @@ libbitcoin_server_a_SOURCES = \ httprpc.cpp \ httpserver.cpp \ init.cpp \ + komodo_cryptoconditions.cpp \ leveldbwrapper.cpp \ main.cpp \ merkleblock.cpp \ @@ -232,6 +235,7 @@ libbitcoin_server_a_SOURCES = \ noui.cpp \ policy/fees.cpp \ pow.cpp \ + replacementpool.cpp \ rest.cpp \ rpcblockchain.cpp \ rpcmining.cpp \ @@ -325,6 +329,7 @@ libbitcoin_common_a_SOURCES = \ hash.cpp \ key.cpp \ keystore.cpp \ + komodo_cryptoconditions.cpp \ netbase.cpp \ primitives/block.cpp \ primitives/transaction.cpp \ @@ -336,7 +341,6 @@ libbitcoin_common_a_SOURCES = \ script/script_error.cpp \ script/sign.cpp \ script/standard.cpp \ - komodo_cryptoconditions.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -506,7 +510,6 @@ libzcashconsensus_la_SOURCES = \ script/zcashconsensus.cpp \ script/interpreter.cpp \ script/script.cpp \ - komodo_cryptoconditions.cpp \ uint256.cpp \ utilstrencodings.cpp diff --git a/src/cryptoconditions b/src/cryptoconditions index 9ba2d4545..f606567ce 160000 --- a/src/cryptoconditions +++ b/src/cryptoconditions @@ -1 +1 @@ -Subproject commit 9ba2d454564c3bb31446a2a2d1db8cb992e6cbe0 +Subproject commit f606567ce30780c28880094718b5b27c5c426827 diff --git a/src/komodo_cryptoconditions.cpp b/src/komodo_cryptoconditions.cpp index 4c516b320..77e4c6c8a 100644 --- a/src/komodo_cryptoconditions.cpp +++ b/src/komodo_cryptoconditions.cpp @@ -1,24 +1,93 @@ +#include "replacementpool.h" +#include "komodo_cryptoconditions.h" #include "cryptoconditions/include/cryptoconditions.h" #include "script/interpreter.h" +#include "coins.h" -int TransactionSignatureChecker::CheckAuxCondition(const CC *cond) const +#define REPLACEMENT_WINDOW_BLOCKS 2 + + +bool GetOpReturnData(const CScript &sig, std::vector &data) { - // Check that condition is equal to fulfillment - if (0 == strcmp((const char*)cond->method, "equals")) { - return (cond->conditionAuxLength == cond->fulfillmentAuxLength) && - (0 == memcmp(cond->conditionAux, cond->fulfillmentAux, cond->conditionAuxLength)); - } + 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; +} - // Check that pubKeyScript specified in fulfillment is OP_RETURN - if (0 == strcmp((const char*)cond->method, "inputIsReturn")) { - if (cond->fulfillmentAuxLength != 1) return 0; - int n = (int) cond->fulfillmentAux[0]; - if (n >= txTo->vout.size()) return 0; - uint8_t *ptr = (uint8_t *)txTo->vout[n].scriptPubKey.data(); - return ptr[0] == OP_RETURN; + +bool EvalConditionBool(const CC *cond, const CTransaction *txTo) +{ + if (strcmp(cond->method, "testEval") == 0) { + return cond->paramsBinLength == 8 && + memcmp(cond->paramsBin, "testEval", 8) == 0; } - printf("no defined behaviour for method:%s\n", cond->method); + if (strcmp(cond->method, "testReplace") == 0) { + return true; + } + fprintf(stderr, "no defined behaviour for method: %s\n", cond->method); return 0; } + + +bool GetConditionPriority(const CC *cond, CTxReplacementPoolItem *rep) +{ + if (strcmp((const char*)cond->method, "testReplace") == 0) { + std::vector data; + if (GetOpReturnData(rep->tx.vout[0].scriptPubKey, data)) { + rep->priority = (uint64_t) data[0]; + rep->replacementWindow = REPLACEMENT_WINDOW_BLOCKS; + return true; + } + } + return false; +} + + +bool TransactionSignatureChecker::CheckEvalCondition(const CC *cond) const +{ + return EvalConditionBool(cond, txTo); +} + + +extern "C" +{ + int visitConditionPriority(CC *cond, struct CCVisitor visitor); +} + + +int visitConditionPriority(CC *cond, struct CCVisitor visitor) +{ + if (cc_typeId(cond) == CC_Eval) { + if (GetConditionPriority(cond, (CTxReplacementPoolItem*)visitor.context)) { + return 0; // stop + } + } + return 1; // continue +} + + +bool SetReplacementParams(CTxReplacementPoolItem &rep) +{ + // first, see if we have a cryptocondition + const CScript &sig = rep.tx.vin[0].scriptSig; + if (!sig.IsPushOnly()) return false; + CScript::const_iterator pc = sig.begin(); + std::vector data; + opcodetype opcode; + if (!sig.GetOp(pc, opcode, data)) return false; + CC *cond = cc_readFulfillmentBinary((unsigned char*)data.data(), data.size()); + if (!cond) return false; + + // now, see if it has a replacement node + CC *replacementNode = 0; + CCVisitor visitor = {&visitConditionPriority, (const unsigned char*)"", 0, &rep}; + bool out = cc_visit(cond, visitor); + cc_free(cond); + return !out; +} diff --git a/src/komodo_cryptoconditions.h b/src/komodo_cryptoconditions.h index 42cf3b077..406b2f100 100644 --- a/src/komodo_cryptoconditions.h +++ b/src/komodo_cryptoconditions.h @@ -1,12 +1,19 @@ #ifndef KOMODO_CRYPTOCONDITIONS_H #define KOMODO_CRYPTOCONDITIONS_H +#include "coins.h" +#include "replacementpool.h" #include "cryptoconditions/include/cryptoconditions.h" extern int32_t ASSETCHAINS_CC; +extern CTxReplacementPool replacementPool; + static bool IsCryptoConditionsEnabled() { return 0 != ASSETCHAINS_CC; } +bool EvalConditionBool(const CC *cond, const CTransaction *tx); +//uint64_t EvalConditionPriority(const CC *cond, const CTransaction *tx); +bool SetReplacementParams(CTxReplacementPoolItem &rep); #endif /* KOMODO_CRYPTOCONDITIONS_H */ diff --git a/src/main.cpp b/src/main.cpp index 72f25f1fc..2ff543b8c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,8 @@ #include "pow.h" #include "txdb.h" #include "txmempool.h" +#include "replacementpool.h" +#include "komodo_cryptoconditions.h" #include "ui_interface.h" #include "undo.h" #include "util.h" @@ -53,6 +55,7 @@ extern uint8_t NOTARY_PUBKEY33[33]; BlockMap mapBlockIndex; CChain chainActive; + CBlockIndex *pindexBestHeader = NULL; int64_t nTimeBestReceived = 0; CWaitableCriticalSection csBestBlock; @@ -1107,7 +1110,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF } -bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee) +bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, bool fAcceptReplacement) { AssertLockHeld(cs_main); if (pfMissingInputs) @@ -1178,6 +1181,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } + CTxReplacementPoolResult rpr = RP_NotReplace; + { CCoinsView dummy; CCoinsViewCache view(&dummy); @@ -1331,13 +1336,35 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString()); } - // Store transaction in memory if ( komodo_is_notarytx(tx) == 0 ) KOMODO_ON_DEMAND++; - pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); + + if (fAcceptReplacement) { + CTxReplacementPoolItem item(tx, GetHeight()); + if (SetReplacementParams(item)) { + rpr = replacementPool.replace(item); + } + } + + if (rpr == RP_Invalid) { + // already have a better one + // TODO: Shouldn't neccesary log this as invalid, not sure if punishing peers is the best idea + fprintf(stderr,"accept failure.20\n"); + return error("AcceptToMemoryPool: Replacement is worse %s", hash.ToString()); + } + + // If there is no replacement action happening... + if (rpr == RP_NotReplace) { + // Store transaction in memory + pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); + } } - SyncWithWallets(tx, NULL); + // in order for replaceable transactions to sync with wallet, replacementpool should advise + // wallet of transaction eviction + if (rpr == RP_NotReplace) { + SyncWithWallets(tx, NULL); + } return true; } @@ -1354,6 +1381,12 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock return true; } + // replacementPool lookup is O(n) since there's no index by txid + if (fAllowSlow && replacementPool.lookup(hash, txOut)) + { + return true; + } + if (fTxIndex) { CDiskTxPos postx; if (pblocktree->ReadTxIndex(hash, postx)) { @@ -1403,6 +1436,17 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock return false; } + +void ProcessReplacementPool(int newHeight) +{ + std::vector pending; + replacementPool.removePending(newHeight, pending); + CValidationState stateDummy; + BOOST_FOREACH(CTransaction tx, pending) { + AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, false, false); + } +} + /*char *komodo_getspendscript(uint256 hash,int32_t n) { CTransaction tx; uint256 hashBlock; @@ -2702,6 +2746,13 @@ bool static DisconnectTip(CValidationState &state) { // Update cached incremental witnesses //fprintf(stderr,"chaintip false\n"); GetMainSignals().ChainTip(pindexDelete, &block, newTree, false); + + /* if chain tip disconnects, some transactions may return to the replacementPool + * via AcceptToMemoryPool. + * + * No double send conflicts may result as the winning transaction will be picked. + */ + return true; } @@ -2761,6 +2812,8 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * mempool.check(pcoinsTip); // Update chainActive & related variables. UpdateTip(pindexNew); + // Process pending replacements + ProcessReplacementPool(pindexNew->nHeight-1); // Tell wallet about transactions that went from mempool // to conflicted: BOOST_FOREACH(const CTransaction &tx, txConflicted) { @@ -2770,6 +2823,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * BOOST_FOREACH(const CTransaction &tx, pblock->vtx) { SyncWithWallets(tx, pblock); } + // Update cached incremental witnesses //fprintf(stderr,"chaintip true\n"); GetMainSignals().ChainTip(pindexNew, pblock, oldTree, true); diff --git a/src/main.h b/src/main.h index bcdd04a5e..061dcfcc5 100644 --- a/src/main.h +++ b/src/main.h @@ -250,7 +250,7 @@ void PruneAndFlush(); /** (try to) add transaction to memory pool **/ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, - bool* pfMissingInputs, bool fRejectAbsurdFee=false); + bool* pfMissingInputs, bool fRejectAbsurdFee=false, bool fAcceptReplacement=true); struct CNodeStateStats { diff --git a/src/replacementpool.cpp b/src/replacementpool.cpp new file mode 100644 index 000000000..0a509ef37 --- /dev/null +++ b/src/replacementpool.cpp @@ -0,0 +1,96 @@ + +#include +#include +#include + +#include "main.h" +#include "coins.h" +#include "replacementpool.h" + + +CTxReplacementPool replacementPool; + + +/* + * Add a transaction to the pool, with a priority. + * Return true if valid, false if not valid. */ +bool ValidateReplacementPoolItem(CTxReplacementPoolItem item) +{ + // Perform some validations. + if (item.tx.vin.size() > 1) { + // Replaceable transactions with multiple inputs are disabled for now. It's not yet clear + // what edge cases may arise. It is speculated that it will "just work", since if + // replaceable transactions spend multiple outputs using the replacement protocol, + // they will never conflict in the replaceMap data structure. But for now, to be prudent, disable. + return false; + } + + // A transaction with 0 priority is not valid. + if (item.priority == 0) { + return false; + } + + return true; +} + + +/* + * Validate the item + * + * Compare the item with any current replacement candidate + * + * Ensure that the item is not passed the replacement window + * + * Insert the item into the map + */ +CTxReplacementPoolResult CTxReplacementPool::replace(CTxReplacementPoolItem &item) +{ + if (!ValidateReplacementPoolItem(item)) { + return RP_Invalid; + } + + auto it = replaceMap.find(item.tx.vin[0].prevout); + + if (it != replaceMap.end()) { + if (it->second.priority >= item.priority) { + // Already have a transaction with equal or greater priority; this is not valid + return RP_Invalid; + } + // copy the previous starting block over + item.startBlock = it->second.startBlock; + } + + // This transaction has higher priority + replaceMap[item.tx.vin[0].prevout] = item; + + return RP_Valid; +} + + +void CTxReplacementPool::removePending(int height, std::vector &txs) +{ + for (auto it = replaceMap.begin(); it != replaceMap.end(); /**/) { + CTxReplacementPoolItem &rep = it->second; + if (rep.GetTargetBlock() <= height) { + txs.push_back(rep.tx); + replaceMap.erase(it++); + } else { + ++it; + } + } +} + + +/* + * O(n) lookup of tx by hash + */ +bool CTxReplacementPool::lookup(uint256 txHash, CTransaction &tx) +{ + for (auto it = replaceMap.begin(); it != replaceMap.end(); it++) { + if (it->second.tx.GetHash() == txHash) { + tx = it->second.tx; + return true; + } + } + return false; +} diff --git a/src/replacementpool.h b/src/replacementpool.h new file mode 100644 index 000000000..71cb775fd --- /dev/null +++ b/src/replacementpool.h @@ -0,0 +1,68 @@ +// Copyright (c) 2018 The Komodo Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef KOMODO_REPLACEMENTCACHE_H +#define KOMODO_REPLACEMENTCACHE_H + +#include "coins.h" +#include "primitives/transaction.h" + + +enum CTxReplacementPoolResult { RP_NotReplace, RP_Valid, RP_Invalid }; + +class CTxReplacementPoolItem +{ +public: + CTransaction tx; + int startBlock; + uint64_t priority; + uint32_t replacementWindow; + + CTxReplacementPoolItem() {} + + CTxReplacementPoolItem(const CTransaction &_tx, int _startBlock) { + tx = _tx; + startBlock = _startBlock; + priority = 0; + replacementWindow = 0; + } + + int GetTargetBlock() + { + return startBlock + replacementWindow; + } +}; + +/** + * CTxReplacementPool stores valid-according-to-the-current-best-chain (??? do we need to do this?) + * transactions that are valid but held for period of time during which + * they may be replaced. + * + * Transactions are added when they are found to be valid but not added + * to the mempool until a timeout. + * + * Replacement pool is like another mempool before the main mempool. + */ +class CTxReplacementPool +{ +private: + // A potential replacement is first stored here, not in the replaceMap. + // This is in case some other checks fail, during AcceptToMemoryPool. + // Later on, if all checks pass, processReplacement() is called. + + /* Index of spends that may be replaced */ + std::map replaceMap; +public: + CTxReplacementPoolResult replace(CTxReplacementPoolItem &item); + + // Remove and return all transactions up to a given block height. + void removePending(int height, std::vector &txs); + + bool lookup(uint256 txHash, CTransaction &tx); +}; + + +extern CTxReplacementPool replacementPool; + +#endif // KOMODO_REPLACEMENTCACHE_H diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 91b22039e..09c09ced3 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1154,18 +1154,18 @@ bool TransactionSignatureChecker::CheckSig(const vector& vchSigIn extern "C" { - static int komodoCCAux(CC *cond, void *transactionSignatureChecker); + static int komodoCCEval(CC *cond, void *transactionSignatureChecker); } -static int komodoCCAux(CC *cond, void *checker) { - return ((TransactionSignatureChecker*)checker)->CheckAuxCondition(cond); +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) const { uint256 message = SignatureHash(scriptCode, *txTo, nIn, SIGHASH_ALL); return cc_verify(cond, (const unsigned char*)&message, 32, 0, - condBin.data(), condBin.size(), komodoCCAux, (void*)this); + condBin.data(), condBin.size(), komodoCCEval, (void*)this); } bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 8936fde7a..2cdeb8f8e 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -125,7 +125,7 @@ public: bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckCryptoCondition(const CC *cond, const std::vector& condBin, const CScript& scriptCode) const; - int CheckAuxCondition(const CC *cond) const; + bool CheckEvalCondition(const CC *cond) const; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker