@@ -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.
|
||||
43
migratecoin.sh
Normal file
43
migratecoin.sh
Normal file
@@ -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
|
||||
@@ -280,6 +280,7 @@ libbitcoin_server_a_SOURCES = \
|
||||
chain.cpp \
|
||||
checkpoints.cpp \
|
||||
crosschain.cpp \
|
||||
crosschain_authority.cpp \
|
||||
deprecation.cpp \
|
||||
httprpc.cpp \
|
||||
httpserver.cpp \
|
||||
|
||||
@@ -140,45 +140,17 @@ int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t time
|
||||
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];
|
||||
int nNotaries = GetNotaries(notaries, height, timestamp);
|
||||
CrosschainAuthority auth;
|
||||
auth.requiredSigs = 11;
|
||||
auth.size = GetNotaries(auth.notaries, height, timestamp);
|
||||
|
||||
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
|
||||
{
|
||||
// Get notary pubkey
|
||||
CTransaction tx;
|
||||
uint256 hashBlock;
|
||||
if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
|
||||
if (tx.vout.size() < txIn.prevout.n) return false;
|
||||
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++) {
|
||||
if (!seenNotaries[i]) {
|
||||
if (memcmp(pk, notaries[i], 33) == 0) {
|
||||
seenNotaries[i] = 1;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
found:;
|
||||
}
|
||||
|
||||
return true;
|
||||
return CheckTxAuthority(tx, auth);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get MoM from a notarisation tx hash (on KMD)
|
||||
*/
|
||||
|
||||
@@ -59,7 +59,7 @@ bool Eval::ImportCoin(const std::vector<uint8_t> 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;
|
||||
|
||||
@@ -50,6 +50,8 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
|
||||
|
||||
int seenOwnNotarisations = 0;
|
||||
|
||||
int authority = GetSymbolAuthority(symbol);
|
||||
|
||||
for (int i=0; i<NOTARISATION_SCAN_LIMIT_BLOCKS; i++) {
|
||||
if (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 (GetSymbolAuthority(nota.second.symbol) == authority)
|
||||
if (nota.second.ccId == targetCCid)
|
||||
moms.push_back(nota.second.MoM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
|
||||
#include "cc/eval.h"
|
||||
|
||||
const int CROSSCHAIN_KOMODO = 1;
|
||||
const int CROSSCHAIN_TXSCL = 2;
|
||||
const int CROSSCHAIN_STAKED = 3;
|
||||
|
||||
typedef struct CrosschainAuthority {
|
||||
uint8_t notaries[64][33];
|
||||
size_t size;
|
||||
size_t requiredSigs;
|
||||
} CrosschainAuthority;
|
||||
|
||||
extern const CrosschainAuthority auth_STAKED;
|
||||
|
||||
int GetSymbolAuthority(const char* symbol);
|
||||
bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth);
|
||||
|
||||
/* On assetchain */
|
||||
TxProof GetAssetchainProof(uint256 hash);
|
||||
|
||||
76
src/crosschain_authority.cpp
Normal file
76
src/crosschain_authority.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "cc/eval.h"
|
||||
#include "crosschain.h"
|
||||
#include "notarisationdb.h"
|
||||
//#include "notaries_STAKED.h"
|
||||
|
||||
const char *notaries_STAKEDcc[][2] =
|
||||
{
|
||||
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" },
|
||||
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8"},
|
||||
{"webworker01", "03d01b559004b88fe71f9034ca25c7da0c142e4428afc969473dfbd101c984e7b4"},
|
||||
{"CrisF", "03f87f1bccb744d90fdbf7fad1515a98e9fc7feb1800e460d2e7565b88c3971bf3"},
|
||||
{"daemonfox", "0383484bdc745b2b953c85b5a0c496a1f27bc42ae971f15779ed1532421b3dd943" },
|
||||
{"xrobesx", "020a403b030211c87c77fc3d397db91313d96b3b43b86ca15cb08481508a7f754f" },
|
||||
{"jorian", "02150c410a606b898bcab4f083e48e0f98a510e0d48d4db367d37f318d26ae72e3" },
|
||||
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" },
|
||||
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" },
|
||||
};
|
||||
|
||||
|
||||
int GetSymbolAuthority(const char* symbol)
|
||||
{
|
||||
if (strlen(symbol) >= 5 && strncmp(symbol, "TXSCL", 5) == 0)
|
||||
return CROSSCHAIN_TXSCL;
|
||||
if (strlen(symbol) >= 6 && strncmp(symbol, "STAKED", 6) == 0)
|
||||
return CROSSCHAIN_STAKED;
|
||||
return CROSSCHAIN_KOMODO;
|
||||
}
|
||||
|
||||
|
||||
bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth)
|
||||
{
|
||||
EvalRef eval;
|
||||
|
||||
if (tx.vin.size() < auth.requiredSigs) return false;
|
||||
|
||||
uint8_t seen[64] = {0};
|
||||
|
||||
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
|
||||
{
|
||||
// Get notary pubkey
|
||||
CTransaction tx;
|
||||
uint256 hashBlock;
|
||||
if (!eval->GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
|
||||
if (tx.vout.size() < txIn.prevout.n) return false;
|
||||
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<auth.size; i++) {
|
||||
if (!seen[i]) {
|
||||
if (memcmp(pk, auth.notaries[i], 33) == 0) {
|
||||
seen[i] = 1;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
found:;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const CrosschainAuthority auth_STAKED = [&](){
|
||||
CrosschainAuthority auth;
|
||||
auth.size = (int32_t)(sizeof(notaries_STAKEDcc)/sizeof(*notaries_STAKEDcc));
|
||||
auth.requiredSigs = (auth.size/5);
|
||||
for (int n=0; n<auth.size; n++)
|
||||
for (size_t i=0; i<33; i++)
|
||||
sscanf(notaries_STAKEDcc[n][1]+(i*2), "%2hhx", auth.notaries[n]+i);
|
||||
return auth;
|
||||
}();
|
||||
@@ -45,7 +45,7 @@ bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint
|
||||
{
|
||||
std::vector<uint8_t> 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<CTxOut> 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;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,21 @@
|
||||
|
||||
#include "komodo_cJSON.h"
|
||||
|
||||
//include "notaries_STAKED.h"
|
||||
|
||||
const char *notaries_STAKED[][2] =
|
||||
{
|
||||
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" },
|
||||
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8"},
|
||||
{"webworker01", "03d01b559004b88fe71f9034ca25c7da0c142e4428afc969473dfbd101c984e7b4"},
|
||||
{"CrisF", "03f87f1bccb744d90fdbf7fad1515a98e9fc7feb1800e460d2e7565b88c3971bf3"},
|
||||
{"daemonfox", "0383484bdc745b2b953c85b5a0c496a1f27bc42ae971f15779ed1532421b3dd943" },
|
||||
{"xrobesx", "020a403b030211c87c77fc3d397db91313d96b3b43b86ca15cb08481508a7f754f" },
|
||||
{"jorian", "02150c410a606b898bcab4f083e48e0f98a510e0d48d4db367d37f318d26ae72e3" },
|
||||
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" },
|
||||
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" },
|
||||
};
|
||||
|
||||
#define KOMODO_MAINNET_START 178999
|
||||
|
||||
const char *Notaries_genesis[][2] =
|
||||
@@ -226,13 +241,24 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam
|
||||
{
|
||||
if ( did1 == 0 )
|
||||
{
|
||||
n1 = (int32_t)(sizeof(Notaries_elected1)/sizeof(*Notaries_elected1));
|
||||
for (i=0; i<n1; i++)
|
||||
decode_hex(elected_pubkeys1[i],33,(char *)Notaries_elected1[i][1]);
|
||||
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
|
||||
fprintf(stderr,"%s height.%d t.%u elected.%d notaries2\n",ASSETCHAINS_SYMBOL,height,timestamp,n1);
|
||||
did1 = 1;
|
||||
}
|
||||
if ( strncmp("STAKED",ASSETCHAINS_SYMBOL,6) == 0 )
|
||||
{
|
||||
n1 = (int32_t)(sizeof(notaries_STAKED)/sizeof(*notaries_STAKED));
|
||||
for (i=0; i<n1; i++)
|
||||
decode_hex(elected_pubkeys1[i],33,(char *)notaries_STAKED[i][1]);
|
||||
did1 = 1;
|
||||
printf("THIS CHAIN IS A STAKED CHAIN!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
n1 = (int32_t)(sizeof(Notaries_elected1)/sizeof(*Notaries_elected1));
|
||||
for (i=0; i<n1; i++)
|
||||
decode_hex(elected_pubkeys1[i],33,(char *)Notaries_elected1[i][1]);
|
||||
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
|
||||
fprintf(stderr,"%s height.%d t.%u elected.%d notaries2\n",ASSETCHAINS_SYMBOL,height,timestamp,n1);
|
||||
did1 = 1;
|
||||
}
|
||||
}
|
||||
memcpy(pubkeys,elected_pubkeys1,n1 * 33);
|
||||
return(n1);
|
||||
}
|
||||
|
||||
17
src/main.cpp
17
src/main.cpp
@@ -1552,14 +1552,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
14
src/notaries_STAKED.h
Normal file
14
src/notaries_STAKED.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
const char *notaries_STAKED[][2] =
|
||||
{
|
||||
{"alright", "03b4f49a1c22087e0a9dfaa87aef98ef496c544f9f86038f6c9fea4550543a7679"},
|
||||
{"test1", "0323b1271dceb046a91e79bf80fc5874fb51b9a5ad572c50ca5f58ee9444b32965"},
|
||||
{"test2", "027b45bc21781c287b06b4af48081b49c9ff42cf9e925a8b32dc28a9e85edd2ccd"},
|
||||
{"test3", "023142dd900025a812c985e0c8d8730cbe7791126b8ceac71a506eeee1cb4d2633"},
|
||||
{"test4", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" },
|
||||
{"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60
|
||||
{"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" },
|
||||
{"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" },
|
||||
{"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" },
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "notarisationdb.h"
|
||||
#include "uint256.h"
|
||||
#include "cc/eval.h"
|
||||
#include "crosschain.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -21,27 +22,27 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight)
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++) {
|
||||
CTransaction tx = block.vtx[i];
|
||||
|
||||
// Special case for TXSCL. Should prob be removed at some point.
|
||||
bool isTxscl = 0;
|
||||
{
|
||||
NotarisationData data;
|
||||
if (ParseNotarisationOpReturn(tx, data))
|
||||
if (strlen(data.symbol) >= 5 && strncmp(data.symbol, "TXSCL", 5) == 0)
|
||||
isTxscl = 1;
|
||||
NotarisationData data;
|
||||
bool parsed = ParseNotarisationOpReturn(tx, data);
|
||||
if (!parsed) data = NotarisationData();
|
||||
int authority = GetSymbolAuthority(data.symbol);
|
||||
|
||||
if (authority == CROSSCHAIN_KOMODO) {
|
||||
if (!eval->CheckNotaryInputs(tx, nHeight, block.nTime))
|
||||
continue;
|
||||
} else if (authority == CROSSCHAIN_STAKED) {
|
||||
if (!CheckTxAuthority(tx, auth_STAKED))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isTxscl || eval->CheckNotaryInputs(tx, nHeight, block.nTime)) {
|
||||
NotarisationData data;
|
||||
if (ParseNotarisationOpReturn(tx, data)) {
|
||||
vNotarisations.push_back(std::make_pair(tx.GetHash(), data));
|
||||
//printf("Parsed a notarisation for: %s, txid:%s, ccid:%i, momdepth:%i\n",
|
||||
// data.symbol, tx.GetHash().GetHex().data(), data.ccId, data.MoMDepth);
|
||||
//if (!data.MoMoM.IsNull()) printf("MoMoM:%s\n", data.MoMoM.GetHex().data());
|
||||
}
|
||||
else
|
||||
LogPrintf("WARNING: Couldn't parse notarisation for tx: %s at height %i\n",
|
||||
tx.GetHash().GetHex().data(), nHeight);
|
||||
}
|
||||
if (parsed) {
|
||||
vNotarisations.push_back(std::make_pair(tx.GetHash(), data));
|
||||
//printf("Parsed a notarisation for: %s, txid:%s, ccid:%i, momdepth:%i\n",
|
||||
// data.symbol, tx.GetHash().GetHex().data(), data.ccId, data.MoMDepth);
|
||||
//if (!data.MoMoM.IsNull()) printf("MoMoM:%s\n", data.MoMoM.GetHex().data());
|
||||
} else
|
||||
LogPrintf("WARNING: Couldn't parse notarisation for tx: %s at height %i\n",
|
||||
tx.GetHash().GetHex().data(), nHeight);
|
||||
}
|
||||
return vNotarisations;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user