ImportPayout cc eval code and alot of general cc polish. tests to write
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -25,4 +25,6 @@ zcash_CreateJoinSplit_LDADD = \
|
||||
$(LIBBITCOIN_UTIL) \
|
||||
$(LIBBITCOIN_CRYPTO) \
|
||||
$(BOOST_LIBS) \
|
||||
$(LIBZCASH_LIBS)
|
||||
$(LIBZCASH_LIBS) \
|
||||
$(LIBCRYPTOCONDITIONS) \
|
||||
$(LIBSECP256K1)
|
||||
|
||||
23
src/cc/eval.cpp
Normal file
23
src/cc/eval.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "primitives/transaction.h"
|
||||
#include "komodo_cc.h"
|
||||
#include "cc/eval.h"
|
||||
#include <cryptoconditions.h>
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
18
src/cc/eval.h
Normal file
18
src/cc/eval.h
Normal file
@@ -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 */
|
||||
191
src/cc/importpayout.cpp
Normal file
191
src/cc/importpayout.cpp
Normal file
@@ -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<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;
|
||||
}
|
||||
|
||||
|
||||
class MomProof
|
||||
{
|
||||
public:
|
||||
uint256 notaryHash;
|
||||
int nPos; // Position of imported tx in MoM
|
||||
std::vector<uint256> branch;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
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; i<nNotaries; i++) {
|
||||
if (!seenNotaries[i]) {
|
||||
if (memcmp(pk, notaries[i], 33) == 0) {
|
||||
seenNotaries[i] = 1;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
found:;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get MoM from a notarisation tx hash
|
||||
*/
|
||||
bool GetMoM(const uint256 notaryHash, uint256 &mom)
|
||||
{
|
||||
CTransaction notarisationTx;
|
||||
uint256 notarisationBlock;
|
||||
if (!GetTransaction(notaryHash, notarisationTx, notarisationBlock, true)) return 0;
|
||||
CBlockIndex* blockindex = mapBlockIndex[notarisationBlock];
|
||||
if (!CheckNotaryInputs(notarisationTx, blockindex->nHeight, blockindex->nTime)) {
|
||||
return false;
|
||||
}
|
||||
if (!notarisationTx.vout.size() < 1) return 0;
|
||||
std::vector<unsigned char> 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<uint256>& 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<CTxOut> payouts(payoutTx->vout.begin() + 2, payoutTx->vout.end());
|
||||
uint256 payoutsHash = SerializeHash(payouts);
|
||||
std::vector<unsigned char> vPayoutsHash(payoutsHash.begin(), payoutsHash.end());
|
||||
|
||||
// load exportTx from vout[1]
|
||||
CTransaction exportTx;
|
||||
{
|
||||
std::vector<unsigned char> 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<unsigned char> 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<unsigned char> 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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -14,7 +14,7 @@ struct CCType cc_thresholdType;
|
||||
static uint32_t thresholdSubtypes(const CC *cond) {
|
||||
uint32_t mask = 0;
|
||||
for (int i=0; i<cond->size; i++) {
|
||||
mask |= getSubtypes(cond->subconditions[i]);
|
||||
mask |= cc_typeMask(cond->subconditions[i]);
|
||||
}
|
||||
mask &= ~(1 << cc_thresholdType.typeId);
|
||||
return mask;
|
||||
|
||||
40
src/komodo_cc.h
Normal file
40
src/komodo_cc.h
Normal file
@@ -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 */
|
||||
@@ -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<unsigned char> &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;
|
||||
}
|
||||
@@ -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<unsigned char> &data);
|
||||
|
||||
#endif /* KOMODO_CRYPTOCONDITIONS_H */
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<unsigned char>& 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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "script_error.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "komodo_cryptoconditions.h"
|
||||
#include "komodo_cc.h"
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
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;
|
||||
bool CheckCryptoCondition(const CC *cond, const std::vector<unsigned char>& condBin, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
bool CheckEvalCondition(const CC *cond) const;
|
||||
VerifyEval GetCCEval() const;
|
||||
};
|
||||
|
||||
class MutableTransactionSignatureChecker : public TransactionSignatureChecker
|
||||
|
||||
@@ -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<unsigned char>& 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<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 accept = IsAcceptableCryptoCondition(cond);
|
||||
return accept;
|
||||
}
|
||||
|
||||
bool CScript::IsPushOnly() const
|
||||
{
|
||||
const_iterator pc = begin();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<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,24 @@ 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.
|
||||
*/
|
||||
VerifyEval ServerTransactionSignatureChecker::GetCCEval() const
|
||||
{
|
||||
return [] (CC *cond, void *checker) {
|
||||
return ((ServerTransactionSignatureChecker*)checker)->CheckEvalCondition(cond);
|
||||
};
|
||||
}
|
||||
|
||||
int ServerTransactionSignatureChecker::CheckEvalCondition(CC *cond) const
|
||||
{
|
||||
return EvalConditionValidity(cond, txTo, nIn);
|
||||
}
|
||||
30
src/script/serverchecker.h
Normal file
30
src/script/serverchecker.h
Normal file
@@ -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 <vector>
|
||||
|
||||
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<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||
int CheckEvalCondition(CC *cond) const;
|
||||
VerifyEval GetCCEval() const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_SCRIPT_SERVERCHECKER_H
|
||||
@@ -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
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "script/script.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "komodo_cryptoconditions.h"
|
||||
#include "komodo_cc.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
@@ -72,9 +72,11 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
|
||||
if (IsCryptoConditionsEnabled()) {
|
||||
// Shortcut for pay-to-crypto-condition
|
||||
if (scriptPubKey.IsPayToCryptoCondition()) {
|
||||
typeRet = TX_CRYPTOCONDITION;
|
||||
// TODO: Extract solutions
|
||||
return true;
|
||||
if (scriptPubKey.MayAcceptCryptoCondition()) {
|
||||
typeRet = TX_CRYPTOCONDITION;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user