Merge pull request #6 from StakedChain/nntest

Nntest
This commit is contained in:
Alrighttt
2018-09-10 01:11:01 -04:00
committed by GitHub
15 changed files with 226 additions and 133 deletions

View File

@@ -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
View 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

View File

@@ -280,6 +280,7 @@ libbitcoin_server_a_SOURCES = \
chain.cpp \
checkpoints.cpp \
crosschain.cpp \
crosschain_authority.cpp \
deprecation.cpp \
httprpc.cpp \
httpserver.cpp \

View File

@@ -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)
*/

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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);

View 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;
}();

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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
View 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" },
};

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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);