various tweaks, combine payloads in ImportTx
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 (...) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user