tests for getting MoM in Eval and fixes

This commit is contained in:
Scott Sadler
2018-04-06 03:52:30 -03:00
parent e625be68a9
commit 9bf132a5a8
9 changed files with 307 additions and 91 deletions

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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");
}