From 375927407bca42e268e7e2f6072563b472c31205 Mon Sep 17 00:00:00 2001 From: Scott Sadler Date: Tue, 3 Apr 2018 04:48:24 -0300 Subject: [PATCH] betprotocol functions --- src/cc/betprotocol.cpp | 240 ++++++++++++++++++ src/cc/importpayout.cpp | 31 +-- src/cc/importpayout.h | 26 ++ src/cryptoconditions/README.md | 2 +- .../include/cryptoconditions.h | 2 +- src/cryptoconditions/src/anon.c | 3 +- src/cryptoconditions/src/cryptoconditions.c | 7 +- src/cryptoconditions/src/ed25519.c | 6 +- src/cryptoconditions/src/eval.c | 6 +- src/cryptoconditions/src/prefix.c | 6 +- src/cryptoconditions/src/preimage.c | 6 +- src/cryptoconditions/src/secp256k1.c | 3 +- src/cryptoconditions/src/threshold.c | 6 +- src/komodo_notary.h | 1 + src/rpcblockchain.cpp | 78 ++++++ src/rpcclient.cpp | 1 + src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + 18 files changed, 371 insertions(+), 55 deletions(-) create mode 100644 src/cc/betprotocol.cpp create mode 100644 src/cc/importpayout.h diff --git a/src/cc/betprotocol.cpp b/src/cc/betprotocol.cpp new file mode 100644 index 000000000..024b4c001 --- /dev/null +++ b/src/cc/betprotocol.cpp @@ -0,0 +1,240 @@ +#include + +#include "primitives/transaction.h" + + +class DisputeHeader +{ +public: + int waitBlocks; + std::vector vmParams; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(VARINT(waitBlocks)); + READWRITE(vmParams); + } +}; + + +static CScript CCPubKey(const CC *cond) +{ + unsigned char buf[1000]; + size_t len = cc_conditionBinary(cond, buf); + return CScript() << std::vector(buf, buf+len) << OP_CHECKCRYPTOCONDITION; +} + + +static CScript CCSig(const CC *cond) +{ + unsigned char buf[1000]; + size_t len = cc_fulfillmentBinary(cond, buf, 1000); + auto ffill = std::vector(buf, buf+len); + ffill.push_back(SIGHASH_ALL); + return CScript() << ffill; +} + + +static unsigned char* CopyPubKey(CPubKey pkIn) +{ + auto *pk = malloc(33); + memcpy(pk, pkIn.begin(), 33); // TODO: compressed? + return pk; +} + + +class PokerProtocol +{ +public: + CAmount MINFEE = 1; + std::vector players; + DisputeHeader disputeHeader; + + // on PANGEA + CC* MakeDisputeCond(); + CMutableTransaction MakeSessionTx(CTxIn dealerInput); + CMutableTransaction MakeDisputeTx(uint256 signedSessionTxHash); + CMutableTransaction MakePostEvidenceTx(uint256 signedSessionTxHash, + CPubKey playerKey, std::vector state); + + // on KMD + CC* MakePayoutCond(); + CMutableTransaction MakeStakeTx(CAmount totalPayout, std::vector playerInputs, + uint256 signedSessionTx); + CMutableTransaction MakeAgreePayoutTx(std::vector payouts, + CC *signedPayoutCond, uint256 signedStakeTxHash); + CMutableTransaction MakeImportPayoutTx(std::vector payouts, + CC *signedPayoutCond, CTransaction signedDisputeTx); +} + + +CC* PokerProtocol::MakeDisputeCond() +{ + CC *disputePoker = cond->subconditions[0] = cc_new(CC_Eval); + char err[1000]; + std::vector headerData; + disputeHeader >> CDataStream(headerData, SER_DISK, PROTOCOL_VERSION); + disputePoker->paramsBin = malloc(headerData.size()); + memcpy(disputePoker->paramsBin, headerData.data()); + disputePoker.paramsBinLength = headerData.size(); + + CC *spendSig = cond->subconditions[1] = cc_new(CC_Threshold); + spendSig->threshold = 1; + spendSig->size = players.size() + 1; + spendSig->subconditions = malloc(spendSig->size, sizeof(CC*)); + + for (int i=0; isubconditions[i] = cc_new(CC_Secp256k1); + sub->publicKey = CopyPubKey(players[i]); + } + + CC *cond = cc_new(CC_Threshold); + cond->threshold = 2; + cond->size = 2; + cond->subconditions = calloc(2, sizeof(CC*)); + cond->subconditions[0] = disputePoker; + cond->subconditions[1] = spendSig; + return cond; +} + + +CMutableTransaction PokerProtocol::MakeSessionTx(CTxIn dealerInput) +{ + CMutableTransaction mtx; + mtx.vin.push_back(dealerInput); + + CC *disputeCond = MakeDisputeCond(players, disputeHeader); + mtx.vout.push_back(CTxOut(MINFEE, CCPubKey(disputeCond))); + cc_free(disputeCond); + + for (int i=0; ipublicKey = CopyPubKey(players[i]); + mtx.vout.push_back(CTxOut(MINFEE, CCPubKey(cond))); + cc_free(cond); + } + return mtx; +} + + +CMutableTransaction PokerProtocol::MakeDisputeTx(uint256 signedSessionTxHash, CC *signedDisputeCond, uint256 vmResultHash) +{ + CMutableTransaction mtx; + + CC *disputeCond = MakeDisputeCond(); + mtx.vin.push_back(CTxIn(signedSessionTxHash, 0, CCSig(signedDisputeCond))); + + std::vector result(vmResultHash.begin(), vmResultHash.begin()+32); + mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << result)); + return mtx; +} + + +CMutableTransaction PokerProtocol::MakePostEvidenceTx(uint256 signedSessionTxHash, + int playerIdx, std::vector state) +{ + CMutableTransaction mtx; + + CC *cond = cc_new(CC_Secp256k1); + cond->publicKey = CopyPubKey(players[i]); + mtx.vin.push_back(CTxIn(signedSessionTxHash, playerIdx+1, CCSig(cond))); + + mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << state)); + + return mtx; +} + +CC* CCNewThreshold(int t, std::vector v) +{ + CC *cond = cc_new(CC_Threshold); + cond->threshold = t; + cond->size = v.size(); + cond->subconditions = calloc(1, sizeof(CC*)); + memcpy(cond->subconditions, v.data(), v.size() * sizeof(CC*)); + return cond; +} + + +CCNewSecp256k1(CPubKey &k) +{ + cond = cc_new(CC_Secp256k1); + cond->publicKey = CopyPubKey(players[i]); + return cond; +} + + +CCNewEval(char *method, unsigned char* paramsBin, size_t len) +{ + CC *cond = cc_new(CC_Eval); + strcpy(cond->method, method); + cond->paramsBin = malloc(32); + memcpy(cond->paramsBin, bin, len); + cond->paramsBinLength = len; + return cond; +} + + +CC* MakePayoutCond(uint256 signedSessionTx) +{ + CC* agree; + { + // TODO: 2/3 majority + std::vector subs; + for (int i=0; i subs; + for (int i=0; i playerInputs, + uint256 signedSessionTx) +{ + CMutableTransaction mtx; + mtx.vin = playerInputs; + + CC *payoutCond = MakePayoutCond(signedSessionTx);push + mtx.vout.push_back(CTxOut(totalPayout, CCPubKey(payoutCond))); + cc_free(payoutCond); + + return mtx; +} + + +CMutableTransaction PokerProtocol::MakeAgreePayoutTx(std::vector payouts, + CC *signedPayoutCond, uint256 signedStakeTxHash) +{ + CMutableTransaction mtx; + mtx.vin.push_back(CTxIn(signedStakeTxHash, 0, CCSig(signedPayoutCond))); + mtx.vouts = payouts; + return mtx; +} + + +CMutableTransaction PokerProtocol::MakeImportPayoutTx(std::vector payouts, + CC *signedPayoutCond, CTransaction signedDisputeTx, uint256 signedStakeTxHash) +{ + std::vector vDisputeTx; + signedDisputeTx >> CDataStream(vDisputeTx, SER_DISK, PROTOCOL_VERSION); + CMutableTransaction mtx; + mtx.vin.push_back(CTxInput(signedStakeTxHash, 0, CCSig(signedPayoutCond))); + mtx.vout = payouts; + CMutableTransaction.vout.insert(0, CTxOutput(0, CScript() << OP_RETURN << "PROOF HERE")); + CMutableTransaction.vout.insert(1, CTxOutput(0, CScript() << OP_RETURN << vDisputeTx)); +} diff --git a/src/cc/importpayout.cpp b/src/cc/importpayout.cpp index ee8913744..f05abb943 100644 --- a/src/cc/importpayout.cpp +++ b/src/cc/importpayout.cpp @@ -3,27 +3,10 @@ #include "chain.h" #include "main.h" #include "cc/eval.h" +#include "cc/importpayout.h" #include "cryptoconditions/include/cryptoconditions.h" -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) @@ -89,11 +72,7 @@ bool GetMoM(const uint256 notaryHash, uint256 &mom) return 1; } - -uint256 ExecMerkle(uint256 hash, const std::vector& vMerkleBranch, int nIndex) -{ - return CBlock::CheckMerkleBranch(hash, vMerkleBranch, nIndex); -} +#define ExecMerkle CBlock::CheckMerkleBranch /* @@ -157,13 +136,13 @@ bool CheckImportPayout(const CC *cond, const CTransaction *payoutTx, int nIn) std::vector vchMomProof; if (!GetOpReturnData(payoutTx->vout[0].scriptPubKey, vchMomProof)) return 0; - MomProof momProof; + MoMProof momProof; CDataStream(vchMomProof, SER_DISK, PROTOCOL_VERSION) >> momProof; uint256 mom; - if (!GetMoM(momProof.notaryHash, mom)) return 0; + if (!GetMoM(momProof.notarisationHash, mom)) return 0; - uint256 proofResult = ExecMerkle(disputeTx.GetHash(), momProof.branch, momProof.nPos); + uint256 proofResult = ExecMerkle(disputeTx.GetHash(), momProof.branch, momProof.nIndex); if (proofResult != mom) return 0; } diff --git a/src/cc/importpayout.h b/src/cc/importpayout.h new file mode 100644 index 000000000..3ae094e80 --- /dev/null +++ b/src/cc/importpayout.h @@ -0,0 +1,26 @@ +#ifndef KOMODO_TXPROOF_H +#define KOMODO_TXPROOF_H + + +class MoMProof +{ +public: + int nIndex; + std::vector branch; + uint256 notarisationHash; + + MoMProof() {} + MoMProof(int i, std::vector b, uint256 n) : notarisationHash(n), nIndex(i), branch(b) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(VARINT(nIndex)); + READWRITE(branch); + READWRITE(notarisationHash); + } +}; + + +#endif /* KOMODO_TXPROOF_H */ diff --git a/src/cryptoconditions/README.md b/src/cryptoconditions/README.md index 45418b62a..9ec2a6a5f 100644 --- a/src/cryptoconditions/README.md +++ b/src/cryptoconditions/README.md @@ -17,7 +17,7 @@ make ## Status -JSON interface not particularly safe. The rest is getting there. +JSON interface may not be particularly safe. The rest is pretty good now. ## Embedding diff --git a/src/cryptoconditions/include/cryptoconditions.h b/src/cryptoconditions/include/cryptoconditions.h index 1af542b03..439fe3f4a 100644 --- a/src/cryptoconditions/include/cryptoconditions.h +++ b/src/cryptoconditions/include/cryptoconditions.h @@ -16,7 +16,7 @@ struct CCType; enum CCTypeId { - CC_Condition = -1, + CC_Anon = -1, CC_Preimage = 0, CC_Prefix = 1, CC_Threshold = 2, diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index c9baa6245..38f8e8543 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -17,8 +17,7 @@ static CC *mkAnon(const Condition_t *asnCond) { printf("Unknown ASN type: %i", asnCond->present); return 0; } - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_AnonType; + CC *cond = cc_new(CC_Anon); cond->conditionType = realType; const CompoundSha256Condition_t *deets = &asnCond->choice.thresholdSha256; memcpy(cond->fingerprint, deets->fingerprint.buf, 32); diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index f993b277f..622f09530 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -255,7 +255,7 @@ CC *cc_readConditionBinary(const unsigned char *cond_bin, size_t length) { int cc_isAnon(const CC *cond) { - return cond->type->typeId == CC_Condition; + return cond->type->typeId == CC_Anon; } @@ -281,9 +281,10 @@ char *cc_typeName(const CC *cond) { return cc_isAnon(cond) ? cond->conditionType->name : cond->type->name; } + CC *cc_new(int typeId) { - CC *cond = malloc(sizeof(CC*)); - cond->type = CCTypeRegistry[type]; + CC *cond = calloc(1, sizeof(CC)); + cond->type = CCTypeRegistry[typeId]; return cond; } diff --git a/src/cryptoconditions/src/ed25519.c b/src/cryptoconditions/src/ed25519.c index 541c9b896..18a75fd5c 100644 --- a/src/cryptoconditions/src/ed25519.c +++ b/src/cryptoconditions/src/ed25519.c @@ -104,8 +104,7 @@ static CC *ed25519FromJSON(const cJSON *params, unsigned char *err) { } } - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_Ed25519Type; + CC *cond = cc_new(CC_Ed25519); cond->publicKey = pk; cond->signature = sig; return cond; @@ -125,8 +124,7 @@ static void ed25519ToJSON(const CC *cond, cJSON *params) { static CC *ed25519FromFulfillment(const Fulfillment_t *ffill) { - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_Ed25519Type; + CC *cond = cc_new(CC_Ed25519); cond->publicKey = malloc(32); memcpy(cond->publicKey, ffill->choice.ed25519Sha256.publicKey.buf, 32); cond->signature = malloc(64); diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index 14db14c70..92a1c6e70 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -42,11 +42,10 @@ static CC *evalFromJSON(const cJSON *params, unsigned char *err) { return NULL; } - CC *cond = calloc(1, sizeof(CC)); + CC *cond = cc_new(CC_Eval); strcpy(cond->method, method_item->valuestring); cond->paramsBin = paramsBin; cond->paramsBinLength = paramsBinLength; - cond->type = &CC_EvalType; return cond; } @@ -64,8 +63,7 @@ static void evalToJSON(const CC *cond, cJSON *params) { static CC *evalFromFulfillment(const Fulfillment_t *ffill) { - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_EvalType; + CC *cond = cc_new(CC_Eval); EvalFulfillment_t *eval = &ffill->choice.evalSha256; diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index d8d8b7aad..15a7fa2b7 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -42,8 +42,7 @@ static CC *prefixFromFulfillment(const Fulfillment_t *ffill) { PrefixFulfillment_t *p = ffill->choice.prefixSha256; CC *sub = fulfillmentToCC(p->subfulfillment); if (!sub) return 0; - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_PrefixType; + CC *cond = cc_new(CC_Prefix); cond->maxMessageLength = p->maxMessageLength; cond->prefix = calloc(1, p->prefix.size); memcpy(cond->prefix, p->prefix.buf, p->prefix.size); @@ -88,8 +87,7 @@ static CC *prefixFromJSON(const cJSON *params, unsigned char *err) { return NULL; } - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_PrefixType; + CC *cond = cc_new(CC_Prefix); cond->maxMessageLength = (unsigned long) mml_item->valuedouble; cond->subcondition = sub; diff --git a/src/cryptoconditions/src/preimage.c b/src/cryptoconditions/src/preimage.c index 639bd1009..39953e815 100644 --- a/src/cryptoconditions/src/preimage.c +++ b/src/cryptoconditions/src/preimage.c @@ -18,8 +18,7 @@ static CC *preimageFromJSON(const cJSON *params, unsigned char *err) { } unsigned char *preimage_b64 = preimage_item->valuestring; - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_PreimageType; + CC *cond = cc_new(CC_Preimage); cond->preimage = base64_decode(preimage_b64, &cond->preimageLength); return cond; } @@ -45,8 +44,7 @@ static unsigned char *preimageFingerprint(const CC *cond) { static CC *preimageFromFulfillment(const Fulfillment_t *ffill) { - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_PreimageType; + CC *cond = cc_new(CC_Preimage); PreimageFulfillment_t p = ffill->choice.preimageSha256; cond->preimage = calloc(1, p.preimage.size); memcpy(cond->preimage, p.preimage.buf, p.preimage.size); diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index f83397db8..78fbd7602 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -202,8 +202,7 @@ static CC *cc_secp256k1Condition(const unsigned char *publicKey, const unsigned memcpy(sig, signature, SECP256K1_SIG_SIZE); } - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_Secp256k1Type; + CC *cond = cc_new(CC_Secp256k1); cond->publicKey = pk; cond->signature = sig; return cond; diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 82ef3d736..da8a3027a 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -119,8 +119,7 @@ static CC *thresholdFromFulfillment(const Fulfillment_t *ffill) { } } - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_ThresholdType; + CC *cond = cc_new(CC_Threshold); cond->threshold = threshold; cond->size = size; cond->subconditions = subconditions; @@ -173,8 +172,7 @@ static CC *thresholdFromJSON(const cJSON *params, unsigned char *err) { return NULL; } - CC *cond = calloc(1, sizeof(CC)); - cond->type = &CC_ThresholdType; + CC *cond = cc_new(CC_Threshold); cond->threshold = (long) threshold_item->valuedouble; cond->size = cJSON_GetArraySize(subfulfillments_item); cond->subconditions = calloc(cond->size, sizeof(CC*)); diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 638327e81..dbaa5f2e4 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -419,6 +419,7 @@ int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp) } } + int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height) { int32_t i; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; struct notarized_checkpoint *np = 0; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 1254217ac..30d2c0aab 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -8,6 +8,7 @@ #include "chainparams.h" #include "checkpoints.h" #include "consensus/validation.h" +#include "cc/importpayout.h" #include "main.h" #include "primitives/transaction.h" #include "rpcserver.h" @@ -621,6 +622,83 @@ UniValue height_MoM(const UniValue& params, bool fHelp) return ret; } +UniValue txMoMproof(const UniValue& params, bool fHelp) +{ + uint256 hash, notarisationHash, MoM; + int32_t notarisedHeight, depth; + CBlockIndex* blockIndex; + std::vector branch; + int nIndex; + + // parse params and get notarisation data for tx + { + if ( fHelp || params.size() != 1) + throw runtime_error("txmomproof needs a txid"); + + uint256 hash(uint256S(params[0].get_str())); + + uint256 blockHash; + CTransaction tx; + if (!GetTransaction(hash, tx, blockHash, true)) + throw runtime_error("cannot find transaction"); + + blockIndex = mapBlockIndex[blockHash]; + + depth = komodo_MoM(¬arisedHeight, &MoM, ¬arisationHash, blockIndex->nHeight); + + if (!depth) + throw runtime_error("notarisation not found"); + + // index of block in MoM leaves + nIndex = notarisedHeight - blockIndex->nHeight; + } + + // build merkle chain from blocks to MoM + { + // since the merkle branch code is tied up in a block class + // and we want to make a merkle branch for something that isnt transactions + CBlock fakeBlock; + for (int i=0; ihashMerkleRoot; + CTransaction fakeTx; + // first value in CTransaction memory is it's hash + memcpy((void*)&fakeTx, mRoot.begin(), 32); + fakeBlock.vtx.push_back(fakeTx); + } + branch = fakeBlock.GetMerkleBranch(nIndex); + } + + // Now get the tx merkle branch + { + CBlock block; + + if (fHavePruned && !(blockIndex->nStatus & BLOCK_HAVE_DATA) && blockIndex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, blockIndex)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + // Locate the transaction in the block + int nTxIndex; + for (nTxIndex = 0; nTxIndex < (int)block.vtx.size(); nTxIndex++) + if (block.vtx[nTxIndex].GetHash() == hash) + break; + + if (nTxIndex == (int)block.vtx.size()) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Error locating tx in block"); + + // concatenate branches + std::vector txBranch = block.GetMerkleBranch(nTxIndex); + nIndex = nIndex << txBranch.size() + nTxIndex; + branch.insert(branch.begin(), txBranch.begin(), txBranch.end()); + } + + // Encode and return + CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION); + ssProof << MoMProof(nIndex, branch, notarisationHash); + return HexStr(ssProof.begin(), ssProof.end()); +} + UniValue minerids(const UniValue& params, bool fHelp) { uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 13e9c357b..6a83e8c19 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -126,6 +126,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "paxpending", 0 }, { "notaries", 2 }, { "height_MoM", 1 }, + { "txMoMproof", 1 }, { "minerids", 1 }, { "kvsearch", 1 }, { "kvupdate", 4 }, diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 716992082..5d573f62b 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -297,6 +297,7 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "paxprices", &paxprices, true }, { "blockchain", "notaries", ¬aries, true }, { "blockchain", "height_MoM", &height_MoM, true }, + { "blockchain", "txMoMproof", &txMoMproof, true }, { "blockchain", "minerids", &minerids, true }, { "blockchain", "kvsearch", &kvsearch, true }, { "blockchain", "kvupdate", &kvupdate, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 1f6bd2f94..b4e6ed8fc 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -305,6 +305,7 @@ extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // i extern UniValue z_validatepaymentdisclosure(const UniValue ¶ms, bool fHelp); // in rpcdisclosure.cpp extern UniValue height_MoM(const UniValue& params, bool fHelp); +extern UniValue txMoMproof(const UniValue& params, bool fHelp); extern UniValue notaries(const UniValue& params, bool fHelp); extern UniValue minerids(const UniValue& params, bool fHelp); extern UniValue kvsearch(const UniValue& params, bool fHelp);