betprotocol functions
This commit is contained in:
240
src/cc/betprotocol.cpp
Normal file
240
src/cc/betprotocol.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
#include <cryptoconditions.h>
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
|
||||
|
||||
class DisputeHeader
|
||||
{
|
||||
public:
|
||||
int waitBlocks;
|
||||
std::vector<unsigned char> vmParams;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
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<unsigned char>(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<unsigned char>(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<CPubKey> players;
|
||||
DisputeHeader disputeHeader;
|
||||
|
||||
// on PANGEA
|
||||
CC* MakeDisputeCond();
|
||||
CMutableTransaction MakeSessionTx(CTxIn dealerInput);
|
||||
CMutableTransaction MakeDisputeTx(uint256 signedSessionTxHash);
|
||||
CMutableTransaction MakePostEvidenceTx(uint256 signedSessionTxHash,
|
||||
CPubKey playerKey, std::vector<unsigned char> state);
|
||||
|
||||
// on KMD
|
||||
CC* MakePayoutCond();
|
||||
CMutableTransaction MakeStakeTx(CAmount totalPayout, std::vector<CTxIn> playerInputs,
|
||||
uint256 signedSessionTx);
|
||||
CMutableTransaction MakeAgreePayoutTx(std::vector<CTxOut> payouts,
|
||||
CC *signedPayoutCond, uint256 signedStakeTxHash);
|
||||
CMutableTransaction MakeImportPayoutTx(std::vector<CTxOut> payouts,
|
||||
CC *signedPayoutCond, CTransaction signedDisputeTx);
|
||||
}
|
||||
|
||||
|
||||
CC* PokerProtocol::MakeDisputeCond()
|
||||
{
|
||||
CC *disputePoker = cond->subconditions[0] = cc_new(CC_Eval);
|
||||
char err[1000];
|
||||
std::vector<unsigned char> 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; i<players.size()+1; i++) {
|
||||
CC *sub = spendSig->subconditions[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; i<players.size(); i++) {
|
||||
CC *cond = cc_new(CC_Secp256k1);
|
||||
cond->publicKey = 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<unsigned char> 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<unsigned char> 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<CC*> 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<CC*> subs;
|
||||
for (int i=0; i<players.size(); i++)
|
||||
subs[i] = CCNewSecp256k1(players[i]);
|
||||
agree = CCNewThreshold(players.size(), subs);
|
||||
}
|
||||
|
||||
CC *import;
|
||||
{
|
||||
CC *importEval = CCNewEval("ImportPayout", signedSessionTx.begin(), 32);
|
||||
|
||||
std::vector<CC*> subs;
|
||||
for (int i=0; i<players.size(); i++)
|
||||
subs[i] = CCNewSecp256k1(players[i]);
|
||||
CC *oneof = CCNewThreshold(1, subs);
|
||||
|
||||
import = CCNewThreshold(2, {oneof, importEval});
|
||||
}
|
||||
|
||||
return CCNewThreshold(1, {agree, import});
|
||||
}
|
||||
|
||||
|
||||
CMutableTransaction PokerProtocol::MakeStakeTx(CAmount totalPayout, std::vector<CTxIn> 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<CTxOut> 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<CTxOut> payouts,
|
||||
CC *signedPayoutCond, CTransaction signedDisputeTx, uint256 signedStakeTxHash)
|
||||
{
|
||||
std::vector<unsigned char> 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));
|
||||
}
|
||||
@@ -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<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)
|
||||
@@ -89,11 +72,7 @@ bool GetMoM(const uint256 notaryHash, uint256 &mom)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint256 ExecMerkle(uint256 hash, const std::vector<uint256>& 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<unsigned char> 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;
|
||||
}
|
||||
|
||||
|
||||
26
src/cc/importpayout.h
Normal file
26
src/cc/importpayout.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef KOMODO_TXPROOF_H
|
||||
#define KOMODO_TXPROOF_H
|
||||
|
||||
|
||||
class MoMProof
|
||||
{
|
||||
public:
|
||||
int nIndex;
|
||||
std::vector<uint256> branch;
|
||||
uint256 notarisationHash;
|
||||
|
||||
MoMProof() {}
|
||||
MoMProof(int i, std::vector<uint256> b, uint256 n) : notarisationHash(n), nIndex(i), branch(b) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(VARINT(nIndex));
|
||||
READWRITE(branch);
|
||||
READWRITE(notarisationHash);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* KOMODO_TXPROOF_H */
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ struct CCType;
|
||||
|
||||
|
||||
enum CCTypeId {
|
||||
CC_Condition = -1,
|
||||
CC_Anon = -1,
|
||||
CC_Preimage = 0,
|
||||
CC_Prefix = 1,
|
||||
CC_Threshold = 2,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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*));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<uint256> 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; i<depth; i++) {
|
||||
uint256 mRoot = chainActive[notarisedHeight - i]->hashMerkleRoot;
|
||||
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<uint256> 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];
|
||||
|
||||
@@ -126,6 +126,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "paxpending", 0 },
|
||||
{ "notaries", 2 },
|
||||
{ "height_MoM", 1 },
|
||||
{ "txMoMproof", 1 },
|
||||
{ "minerids", 1 },
|
||||
{ "kvsearch", 1 },
|
||||
{ "kvupdate", 4 },
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user