Files
hush3/src/cc/betprotocol.cpp
Asher Dawes 5f48c77923 Updating branch (#108)
* Fix

* -print

* Filter null outputs

* Rewards cc

* Fix

* Linker

* Fix

* Fix

* KOMODO_LONGESTCHAIN

* Mining_height

* Fix dropped assetoshis

* Error null CCvin

* Test

* Test

* Test

* Fix sell

* Fix order book prints

* )

* Test

* Test

* Fix order display

* Fix oops

* Fix duplicate vin

* Remove dust check

* Fix silly bug

* Test

* Test

* Fix

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Fix compiler error: call of overloaded 'Pair(const char [9], time_t)' is ambiguous

* Fix compiler error: call of overloaded 'Pair(const char [9], time_t)' is ambiguous

* Correctly parse optional top parameter to getsnapshot

* Fix token orders crash

* Add SEC to assetchains.json

* Split amounts/validation: bid, ask, swap

* Fixes

* Test

* Test

* Test

* Test

* +print

* Test

* Test

* Test

* Test

* Test

* Test

* SMALLVAL

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Properly handle multiple vins funding fills

* Test

* Test

* Test

* Test

* Fix ask fill dest

* Test

* Rewards functions

* Fix

* Test

* Params to rewardscalc

* Create funding, addfunding, lock

* Test

* +print

* tokenswapask

* Test

* Test

* Swap functions

* ac_cc under 1000 is not fungible

* Allow to cancel invalid orders

* Prevent negative numbers in assets tx

* Uint64 -> int64

* Fix oops

* Prevent bid for nonexistent assetid

* Error check bidding for assetid that is txid but not asset creation

* Fix

* Fix

* Add pause if scriptcheckqueue isn't idle

* Fix

* -> -> .

* Fix

* Test

* VOBJ

* Tokeninfo rpc

* Asset list

* Test

*             strcpy(cp->normaladdr,AssetsNormaladdr);

* Fix

* Rewardslist rewardsinfo

* Fix

* Fix

* Fix

* Vent

* fix

* Int64

* Int64

* Fix createfunding

* Fix false positive error

*     sbits = stringbits(planstr);

* Fix maxmoney

* Fix funding name

* Test

* Print

* CCutoxvalue

* Fix rewardslock utxo selection

* New PoW diff calc

* tst

* Test

* Oldflag for PoW calc

* Test

* Test

* tst

* Test

* Test

* Filter locked utxo

* Test

* Fix PoW recalc

* Test min seconds

* int64_t CCduration(uint256 txid)

* Test

* Test

* Test one day

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Prevent inputs of CC inputs

* Test

* tst

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* New rewards address

* Fix mask

* Test

* Test

* Test

* Test

* Test

* Test

* Teest

* Stricter vin/vout checks for assets

* Token swap ready for testing

* Fix rewards unlock

* Fix

* Test

* Validate rewards

* Test

* Trim funding input

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Test

* Activate CCduration constraint

* Parameterize KOMODO_FIRSTFUNGIBLEID to 100

* +print

* Test

* Test

* Test

* Test

* Fix c script

* Test

* Initial dice morph from rewards.cpp

* Fix

* Test

* Fix

* Test

* Diceaddfunds

* Fix

* Dice list and dice info

* dicefund

* Dice bet

* Test

* Test

* Put process block's check block call inside lock, revert mining testblockvalidity outside lock

* Don't exit fiat-cli on error

* Docs for coinsupply RPC and improved error-checking on block height

* Version to 0.3.12-beta.

* Change version to 0.3.12 for gilab CI.

* Put undefines for _cpuid back.

* Network decentralizatoin and bug fixes

* Remove unnecessary staking delay

* Staking and mining timeing improvements

* Put staking readout once per staking loop so people know it's staking

* Fail on get_chainactive before lock if checks fail

* Fix check for stake transaction after Komodo merge

* Portable dev (#105)

* Force portable code

* Switch to old MMX instructions, avoiding SSE & SSE2 instructions.

* Less agressive, leave verus code (which checks for it) using advanced instructions.

* Compiling only for windows

* Update .gitlab-ci.yml

* Try -march=native for C++ code generation.

* Tweaking machine architecture settings.

* Try native alone.

* Also get LIBCRYPTOCONDITIONS to -march=native

* Switch other lib to native as well.

* Try switching back further for CPU architecture.

* Even lower end settings.

* Turn on symbols.

* Use sse2,3 and 4 capable x64.

* Once again let verus lib use advances instructioins since it checjs via CPUID at run time.

* Modify a few more makefile entries.

* Switch to AMD model similar to our test system.

* Get snark makefile to k8 too.

* Yet another -march to modify to k8, or two of them.

* Brute force k8 settings, comment non-portable code out.

* Put the condition on cpuid back.

* Put non-portable advenced instruction code back

* Enable instructions.

* Add lib for separate settings.

* Update .gitlab-ci.yml

* Update .gitlab-ci.yml

* Update .gitlab-ci.yml

* Update .gitlab-ci.yml

* replacing k8-sse3 specific flags to x86-84

* updating versions

* updating versions

* Get verus-cli verusd updated (#106)

* Force portable code

* Switch to old MMX instructions, avoiding SSE & SSE2 instructions.

* Less agressive, leave verus code (which checks for it) using advanced instructions.

* Compiling only for windows

* Update .gitlab-ci.yml

* Try -march=native for C++ code generation.

* Tweaking machine architecture settings.

* Try native alone.

* Also get LIBCRYPTOCONDITIONS to -march=native

* Switch other lib to native as well.

* Try switching back further for CPU architecture.

* Even lower end settings.

* Turn on symbols.

* Use sse2,3 and 4 capable x64.

* Once again let verus lib use advances instructioins since it checjs via CPUID at run time.

* Modify a few more makefile entries.

* Switch to AMD model similar to our test system.

* Get snark makefile to k8 too.

* Yet another -march to modify to k8, or two of them.

* Brute force k8 settings, comment non-portable code out.

* Put the condition on cpuid back.

* Put non-portable advenced instruction code back

* Enable instructions.

* Add lib for separate settings.

* Update .gitlab-ci.yml

* Update .gitlab-ci.yml

* Update .gitlab-ci.yml

* Update .gitlab-ci.yml

* replacing k8-sse3 specific flags to x86-84

* updating versions

* Propagate verusd changes.
2018-08-11 13:43:52 -07:00

302 lines
9.3 KiB
C++

/******************************************************************************
* Copyright © 2014-2018 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include <cryptoconditions.h>
#include "hash.h"
#include "main.h"
#include "chain.h"
#include "streams.h"
#include "script/cc.h"
#include "cc/betprotocol.h"
#include "cc/eval.h"
#include "cc/utils.h"
#include "primitives/transaction.h"
std::vector<CC*> BetProtocol::PlayerConditions()
{
std::vector<CC*> subs;
for (int i=0; i<players.size(); i++)
subs.push_back(CCNewSecp256k1(players[i]));
return subs;
}
CC* BetProtocol::MakeDisputeCond()
{
CC *disputePoker = CCNewEval(E_MARSHAL(
ss << disputeCode << VARINT(waitBlocks) << vmParams;
));
CC *anySig = CCNewThreshold(1, PlayerConditions());
return CCNewThreshold(2, {disputePoker, anySig});
}
/*
* 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(spendFee, CCPubKey(disputeCond)));
cc_free(disputeCond);
for (int i=0; i<players.size(); i++) {
CC *cond = CCNewSecp256k1(players[i]);
mtx.vout.push_back(CTxOut(spendFee, CCPubKey(cond)));
cc_free(cond);
}
return mtx;
}
CMutableTransaction BetProtocol::MakeDisputeTx(uint256 signedSessionTxHash, uint256 vmResultHash)
{
CMutableTransaction mtx;
CC *disputeCond = MakeDisputeCond();
mtx.vin.push_back(CTxIn(signedSessionTxHash, 0, CScript()));
std::vector<unsigned char> result(vmResultHash.begin(), vmResultHash.begin()+32);
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << result));
return mtx;
}
CMutableTransaction BetProtocol::MakePostEvidenceTx(uint256 signedSessionTxHash,
int playerIdx, std::vector<unsigned char> state)
{
CMutableTransaction mtx;
mtx.vin.push_back(CTxIn(signedSessionTxHash, playerIdx+1, CScript()));
mtx.vout.push_back(CTxOut(0, CScript() << OP_RETURN << state));
return mtx;
}
CC* BetProtocol::MakePayoutCond(uint256 signedSessionTxHash)
{
// TODO: 2/3 majority
CC* agree = CCNewThreshold(players.size(), PlayerConditions());
CC *import;
{
CC *importEval = CCNewEval(E_MARSHAL(
ss << EVAL_IMPORTPAYOUT << signedSessionTxHash;
));
CC *oneof = CCNewThreshold(1, PlayerConditions());
import = CCNewThreshold(2, {oneof, importEval});
}
return CCNewThreshold(1, {agree, import});
}
CMutableTransaction BetProtocol::MakeStakeTx(CAmount totalPayout, uint256 signedSessionTxHash)
{
CMutableTransaction mtx;
CC *payoutCond = MakePayoutCond(signedSessionTxHash);
mtx.vout.push_back(CTxOut(totalPayout, CCPubKey(payoutCond)));
cc_free(payoutCond);
return mtx;
}
CMutableTransaction BetProtocol::MakeAgreePayoutTx(std::vector<CTxOut> payouts,
uint256 signedStakeTxHash)
{
CMutableTransaction mtx;
mtx.vin.push_back(CTxIn(signedStakeTxHash, 0, CScript()));
mtx.vout = payouts;
return mtx;
}
CMutableTransaction BetProtocol::MakeImportPayoutTx(std::vector<CTxOut> payouts,
CTransaction signedDisputeTx, uint256 signedStakeTxHash, MoMProof momProof)
{
CMutableTransaction mtx;
mtx.vin.push_back(CTxIn(signedStakeTxHash, 0, CScript()));
mtx.vout = payouts;
CScript proofData;
proofData << OP_RETURN << E_MARSHAL(ss << 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;
}
/*
* Crypto-Condition EVAL method that verifies a payout against a transaction
* notarised on another chain.
*
* IN: params - condition params
* IN: importTx - Payout transaction on value chain (KMD)
* IN: nIn - index of input of stake
*
* importTx: Spends stakeTx with payouts from asset chain
*
* in 0: Spends Stake TX and contains ImportPayout CC
* out 0: OP_RETURN MomProof, disputeTx
* out 1-: arbitrary payouts
*
* disputeTx: Spends sessionTx.0 (opener on asset chain)
*
* in 0: spends sessionTx.0
* in 1-: anything
* out 0: OP_RETURN hash of payouts
* out 1-: anything
*/
bool Eval::ImportPayout(const std::vector<uint8_t> params, const CTransaction &importTx, unsigned int nIn)
{
if (importTx.vout.size() == 0) return Invalid("no-vouts");
// load data from vout[0]
MoMProof proof;
CTransaction disputeTx;
{
std::vector<unsigned char> vopret;
GetOpReturnData(importTx.vout[0].scriptPubKey, vopret);
if (!E_UNMARSHAL(vopret, ss >> proof; ss >> disputeTx))
return Invalid("invalid-payload");
}
// Check disputeTx.0 shows correct payouts
{
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");
}
// Check disputeTx spends sessionTx.0
// condition ImportPayout params is session ID from other chain
{
uint256 sessionHash;
if (!E_UNMARSHAL(params, ss >> sessionHash))
return Invalid("malformed-params");
if (disputeTx.vin[0].prevout != COutPoint(sessionHash, 0))
return Invalid("wrong-session");
}
// Check disputeTx solves momproof from vout[0]
{
NotarisationData data(0);
if (!GetNotarisationData(proof.notarisationHash, data))
return Invalid("coudnt-load-mom");
if (data.MoM != proof.branch.Exec(disputeTx.GetHash()))
return Invalid("mom-check-fail");
}
return Valid();
}
/*
* Crypto-Condition EVAL method that resolves a dispute of a session
*
* IN: vm - AppVM virtual machine to verify states
* IN: params - condition params
* IN: disputeTx - transaction attempting to resolve dispute
* IN: nIn - index of input of dispute tx
*
* disputeTx: attempt to resolve a dispute
*
* in 0: Spends Session TX first output, reveals DisputeHeader
* out 0: OP_RETURN hash of payouts
*/
bool Eval::DisputePayout(AppVM &vm, std::vector<uint8_t> params, const CTransaction &disputeTx, unsigned int nIn)
{
if (disputeTx.vout.size() == 0) return Invalid("no-vouts");
// get payouts hash
uint256 payoutHash;
if (!GetOpReturnHash(disputeTx.vout[0].scriptPubKey, payoutHash))
return Invalid("invalid-payout-hash");
// load params
uint16_t waitBlocks;
std::vector<uint8_t> vmParams;
if (!E_UNMARSHAL(params, ss >> VARINT(waitBlocks); ss >> vmParams))
return Invalid("malformed-params");
// ensure that enough time has passed
{
CTransaction sessionTx;
CBlockIndex sessionBlock;
// if unconformed its too soon
if (!GetTxConfirmed(disputeTx.vin[0].prevout.hash, sessionTx, sessionBlock))
return Error("couldnt-get-parent");
if (GetCurrentHeight() < sessionBlock.nHeight + waitBlocks)
return Invalid("dispute-too-soon"); // Not yet
}
// get spends
std::vector<CTransaction> spends;
if (!GetSpendsConfirmed(disputeTx.vin[0].prevout.hash, spends))
return Error("couldnt-get-spends");
// verify result from VM
int maxLength = -1;
uint256 bestPayout;
for (int i=1; i<spends.size(); i++)
{
std::vector<unsigned char> vmState;
if (spends[i].vout.size() == 0) continue;
if (!GetOpReturnData(spends[i].vout[0].scriptPubKey, vmState)) continue;
auto out = vm.evaluate(vmParams, vmState);
uint256 resultHash = SerializeHash(out.second);
if (out.first > maxLength) {
maxLength = out.first;
bestPayout = resultHash;
}
// 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");
bestPayout = resultHash;
}
}
}
if (maxLength == -1) return Invalid("no-evidence");
return bestPayout == payoutHash ? Valid() : Invalid("wrong-payout");
}