7 #include <cryptoconditions.h>
8 #include <gtest/gtest.h>
11 #include "importcoin.h"
14 #include "crosschain.h"
16 #include "komodo_structs.h"
18 #include "notarisationdb.h"
19 #include "primitives/block.h"
20 #include "primitives/transaction.h"
21 #include "script/cc.h"
22 #include "script/interpreter.h"
23 #include "script/serverchecker.h"
24 #include "txmempool.h"
25 #include "crosschain.h"
27 #include "testutils.h"
30 extern uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
31 extern bool KOMODO_TEST_ASSETCHAIN_SKIP_POW;
35 * Tests for the whole process of creating and validating notary proofs
36 * using proof roots (MoMoMs). This is to support coin imports.
39 namespace TestCrossChainProof {
42 class TestCrossChain : public ::testing::Test, public Eval {
44 bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
46 NotarisationData data(2);
47 return ParseNotarisationOpReturn(tx, data); // If it parses it's valid
50 static void SetUpTestCase() { }
51 virtual void SetUp() {
52 KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1;
59 uint256 endianHash(uint256 h)
62 for (int i=0; i<32; i++) {
63 out.begin()[31-i] = h.begin()[i];
69 TEST_F(TestCrossChain, testCreateAndValidateImportProof)
72 * This tests the full process of creation of a cross chain proof.
73 * For the purposes of the test we will use one assetchain and a KMD chain.
75 * In order to do this test, we need 2 blockchains, so we'll fork and make a socket
79 int childPid = fork();
80 void *ctx = zmq_ctx_new();
81 void *socket = zmq_socket(ctx, ZMQ_PAIR);
83 strcpy(ASSETCHAINS_SYMBOL, "PIZZA");
85 std::vector<CBlock> blocks;
87 NotarisationData a2kmd(0), kmd2a(1);
88 int numTestNotarisations = 10;
91 auto SendIPC = [&] (std::vector<uint8_t> v) {
92 assert(v.size() == zmq_send(socket, v.data(), v.size(), 0));
95 auto RecvIPC = [&] () {
96 std::vector<uint8_t> out;
98 int len = zmq_recv(socket, out.data(), out.size(), 0);
104 auto RecordNotarisation = [&] (CTransaction inputTx, NotarisationData data) {
105 CMutableTransaction mtx = spendTx(inputTx);
107 mtx.vout[0].scriptPubKey << VCH(notaryKey.GetPubKey().begin(), 33) << OP_CHECKSIG;
108 mtx.vout[1].scriptPubKey << OP_RETURN << E_MARSHAL(ss << data);
109 mtx.vout[1].nValue = 0;
110 mtx.vin[0].scriptSig << getSig(mtx, inputTx.vout[0].scriptPubKey);
112 acceptTxFail(CTransaction(mtx));
113 return mtx.GetHash();
116 auto RunTestAssetchain = [&] ()
118 NotarisationData n(0), back(1);
119 strcpy(n.symbol, "PIZZA");
124 * Send notarisations and write backnotarisations
126 for (int ni=0; ni<numTestNotarisations; ni++)
128 generateBlock(&blocks[++height]);
129 generateBlock(&blocks[++height]);
130 n.blockHash = blocks[height].GetHash();
131 n.MoM = endianHash(komodo_calcMoM(n.height=height, n.MoMDepth=2));
132 SendIPC(E_MARSHAL(ss << n));
133 assert(E_UNMARSHAL(RecvIPC(), ss >> back));
134 RecordNotarisation(blocks[height].vtx[0], back);
140 uint256 txid = blocks[7].vtx[0].GetHash();
141 TxProof proof = GetAssetchainProof(txid);
142 SendIPC(E_MARSHAL(ss << txid; ss << proof));
143 E_UNMARSHAL(RecvIPC(), ss >> proof);
145 std::pair<uint256,NotarisationData> bn;
146 if (!GetNextBacknotarisation(proof.first, bn)) {
147 printf("GetNextBackNotarisation failed\n");
150 if (proof.second.Exec(txid) != bn.second.MoMoM) {
151 printf("MoMom incorrect\n");
157 auto RunTestKmd = [&] ()
159 NotarisationData n(0);
163 * Write notarisations and send backnotarisations
165 for (int ni=0; ni<numTestNotarisations; ni++)
167 n.IsBackNotarisation = 0;
168 E_UNMARSHAL(RecvIPC(), ss >> n);
169 // Grab a coinbase input to fund notarisation
170 generateBlock(&blocks[++height]);
171 n.txHash = RecordNotarisation(blocks[height].vtx[0], n);
173 std::vector<uint256> moms;
174 uint256 destNotarisationTxid;
175 n.MoMoM = CalculateProofRoot(n.symbol, 2, height, moms, destNotarisationTxid);
177 n.IsBackNotarisation = 1;
178 SendIPC(E_MARSHAL(ss << n));
186 // Extend proof to MoMoM
187 assert(E_UNMARSHAL(RecvIPC(), ss >> txid; ss >> proof));
188 proof = GetCrossChainProof(txid, (char*)"PIZZA", 2, proof);
189 SendIPC(E_MARSHAL(ss << proof));
192 const char endpoint[] = "ipc://tmpKomodoTestCrossChainSock";
195 assert(0 == zmq_connect(socket, endpoint));
197 int out = RunTestAssetchain();
198 if (!out) printf("Assetchain success\n");
202 assert(0 == zmq_bind(socket, endpoint));
205 waitpid(childPid, &returnStatus, 0);
206 unlink("tmpKomodoTestCrossChainSock");
207 ASSERT_EQ(0, returnStatus);
213 } /* namespace TestCrossChainProof */