From 46d1bcc607ee5b795ed72351b24f978ab6952633 Mon Sep 17 00:00:00 2001 From: Scott Sadler Date: Thu, 22 Feb 2018 01:43:43 -0300 Subject: [PATCH] integration test for complex aux condition --- qa/cryptoconditions/test_integration.py | 44 +++++++++++++++++++++++++ src/komodo_cryptoconditions.cpp | 13 +++++++- src/script/interpreter.cpp | 2 +- src/script/interpreter.h | 7 +--- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/qa/cryptoconditions/test_integration.py b/qa/cryptoconditions/test_integration.py index d5b456953..6d60ee921 100644 --- a/qa/cryptoconditions/test_integration.py +++ b/qa/cryptoconditions/test_integration.py @@ -127,6 +127,50 @@ def test_aux_basic(inp): assert 'Script evaluated without error but finished with a false/empty top stack element' in str(e), str(e) +@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 evaluated without error but finished with a false/empty top stack element' in str(e), str(e) + + if __name__ == '__main__': logging.basicConfig(level=logging.INFO) for name, f in globals().items(): diff --git a/src/komodo_cryptoconditions.cpp b/src/komodo_cryptoconditions.cpp index 9617add50..c807df7c9 100644 --- a/src/komodo_cryptoconditions.cpp +++ b/src/komodo_cryptoconditions.cpp @@ -3,11 +3,22 @@ #include "script/interpreter.h" -int CryptoConditionChecker::CheckAuxCondition(const CC *cond) const { +int TransactionSignatureChecker::CheckAuxCondition(const CC *cond) const { + + // 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)); } + + // 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; + } printf("no defined behaviour for method:%s\n", cond->method); return 0; } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 689dcf204..709b566f6 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1158,7 +1158,7 @@ extern "C" } static int komodoCCAux(CC *cond, void *checker) { - return ((CryptoConditionChecker*)checker)->CheckAuxCondition(cond); + return ((TransactionSignatureChecker*)checker)->CheckAuxCondition(cond); } bool TransactionSignatureChecker::CheckCryptoCondition(const CC *cond, const std::vector& condBin, const CScript& scriptCode) const diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 90c50eff6..8936fde7a 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -125,6 +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; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker @@ -139,10 +140,4 @@ public: bool EvalScript(std::vector >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL); -class CryptoConditionChecker : public TransactionSignatureChecker -{ -public: - int CheckAuxCondition(const CC *cond) const; -}; - #endif // BITCOIN_SCRIPT_INTERPRETER_H