diff --git a/Makefile.am b/Makefile.am index d3171b206..30be7500c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,6 +36,7 @@ BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \ $(top_srcdir)/contrib/devtools/security-check.py + WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \ $(top_srcdir)/share/pixmaps/nsis-header.bmp \ $(top_srcdir)/share/pixmaps/nsis-wizard.bmp diff --git a/doc/beefy-node-reference-komodo.conf b/doc/beefy-node-reference-komodo.conf new file mode 100644 index 000000000..455f1ee3f --- /dev/null +++ b/doc/beefy-node-reference-komodo.conf @@ -0,0 +1,12 @@ +rpcuser=dontuseweakusernameoryougetrobbed +rpcpassword=dontuseweakpasswordoryougetrobbed +txindex=1 +server=1 +rpcworkqueue=64 +addnode=5.9.102.210 +addnode=78.47.196.146 +addnode=178.63.69.164 +addnode=88.198.65.74 +addnode=5.9.122.241 +addnode=144.76.94.38 +addnode=89.248.166.91 \ No newline at end of file diff --git a/migratecoin.md b/migratecoin.md deleted file mode 100644 index 7859bdff2..000000000 --- a/migratecoin.md +++ /dev/null @@ -1,61 +0,0 @@ -# MigrateCoin protocol - - - -## ExportCoins tx: - - - -``` - -vin: - - [ any ] - -vout: - - - amount: {burnAmount} - - script: OP_RETURN "send to ledger {id} {voutsHash}" - -``` - - - -* ExportCoin is a standard tx which burns coins in an OP_RETURN - - - -## ImportCoins tx: - - - -``` - -vin: - - - txid: 0000000000000000000000000000000000000000000000000000000000000000 - - idx: 0 - - script: CC_EVAL(EVAL_IMPORTCOINS, {momoProof},{exportCoin}) OP_CHECKCRYPTOCONDITION_UNILATERAL - -vout: - - - [ vouts matching voutsHash in exportCoin ] - -``` - - - -* ImportCoin transaction has no signature - -* ImportCoin is non malleable - -* ImportCoin satisfies tx.IsCoinBase() - -* ImportCoin uses a new opcode which allows a one sided check (no scriptPubKey) - -* ImportCoin must contain CC opcode EVAL_IMPORTCOINS - -* ImportCoin fees are equal to the difference between burnAmount in exportCoins and the sum of outputs. diff --git a/migratecoin.sh b/migratecoin.sh new file mode 100644 index 000000000..6cd09ba04 --- /dev/null +++ b/migratecoin.sh @@ -0,0 +1,43 @@ +#!/usr/bin/bash + +# This script makes the neccesary transactions to migrate +# coin between 2 assetchains on the same -ac_cc id + +set -e + +source=TXSCL +target=TXSCL000 +address="RFw7byY4xZpZCrtkMk3nFuuG1NTs9rSGgQ" +amount=1 + +# Alias for running cli on source chain +cli_source="komodo-cli -ac_name=$source" + +# Raw tx that we will work with +txraw=`$cli_source createrawtransaction "[]" "{\"$address\":$amount}"` + +# Convert to an export tx +exportData=`$cli_source migrate_converttoexport $txraw $target $amount` +exportRaw=`echo $exportData | jq -r .exportTx` +exportPayouts=`echo $exportData | jq -r .payouts` + +# Fund +exportFundedData=`$cli_source fundrawtransaction $exportRaw` +exportFundedTx=`echo $exportFundedData | jq -r .hex` + +# Sign +exportSignedData=`$cli_source signrawtransaction $exportFundedTx` +exportSignedTx=`echo $exportSignedData | jq -r .hex` + +# Send +echo "Sending export tx" +$cli_source sendrawtransaction $exportSignedTx + +read -p "Wait for a notarisation to KMD, and then two more notarisations from the target chain, and then press enter to continue" + +# Create import +importTx=`$cli_source migrate_createimporttransaction $exportSignedTx $payouts` +importTx=`komodo-cli migrate_completeimporttransaction $importTx` + +# Send import +komodo-cli -ac_name=$target sendrawtransaction $importTx diff --git a/qa/rpc-tests/cryptoconditions.py b/qa/rpc-tests/cryptoconditions.py index fbd650a8e..e7d3065cc 100755 --- a/qa/rpc-tests/cryptoconditions.py +++ b/qa/rpc-tests/cryptoconditions.py @@ -422,7 +422,6 @@ class CryptoConditionsTest (BitcoinTestFramework): result = rpc.tokenbid("100", "deadbeef", "1") assert_error(result) - # valid bid tokenbid = rpc.tokenbid("100", tokenid, "10") tokenbidhex = tokenbid['hex'] tokenbidid = self.send_and_mine(tokenbid['hex']) @@ -595,6 +594,7 @@ class CryptoConditionsTest (BitcoinTestFramework): print("Importing privkey") rpc.importprivkey(self.privkey) +# self.run_faucet_tests() self.run_rewards_tests() self.run_dice_tests() self.run_token_tests() diff --git a/src/assetchains.json b/src/assetchains.json index b74d953a0..ceda4cce1 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -45,7 +45,8 @@ }, { "ac_name": "COQUI", - "ac_supply": "72000000" + "ac_supply": "72000000", + "ac_ccactivate": "200000" }, { "ac_name": "WLC", @@ -140,7 +141,9 @@ "ac_cc": "2", "addressindex": "1", "spentindex": "1", - "addnode": "142.93.136.89", - "addnode": "195.201.22.89" + "addnode": [ + "142.93.136.89", + "195.201.22.89" + ] } ] diff --git a/src/assetchains.old b/src/assetchains.old index d7a18811d..158e62cad 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -15,7 +15,7 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=MSHARK -ac_supply=1400000 -addnode=78.47.196.146 $1 & ./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=78.47.196.146 $1 & ./komodod -pubkey=$pubkey -ac_name=MGW -ac_supply=999999 -addnode=78.47.196.146 $1 & -./komodod -pubkey=$pubkey -ac_name=COQUI -ac_supply=72000000 -addnode=78.47.196.146 $1 & +./komodod -pubkey=$pubkey -ac_name=COQUI -ac_supply=72000000 -ac_ccactivate=200000 -addnode=78.47.196.146 $1 & ./komodod -pubkey=$pubkey -ac_name=WLC -ac_supply=210000000 -addnode=148.251.190.89 $1 & ./komodod -pubkey=$pubkey -ac_name=KV -ac_supply=1000000 -addnode=78.47.196.146 $1 & ./komodod -pubkey=$pubkey -ac_name=CEAL -ac_supply=366666666 -addnode=78.47.196.146 $1 & diff --git a/src/cc/disputepayout.cpp b/src/cc/disputepayout.cpp new file mode 100644 index 000000000..610342274 --- /dev/null +++ b/src/cc/disputepayout.cpp @@ -0,0 +1,84 @@ +#include + +#include "hash.h" +#include "chain.h" +#include "version.h" +#include "script/cc.h" +#include "cc/eval.h" +#include "cc/betprotocol.h" +#include "primitives/transaction.h" + + +/* + * 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 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 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 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 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"); +} diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 99418f711..ffc94ac43 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -59,7 +59,7 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp // check burn amount { - uint64_t burnAmount = burnTx.vout[0].nValue; + uint64_t burnAmount = burnTx.vout.back().nValue; if (burnAmount == 0) return Invalid("invalid-burn-amount"); uint64_t totalOut = 0; diff --git a/src/cc/importpayout.cpp b/src/cc/importpayout.cpp new file mode 100644 index 000000000..1363eb924 --- /dev/null +++ b/src/cc/importpayout.cpp @@ -0,0 +1,76 @@ +#include + +#include "main.h" +#include "chain.h" +#include "streams.h" +#include "cc/eval.h" +#include "cc/betprotocol.h" +#include "primitives/transaction.h" + + +/* + * 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 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 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 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; + if (!GetNotarisationData(proof.notarisationHash, data)) + return Invalid("coudnt-load-mom"); + + if (data.MoM != proof.Exec(disputeTx.GetHash())) + return Invalid("mom-check-fail"); + } + + return Valid(); +} diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 197390e59..831c7bcae 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -50,6 +50,8 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh int seenOwnNotarisations = 0; + bool txscl = IsTXSCL(symbol); + for (int i=0; i kmdHeight) break; NotarisationsInBlock notarisations; @@ -72,8 +74,9 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh if (seenOwnNotarisations == 1) { BOOST_FOREACH(Notarisation& nota, notarisations) { - if (nota.second.ccId == targetCCid) - moms.push_back(nota.second.MoM); + if (IsTXSCL(nota.second.symbol) == txscl) + if (nota.second.ccId == targetCCid) + moms.push_back(nota.second.MoM); } } } diff --git a/src/fiat/vote2018 b/src/fiat/vote2018 new file mode 100755 index 000000000..4e385d76f --- /dev/null +++ b/src/fiat/vote2018 @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=VOTE2018 $1 $2 $3 $4 $5 $6 diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 8b87cb535..d36943b5d 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -45,7 +45,7 @@ bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint { std::vector burnOpret; if (burnTx.vout.size() == 0) return false; - GetOpReturnData(burnTx.vout[0].scriptPubKey, burnOpret); + GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret); return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid); ss >> targetSymbol; ss >> payoutsHash); @@ -61,7 +61,7 @@ CAmount GetCoinImportValue(const CTransaction &tx) CTransaction burnTx; std::vector payouts; if (UnmarshalImportTx(tx, proof, burnTx, payouts)) { - return burnTx.vout.size() ? burnTx.vout[0].nValue : 0; + return burnTx.vout.size() ? burnTx.vout.back().nValue : 0; } return 0; } diff --git a/src/main.cpp b/src/main.cpp index e25d6419b..ce61a0e35 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1547,14 +1547,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa KOMODO_ON_DEMAND++; pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); - // Add memory address index - if (fAddressIndex) { - pool.addAddressIndex(entry, view); - } + if (!tx.IsCoinImport()) + { + // Add memory address index + if (fAddressIndex) { + pool.addAddressIndex(entry, view); + } - // Add memory spent index - if (fSpentIndex) { - pool.addSpentIndex(entry, view); + // Add memory spent index + if (fSpentIndex) { + pool.addSpentIndex(entry, view); + } } } diff --git a/src/notarisationdb.cpp b/src/notarisationdb.cpp index cdfbb82c1..de3dd75f2 100644 --- a/src/notarisationdb.cpp +++ b/src/notarisationdb.cpp @@ -26,7 +26,7 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) { NotarisationData data; if (ParseNotarisationOpReturn(tx, data)) - if (strlen(data.symbol) >= 5 && strncmp(data.symbol, "TXSCL", 5) == 0) + if (IsTXSCL(data.symbol)) isTxscl = 1; } @@ -46,6 +46,11 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight) return vNotarisations; } +bool IsTXSCL(const char* symbol) +{ + return strlen(symbol) >= 5 && strncmp(symbol, "TXSCL", 5) == 0; +} + bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs) { diff --git a/src/notarisationdb.h b/src/notarisationdb.h index b8cd93691..f01a5a587 100644 --- a/src/notarisationdb.h +++ b/src/notarisationdb.h @@ -24,5 +24,6 @@ bool GetBackNotarisation(uint256 notarisationHash, Notarisation &n); void WriteBackNotarisations(const NotarisationsInBlock notarisations, CLevelDBBatch &batch); void EraseBackNotarisations(const NotarisationsInBlock notarisations, CLevelDBBatch &batch); int ScanNotarisationsDB(int height, std::string symbol, int scanLimitBlocks, Notarisation& out); +bool IsTXSCL(const char* symbol); #endif /* NOTARISATIONDB_H */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 7f01c862f..08592fb67 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -31,6 +31,7 @@ using namespace std; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); +int32_t komodo_longestchain(); double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) { @@ -1297,14 +1298,20 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) ); LOCK(cs_main); - + double progress; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { + progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); + } else { + int32_t longestchain = komodo_longestchain(); + progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; + } UniValue obj(UniValue::VOBJ); obj.push_back(Pair("chain", Params().NetworkIDString())); obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()))); + obj.push_back(Pair("verificationprogress", progress)); obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index c24525bdc..0cac14c8b 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -303,6 +303,8 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "paxpending", &paxpending, true }, { "blockchain", "paxprices", &paxprices, true }, { "blockchain", "notaries", ¬aries, true }, + //{ "blockchain", "height_MoM", &height_MoM, true }, + //{ "blockchain", "txMoMproof", &txMoMproof, true }, { "blockchain", "minerids", &minerids, true }, { "blockchain", "kvsearch", &kvsearch, true }, { "blockchain", "kvupdate", &kvupdate, true }, diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index eac21428a..8c1d8b0f8 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -180,7 +180,7 @@ TEST_F(TestCoinImport, testInvalidBurnOutputs) TEST_F(TestCoinImport, testInvalidBurnParams) { - burnTx.vout[0].scriptPubKey = CScript() << OP_RETURN << E_MARSHAL(ss << VARINT(testCcid)); + burnTx.vout.back().scriptPubKey = CScript() << OP_RETURN << E_MARSHAL(ss << VARINT(testCcid)); MoMoM = burnTx.GetHash(); // TODO: an actual branch CTransaction tx = MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts); TestRunCCEval(tx); @@ -198,7 +198,7 @@ TEST_F(TestCoinImport, testWrongChainId) TEST_F(TestCoinImport, testInvalidBurnAmount) { - burnTx.vout[0].nValue = 0; + burnTx.vout.back().nValue = 0; MoMoM = burnTx.GetHash(); // TODO: an actual branch CTransaction tx = MakeImportCoinTransaction(proof, CTransaction(burnTx), payouts); TestRunCCEval(tx); diff --git a/zcutil/fetch-params.sh b/zcutil/fetch-params.sh index 10bade7cb..1e2fe8b81 100755 --- a/zcutil/fetch-params.sh +++ b/zcutil/fetch-params.sh @@ -2,7 +2,11 @@ set -eu -PARAMS_DIR="$HOME/.zcash-params" +if [[ "$OSTYPE" == "darwin"* ]]; then + PARAMS_DIR="$HOME/Library/Application Support/ZcashParams" +else + PARAMS_DIR="$HOME/.zcash-params" +fi SPROUT_PKEY_NAME='sprout-proving.key' SPROUT_VKEY_NAME='sprout-verifying.key'