From 07f83521f7f4dc21e895d3a2a60a1a40aa0ce2bb Mon Sep 17 00:00:00 2001 From: Scott Sadler Date: Thu, 19 Oct 2017 14:08:32 -0700 Subject: [PATCH] basic integration of cryptoconditions --- .gitmodules | 4 +++ configure.ac | 2 +- src/Makefile.am | 16 +++++++++--- src/cJSON.h | 1 + src/cryptoconditions | 1 + src/komodo_structs.h | 5 ++++ src/script/interpreter.cpp | 52 ++++++++++++++++++++++++++++++++++++++ src/script/interpreter.h | 7 +++++ src/script/script.cpp | 3 +++ src/script/script.h | 3 ++- src/script/script_error.h | 5 +++- 11 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 .gitmodules create mode 160000 src/cryptoconditions diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..44ceb9030 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "cryptoconditions"] + path = src/cryptoconditions + url = https://github.com/libscott/libcryptoconditions + branch = komodo-integration diff --git a/configure.ac b/configure.ac index c471bab89..9f8f1900f 100644 --- a/configure.ac +++ b/configure.ac @@ -996,7 +996,7 @@ unset PKG_CONFIG_LIBDIR PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no" -AC_CONFIG_SUBDIRS([src/secp256k1 src/univalue]) +AC_CONFIG_SUBDIRS([src/secp256k1 src/univalue src/cryptoconditions]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 72805281a..8907fa54a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -DIST_SUBDIRS = secp256k1 univalue +DIST_SUBDIRS = secp256k1 univalue cryptoconditions AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) @@ -21,6 +21,7 @@ BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include +BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/include -I$(srcdir)/cryptoconditions/src/asn BITCOIN_INCLUDES += -I$(srcdir)/univalue/include if TARGET_WINDOWS @@ -38,6 +39,7 @@ LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la +LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions.la LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a -lcurl @@ -47,6 +49,9 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue/ +$(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) + # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES = \ @@ -389,7 +394,8 @@ komodod_LDADD = \ $(LIBZCASH) \ $(LIBLEVELDB) \ $(LIBMEMENV) \ - $(LIBSECP256K1) + $(LIBSECP256K1) \ + $(LIBCRYPTOCONDITIONS) if ENABLE_ZMQ komodod_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) @@ -450,7 +456,8 @@ komodo_tx_LDADD = \ $(LIBSECP256K1) \ $(LIBZCASH) \ $(LIBBITCOIN_CRYPTO) \ - $(LIBZCASH_LIBS) + $(LIBZCASH_LIBS) \ + $(LIBCRYPTOCONDITIONS) komodo_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # @@ -507,7 +514,8 @@ endif libzcashconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS) libzcashconsensus_la_LIBADD = $(CRYPTO_LIBS) -libzcashconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL +libzcashconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL \ + -I$(builddir)/cryptoconditions/src/asn endif # diff --git a/src/cJSON.h b/src/cJSON.h index d3076aa53..2ee786358 100755 --- a/src/cJSON.h +++ b/src/cJSON.h @@ -30,6 +30,7 @@ #include #include #include +#include "komodo_structs.h" //#include "../crypto777/OS_portable.h" diff --git a/src/cryptoconditions b/src/cryptoconditions new file mode 160000 index 000000000..7bd65d43a --- /dev/null +++ b/src/cryptoconditions @@ -0,0 +1 @@ +Subproject commit 7bd65d43af4e95ea6d8edf6c3dc5f340e39770cd diff --git a/src/komodo_structs.h b/src/komodo_structs.h index a35e7e008..fa8b3c2f1 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -22,6 +22,9 @@ #define PACKED __attribute__((packed)) #endif*/ +#ifndef KOMODO_STRUCTS_H +#define KOMODO_STRUCTS_H + #define GENESIS_NBITS 0x1f00ffff #define KOMODO_MINRATIFY ((height < 90000) ? 7 : 11) #define KOMODO_MAXBLOCKS 5000000 @@ -88,3 +91,5 @@ struct komodo_state struct komodo_event **Komodo_events; int32_t Komodo_numevents; uint32_t RTbufs[64][3]; uint64_t RTmask; }; + +#endif /* KOMODO_STRUCTS_H */ diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 6c17eab70..f65581068 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -13,6 +13,8 @@ #include "pubkey.h" #include "script/script.h" #include "uint256.h" +#include "cryptoconditions/include/cryptoconditions.h" + using namespace std; @@ -934,6 +936,51 @@ bool EvalScript(vector >& stack, const CScript& script, un } break; + case OP_CHECKCRYPTOCONDITION: + case OP_CHECKCRYPTOCONDITIONVERIFY: + { + // (fulfillment condition -- bool) + + if (stack.size() < 2) + return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + + valtype& vchFulfillment = stacktop(-2); + valtype& vchCondition = stacktop(-1); + + // Hard limit fulfillment size + if (vchFulfillment.size() > 1024 * 10) { + return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT); + } + + CC *cond = (CC*) calloc(1, sizeof(CC)); + char *fulfillmentBin = (char*) vchFulfillment.data(); + int rc = cc_readFulfillmentBinary(cond, fulfillmentBin, vchFulfillment.size()); + if (rc != 0) { + return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT); + } + + char *condBin = (char*) &vchCondition[0]; + // TODO: Should nHashType be hardcoded? + // Other types use the last byte of the signature + char *msg = (char*) checker.GetMessage(script, SIGHASH_ALL).begin(); +; + bool fSuccess = cc_verify(cond, msg, 32, condBin, vchCondition.size()); + + popstack(stack); + popstack(stack); + + stack.push_back(fSuccess ? vchTrue : vchFalse); + + if (opcode == OP_CHECKCRYPTOCONDITIONVERIFY) + { + if (fSuccess) + popstack(stack); + else + return set_error(serror, SCRIPT_ERR_CRYPTOCONDITION_VERIFY); + } + } + break; + default: return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } @@ -1147,6 +1194,11 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con return true; } +uint256 TransactionSignatureChecker::GetMessage(const CScript& scriptCode, int nHashType) const +{ + return SignatureHash(scriptCode, *txTo, nIn, nHashType); +} + bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { diff --git a/src/script/interpreter.h b/src/script/interpreter.h index b94916fac..fad2d9a91 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -102,6 +102,12 @@ public: return false; } + virtual uint256 GetMessage(const CScript& scriptCode, int nHashType) const + { + uint256 blob; + return blob; + } + virtual ~BaseSignatureChecker() {} }; @@ -118,6 +124,7 @@ public: TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const; bool CheckLockTime(const CScriptNum& nLockTime) const; + uint256 GetMessage(const CScript& scriptCode, int nHashType) const; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker diff --git a/src/script/script.cpp b/src/script/script.cpp index fd3392473..3cb3f855d 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -138,6 +138,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"; // expanson case OP_NOP1 : return "OP_NOP1"; diff --git a/src/script/script.h b/src/script/script.h index e0e89185f..584fefac1 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -154,6 +154,8 @@ enum opcodetype OP_CHECKSIGVERIFY = 0xad, OP_CHECKMULTISIG = 0xae, OP_CHECKMULTISIGVERIFY = 0xaf, + OP_CHECKCRYPTOCONDITION = 0xcc, + OP_CHECKCRYPTOCONDITIONVERIFY = 0xcd, // expansion OP_NOP1 = 0xb0, @@ -168,7 +170,6 @@ enum opcodetype OP_NOP9 = 0xb8, OP_NOP10 = 0xb9, - // template matching params OP_SMALLDATA = 0xf9, OP_SMALLINTEGER = 0xfa, diff --git a/src/script/script_error.h b/src/script/script_error.h index bb10b8a29..e84268977 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -52,7 +52,10 @@ typedef enum ScriptError_t /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, - SCRIPT_ERR_ERROR_COUNT + SCRIPT_ERR_ERROR_COUNT, + + SCRIPT_ERR_CRYPTOCONDITION_VERIFY, + SCRIPT_ERR_CRYPTOCONDITION_INVALID_FULFILLMENT } ScriptError; #define SCRIPT_ERR_LAST SCRIPT_ERR_ERROR_COUNT