various tweaks, combine payloads in ImportTx

This commit is contained in:
Scott Sadler
2018-04-06 13:37:56 -03:00
parent aa9eec4522
commit 56cf273faf
7 changed files with 67 additions and 73 deletions

View File

@@ -26,17 +26,21 @@ CC* BetProtocol::MakeDisputeCond()
}
CMutableTransaction BetProtocol::MakeSessionTx()
/*
* spendFee is the amount assigned to each output, for the purposes of posting
* dispute / evidence.
*/
CMutableTransaction BetProtocol::MakeSessionTx(CAmount spendFee)
{
CMutableTransaction mtx;
CC *disputeCond = MakeDisputeCond();
mtx.vout.push_back(CTxOut(MINFEE, CCPubKey(disputeCond)));
mtx.vout.push_back(CTxOut(spendFee, CCPubKey(disputeCond)));
cc_free(disputeCond);
for (int i=0; i<players.size(); i++) {
CC *cond = CCNewSecp256k1(players[i]);
mtx.vout.push_back(CTxOut(MINFEE, CCPubKey(cond)));
mtx.vout.push_back(CTxOut(spendFee, CCPubKey(cond)));
cc_free(cond);
}
return mtx;
@@ -115,7 +119,18 @@ CMutableTransaction BetProtocol::MakeImportPayoutTx(std::vector<CTxOut> payouts,
CMutableTransaction mtx;
mtx.vin.push_back(CTxIn(signedStakeTxHash, 0, CScript()));
mtx.vout = payouts;
mtx.vout.insert(mtx.vout.begin(), CTxOut(0, CScript() << OP_RETURN << CheckSerialize(momProof)));
mtx.vout.insert(mtx.vout.begin()+1, CTxOut(0, CScript() << OP_RETURN << CheckSerialize(signedDisputeTx)));
CScript proofData;
proofData << OP_RETURN << CheckSerialize(std::make_pair(momProof, signedDisputeTx));
mtx.vout.insert(mtx.vout.begin(), CTxOut(0, proofData));
return mtx;
}
bool GetOpReturnHash(CScript script, uint256 &hash)
{
std::vector<unsigned char> vHash;
GetOpReturnData(script, vHash);
if (vHash.size() != 32) return false;
hash = uint256(vHash);
return true;
}

View File

@@ -54,7 +54,6 @@ protected:
char* disputeFunc = (char*) "DisputeBet";
std::vector<CC*> playerConditions();
public:
CAmount MINFEE = 1;
std::vector<CPubKey> players;
DisputeHeader disputeHeader;
@@ -64,7 +63,7 @@ public:
// on PANGEA
CC* MakeDisputeCond();
CMutableTransaction MakeSessionTx();
CMutableTransaction MakeSessionTx(CAmount spendFee);
CMutableTransaction MakeDisputeTx(uint256 signedSessionTxHash, uint256 vmResultHash);
CMutableTransaction MakePostEvidenceTx(uint256 signedSessionTxHash,
int playerIndex, std::vector<unsigned char> state);
@@ -78,4 +77,8 @@ public:
};
bool GetOpReturnHash(CScript script, uint256 &hash);
#endif /* BETPROTOCOL_H */

View File

@@ -9,19 +9,6 @@
#include "primitives/transaction.h"
class DisputeHeader;
static bool GetOpReturnHash(CScript script, uint256 &hash)
{
std::vector<unsigned char> vHash;
GetOpReturnData(script, vHash);
if (vHash.size() != 32) return false;
memcpy(hash.begin(), vHash.data(), 32);
return true;
}
/*
* Crypto-Condition EVAL method that resolves a dispute of a session
*
@@ -85,7 +72,7 @@ bool Eval::DisputePayout(AppVM &vm, const CC *cond, const CTransaction &disputeT
maxLength = out.first;
bestPayout = resultHash;
}
// The below means that if for any reason there is a draw,
// The below means that if for any reason there is a draw, the first dispute wins
else if (out.first == maxLength) {
if (bestPayout != payoutHash) {
fprintf(stderr, "WARNING: VM has multiple solutions of same length\n");

View File

@@ -134,6 +134,9 @@ bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t t
}
extern char ASSETCHAINS_SYMBOL[16];
bool NotarisationData::Parse(const CScript scriptPK)
{
*this = NotarisationData();
@@ -146,12 +149,14 @@ bool NotarisationData::Parse(const CScript scriptPK)
try {
ss >> blockHash;
ss >> height;
if (ASSETCHAINS_SYMBOL[0])
ss >> txHash;
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;
if (ss.size() < 36) return false;
ss >> MoM;
ss >> MoMDepth;
} catch (...) {

View File

@@ -78,7 +78,7 @@ class NotarisationData {
public:
uint256 blockHash;
uint32_t height;
uint256 txHash;
uint256 txHash; // Only get this guy in asset chains not in KMD
char symbol[64];
uint256 MoM;
uint32_t MoMDepth;
@@ -91,7 +91,7 @@ public:
* Serialisation boilerplate
*/
template <class T>
std::vector<unsigned char> CheckSerialize(T &in)
std::vector<unsigned char> CheckSerialize(const T in)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << in;
@@ -99,7 +99,7 @@ std::vector<unsigned char> CheckSerialize(T &in)
}
template <class T>
bool CheckDeserialize(std::vector<unsigned char> vIn, T &out)
bool CheckDeserialize(const std::vector<unsigned char> vIn, T &out)
{
CDataStream ss(vIn, SER_NETWORK, PROTOCOL_VERSION);
try {

View File

@@ -13,15 +13,14 @@
* notarised on another chain.
*
* IN: cond - CC EVAL node
* IN: payoutTx - Payout transaction on value chain (KMD)
* IN: importTx - Payout transaction on value chain (KMD)
* IN: nIn - index of input of stake
*
* payoutTx: Spends stakeTx with payouts from asset chain
* importTx: 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 disputeTx from other chain
* out 2-: arbitrary payouts
* out 0: OP_RETURN MomProof, disputeTx
* out 1-: arbitrary payouts
*
* disputeTx: Spends sessionTx.0 (opener on asset chain)
*
@@ -30,25 +29,27 @@
* out 0: OP_RETURN hash of payouts
* out 1-: anything
*/
bool Eval::ImportPayout(const CC *cond, const CTransaction &payoutTx, unsigned int nIn)
bool Eval::ImportPayout(const CC *cond, const CTransaction &importTx, unsigned int nIn)
{
// TODO: Error messages!
if (payoutTx.vout.size() < 2) return Invalid("need-2-vouts");
if (importTx.vout.size() == 0) return Invalid("no-vouts");
// load disputeTx from vout[1]
// load data from vout[0]
MoMProof proof;
CTransaction disputeTx;
std::vector<unsigned char> exportData;
GetOpReturnData(payoutTx.vout[1].scriptPubKey, exportData);
if (!CheckDeserialize(exportData, disputeTx))
return Invalid("invalid-dispute-tx");
{
std::pair<MoMProof&, CTransaction&> pair(proof, disputeTx);
std::vector<unsigned char> vopret;
GetOpReturnData(importTx.vout[0].scriptPubKey, vopret);
if (!CheckDeserialize(vopret, pair))
return Invalid("invalid-payload");
}
// Check disputeTx.0 shows correct 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());
if (disputeTx.vout[0].scriptPubKey != CScript() << OP_RETURN << vPayoutsHash)
uint256 givenPayoutsHash;
GetOpReturnHash(disputeTx.vout[0].scriptPubKey, givenPayoutsHash);
std::vector<CTxOut> payouts(importTx.vout.begin() + 1, importTx.vout.end());
if (givenPayoutsHash != SerializeHash(payouts))
return Invalid("wrong-payouts");
}
@@ -63,12 +64,6 @@ bool Eval::ImportPayout(const CC *cond, const CTransaction &payoutTx, unsigned i
// Check disputeTx solves momproof from vout[0]
{
std::vector<unsigned char> vProof;
GetOpReturnData(payoutTx.vout[0].scriptPubKey, vProof);
MoMProof proof;
if (!CheckDeserialize(vProof, proof))
return Invalid("invalid-mom-proof-payload");
NotarisationData data;
if (!GetNotarisationData(proof.notarisationHash, data)) return Invalid("coudnt-load-mom");

View File

@@ -152,7 +152,7 @@ public:
CTransaction SessionTx()
{
return CTransaction(bet.MakeSessionTx());
return CTransaction(bet.MakeSessionTx(1));
}
CC* DisputeCond()
@@ -502,24 +502,24 @@ TEST_F(TestBet, testImportPayoutFewVouts)
EvalMock eval = ebet.SetEvalMock(12);
CMutableTransaction importTx = ebet.ImportPayoutTx();
importTx.vout.resize(1);
importTx.vout.resize(0);
CC *payoutCond = ebet.PayoutCond();
EXPECT_EQ(2, CCSign(importTx, 0, payoutCond, {Player2}));
EXPECT_FALSE(TestCC(importTx, 0, payoutCond));
EXPECT_EQ("need-2-vouts", eval.state.GetRejectReason());
EXPECT_EQ("no-vouts", eval.state.GetRejectReason());
}
TEST_F(TestBet, testImportPayoutInvalidDisputeTx)
TEST_F(TestBet, testImportPayoutInvalidPayload)
{
EvalMock eval = ebet.SetEvalMock(12);
CMutableTransaction importTx = ebet.ImportPayoutTx();
importTx.vout[1].scriptPubKey.pop_back();
importTx.vout[0].scriptPubKey.pop_back();
CC *payoutCond = ebet.PayoutCond();
EXPECT_EQ(2, CCSign(importTx, 0, payoutCond, {Player2}));
EXPECT_FALSE(TestCC(importTx, 0, payoutCond));
EXPECT_EQ("invalid-dispute-tx", eval.state.GetRejectReason());
EXPECT_EQ("invalid-payload", eval.state.GetRejectReason());
}
@@ -528,7 +528,7 @@ TEST_F(TestBet, testImportPayoutWrongPayouts)
EvalMock eval = ebet.SetEvalMock(12);
CMutableTransaction importTx = ebet.ImportPayoutTx();
importTx.vout[2].nValue = 7;
importTx.vout[1].nValue = 7;
CC *payoutCond = ebet.PayoutCond();
EXPECT_EQ(2, CCSign(importTx, 0, payoutCond, {Player2}));
ASSERT_FALSE(TestCC(importTx, 0, payoutCond));
@@ -555,27 +555,15 @@ TEST_F(TestBet, testImportPayoutMangleSessionId)
}
TEST_F(TestBet, testImportPayoutInvalidProofPayload)
{
EvalMock eval = ebet.SetEvalMock(12);
CMutableTransaction importTx = ebet.ImportPayoutTx();
importTx.vout[0].scriptPubKey.pop_back();
CC *payoutCond = ebet.PayoutCond();
EXPECT_EQ(2, CCSign(importTx, 0, payoutCond, {Player2}));
EXPECT_FALSE(TestCC(importTx, 0, payoutCond));
EXPECT_EQ("invalid-mom-proof-payload", eval.state.GetRejectReason());
}
TEST_F(TestBet, testImportPayoutInvalidNotarisationHash)
{
EvalMock eval = ebet.SetEvalMock(12);
CMutableTransaction importTx = ebet.ImportPayoutTx();
MoMProof proof = ebet.GetMoMProof();
proof.notarisationHash = uint256();
importTx.vout[0].scriptPubKey = CScript() << OP_RETURN << CheckSerialize(proof);
CMutableTransaction importTx = ebet.bet.MakeImportPayoutTx(
ebet.Payouts(Player2), ebet.DisputeTx(Player2), uint256(), proof);
CC *payoutCond = ebet.PayoutCond();
EXPECT_EQ(2, CCSign(importTx, 0, payoutCond, {Player2}));
EXPECT_FALSE(TestCC(importTx, 0, payoutCond));
@@ -587,10 +575,11 @@ TEST_F(TestBet, testImportPayoutMomFail)
{
EvalMock eval = ebet.SetEvalMock(12);
CMutableTransaction importTx = ebet.ImportPayoutTx();
MoMProof proof = ebet.GetMoMProof();
proof.nIndex ^= 1;
importTx.vout[0].scriptPubKey = CScript() << OP_RETURN << CheckSerialize(proof);
CMutableTransaction importTx = ebet.bet.MakeImportPayoutTx(
ebet.Payouts(Player2), ebet.DisputeTx(Player2), uint256(), proof);
CC *payoutCond = ebet.PayoutCond();
EXPECT_EQ(2, CCSign(importTx, 0, payoutCond, {Player2}));
EXPECT_FALSE(TestCC(importTx, 0, payoutCond));