tests for getting MoM in Eval and fixes
This commit is contained in:
@@ -7,44 +7,6 @@
|
||||
#include "primitives/transaction.h"
|
||||
|
||||
|
||||
static unsigned char* CopyPubKey(CPubKey pkIn)
|
||||
{
|
||||
unsigned char* pk = (unsigned char*) malloc(33);
|
||||
memcpy(pk, pkIn.begin(), 33); // TODO: compressed?
|
||||
return pk;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewThreshold(int t, std::vector<CC*> v)
|
||||
{
|
||||
CC *cond = cc_new(CC_Threshold);
|
||||
cond->threshold = t;
|
||||
cond->size = v.size();
|
||||
cond->subconditions = (CC**) calloc(v.size(), sizeof(CC*));
|
||||
memcpy(cond->subconditions, v.data(), v.size() * sizeof(CC*));
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewSecp256k1(CPubKey k)
|
||||
{
|
||||
CC *cond = cc_new(CC_Secp256k1);
|
||||
cond->publicKey = CopyPubKey(k);
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
CC* CCNewEval(std::string method, std::vector<unsigned char> paramsBin)
|
||||
{
|
||||
CC *cond = cc_new(CC_Eval);
|
||||
strcpy(cond->method, method.data());
|
||||
cond->paramsBin = (unsigned char*) malloc(paramsBin.size());
|
||||
memcpy(cond->paramsBin, paramsBin.data(), paramsBin.size());
|
||||
cond->paramsBinLength = paramsBin.size();
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
||||
std::vector<CC*> BetProtocol::PlayerConditions()
|
||||
{
|
||||
std::vector<CC*> subs;
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
#define BETPROTOCOL_H
|
||||
|
||||
#include "pubkey.h"
|
||||
#include "primitives/block.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "cryptoconditions/include/cryptoconditions.h"
|
||||
|
||||
|
||||
#define ExecMerkle CBlock::CheckMerkleBranch
|
||||
|
||||
|
||||
class MoMProof
|
||||
{
|
||||
public:
|
||||
@@ -18,6 +16,7 @@ public:
|
||||
|
||||
MoMProof() {}
|
||||
MoMProof(int i, std::vector<uint256> b, uint256 n) : notarisationHash(n), nIndex(i), branch(b) {}
|
||||
uint256 Exec(uint256 hash) const { return CBlock::CheckMerkleBranch(hash, branch, nIndex); }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
@@ -79,7 +78,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
CC* CCNewSecp256k1(CPubKey k);
|
||||
|
||||
|
||||
#endif /* BETPROTOCOL_H */
|
||||
|
||||
@@ -88,14 +88,19 @@ bool Eval::GetBlock(uint256 hash, CBlockIndex& blockIdx) const
|
||||
extern int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
|
||||
|
||||
|
||||
int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const
|
||||
{
|
||||
return komodo_notaries(pubkeys, height, timestamp);
|
||||
}
|
||||
|
||||
|
||||
bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
|
||||
{
|
||||
if (tx.vin.size() < 11) return false;
|
||||
|
||||
uint8_t seenNotaries[64] = {0};
|
||||
uint8_t notaries[64][33];
|
||||
uint8_t seenNotaries[64];
|
||||
int nNotaries = komodo_notaries(notaries, height, timestamp);
|
||||
char pk[33];
|
||||
int nNotaries = GetNotaries(notaries, height, timestamp);
|
||||
|
||||
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
|
||||
{
|
||||
@@ -104,10 +109,11 @@ bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t t
|
||||
uint256 hashBlock;
|
||||
if (!GetTx(txIn.prevout.hash, tx, hashBlock, false)) return false;
|
||||
if (tx.vout.size() < txIn.prevout.n) return false;
|
||||
const unsigned char *script = tx.vout[txIn.prevout.n].scriptPubKey.data();
|
||||
if (script[0] != 33) return false;
|
||||
memcpy(pk, script+1, 33);
|
||||
return true;
|
||||
CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
|
||||
if (spk.size() != 35) return false;
|
||||
const unsigned char *pk = spk.data();
|
||||
if (pk++[0] != 33) return false;
|
||||
if (pk[33] != OP_CHECKSIG) return false;
|
||||
|
||||
// Check it's a notary
|
||||
for (int i=0; i<nNotaries; i++) {
|
||||
@@ -121,31 +127,51 @@ bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t t
|
||||
return false;
|
||||
found:;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NotarisationData::Parse(const CScript scriptPK)
|
||||
{
|
||||
*this = NotarisationData();
|
||||
|
||||
std::vector<unsigned char> vdata;
|
||||
if (!GetOpReturnData(scriptPK, vdata)) return false;
|
||||
|
||||
CDataStream ss(vdata, SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
try {
|
||||
ss >> blockHash;
|
||||
ss >> height;
|
||||
|
||||
char *nullPos = (char*) memchr(&ss[0], 0, ss.size());
|
||||
if (!nullPos) return false;
|
||||
ss.read(symbol, nullPos-&ss[0]+1);
|
||||
|
||||
if (ss.size() != 36) return false;
|
||||
ss >> MoM;
|
||||
ss >> MoMDepth;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Get MoM from a notarisation tx hash
|
||||
*/
|
||||
bool Eval::GetMoM(const uint256 notaryHash, uint256 &mom) const
|
||||
bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const
|
||||
{
|
||||
CTransaction notarisationTx;
|
||||
uint256 notarisationBlock;
|
||||
if (!GetTx(notaryHash, notarisationTx, notarisationBlock, true)) return 0;
|
||||
if (!GetTx(notaryHash, notarisationTx, notarisationBlock, true)) return false;
|
||||
CBlockIndex block;
|
||||
if (!GetBlock(notarisationBlock, block)) return 0;
|
||||
if (!CheckNotaryInputs(notarisationTx, block.nHeight, block.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;
|
||||
if (!GetBlock(notarisationBlock, block)) return false;
|
||||
if (!CheckNotaryInputs(notarisationTx, block.nHeight, block.nTime)) return false;
|
||||
if (notarisationTx.vout.size() < 2) return false;
|
||||
if (!data.Parse(notarisationTx.vout[1].scriptPubKey)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
|
||||
class AppVM;
|
||||
class NotarisationData;
|
||||
|
||||
|
||||
class Eval
|
||||
@@ -44,7 +45,8 @@ public:
|
||||
virtual unsigned int GetCurrentHeight() const;
|
||||
virtual bool GetSpends(uint256 hash, std::vector<CTransaction> &spends) const;
|
||||
virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const;
|
||||
virtual bool GetMoM(uint256 notarisationHash, uint256& MoM) const;
|
||||
virtual int32_t GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const;
|
||||
virtual bool GetNotarisationData(uint256 notarisationHash, NotarisationData &data) const;
|
||||
virtual bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const;
|
||||
};
|
||||
|
||||
@@ -69,16 +71,25 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Data from notarisation OP_RETURN
|
||||
*/
|
||||
class NotarisationData {
|
||||
public:
|
||||
uint256 blockHash;
|
||||
uint32_t height;
|
||||
uint256 txHash;
|
||||
char symbol[64];
|
||||
uint256 MoM;
|
||||
uint32_t MoMDepth;
|
||||
|
||||
bool Parse(CScript scriptPubKey);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Serialisation boilerplate
|
||||
*/
|
||||
template <class T>
|
||||
std::vector<unsigned char> CheckSerialize(T &in);
|
||||
template <class T>
|
||||
bool CheckDeserialize(std::vector<unsigned char> vIn, T &out);
|
||||
|
||||
|
||||
|
||||
template <class T>
|
||||
std::vector<unsigned char> CheckSerialize(T &in)
|
||||
{
|
||||
@@ -87,7 +98,6 @@ std::vector<unsigned char> CheckSerialize(T &in)
|
||||
return std::vector<unsigned char>(ss.begin(), ss.end());
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
bool CheckDeserialize(std::vector<unsigned char> vIn, T &out)
|
||||
{
|
||||
|
||||
@@ -69,10 +69,10 @@ bool Eval::ImportPayout(const CC *cond, const CTransaction &payoutTx, unsigned i
|
||||
if (!CheckDeserialize(vProof, proof))
|
||||
return Invalid("invalid-mom-proof-payload");
|
||||
|
||||
uint256 MoM;
|
||||
if (!GetMoM(proof.notarisationHash, MoM)) return Invalid("coudnt-load-mom");
|
||||
NotarisationData data;
|
||||
if (!GetNotarisationData(proof.notarisationHash, data)) return Invalid("coudnt-load-mom");
|
||||
|
||||
if (MoM != ExecMerkle(disputeTx.GetHash(), proof.branch, proof.nIndex))
|
||||
if (data.MoM != proof.Exec(disputeTx.GetHash()))
|
||||
return Invalid("mom-check-fail");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user