]> Git Repo - VerusCoin.git/blob - src/test-komodo/test_crosschain.cpp
Merge branch 'dev' into jl777
[VerusCoin.git] / src / test-komodo / test_crosschain.cpp
1 #include <zmq.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <assert.h>
6
7 #include <cryptoconditions.h>
8 #include <gtest/gtest.h>
9
10 #include "cc/eval.h"
11 #include "importcoin.h"
12 #include "base58.h"
13 #include "core_io.h"
14 #include "crosschain.h"
15 #include "key.h"
16 #include "komodo_structs.h"
17 #include "main.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"
26
27 #include "testutils.h"
28
29
30 extern uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth);
31 extern bool KOMODO_TEST_ASSETCHAIN_SKIP_POW;
32
33
34 /*
35  * Tests for the whole process of creating and validating notary proofs
36  * using proof roots (MoMoMs). This is to support coin imports.
37  */
38
39 namespace TestCrossChainProof {
40
41
42 class TestCrossChain : public ::testing::Test, public Eval {
43 public:
44     bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
45     {
46         NotarisationData data(2);
47         return ParseNotarisationOpReturn(tx, data);  // If it parses it's valid
48     }
49 protected:
50     static void SetUpTestCase() { }
51     virtual void SetUp() {
52         KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1;
53         ASSETCHAINS_CC = 1;
54         EVAL_TEST = this;
55     }
56 };
57
58
59 uint256 endianHash(uint256 h)
60 {
61     uint256 out;
62     for (int i=0; i<32; i++) {
63         out.begin()[31-i] = h.begin()[i];
64     }
65     return out;
66 }
67
68
69 TEST_F(TestCrossChain, testCreateAndValidateImportProof)
70 {
71     /*
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.
74      *
75      * In order to do this test, we need 2 blockchains, so we'll fork and make a socket
76      * for IPC.
77      */
78
79     int childPid = fork();
80     void *ctx = zmq_ctx_new();
81     void *socket = zmq_socket(ctx, ZMQ_PAIR);
82     if (!childPid)
83         strcpy(ASSETCHAINS_SYMBOL, "PIZZA");
84     setupChain(); 
85     std::vector<CBlock> blocks;
86     blocks.resize(1000);
87     NotarisationData a2kmd(0), kmd2a(1);
88     int numTestNotarisations = 10;
89
90
91     auto SendIPC = [&] (std::vector<uint8_t> v) {
92         assert(v.size() == zmq_send(socket, v.data(), v.size(), 0));
93     };
94
95     auto RecvIPC = [&] () {
96         std::vector<uint8_t> out;
97         out.resize(100000);
98         int len = zmq_recv(socket, out.data(), out.size(), 0);
99         assert(len != -1);
100         out.resize(len);
101         return out;
102     };
103
104     auto RecordNotarisation = [&] (CTransaction inputTx, NotarisationData data) {
105         CMutableTransaction mtx = spendTx(inputTx);
106         mtx.vout.resize(2);
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);
111         
112         acceptTxFail(CTransaction(mtx));
113         return mtx.GetHash();
114     };
115
116     auto RunTestAssetchain = [&] ()
117     {
118         NotarisationData n(0), back(1);
119         strcpy(n.symbol, "PIZZA");
120         n.ccId = 2;
121         int height = 0;
122
123         /*
124          * Send notarisations and write backnotarisations
125          */
126         for (int ni=0; ni<numTestNotarisations; ni++)
127         {
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);
135         }
136
137         /*
138          * Test a proof
139          */
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);
144
145         std::pair<uint256,NotarisationData> bn;
146         if (!GetNextBacknotarisation(proof.first, bn)) {
147             printf("GetNextBackNotarisation failed\n");
148             return 1;
149         }
150         if (proof.second.Exec(txid) != bn.second.MoMoM) {
151             printf("MoMom incorrect\n");
152             return 1;
153         }
154         return 0;
155     };
156
157     auto RunTestKmd = [&] ()
158     {
159         NotarisationData n(0);
160         int height = 0;
161
162         /*
163          * Write notarisations and send backnotarisations
164          */
165         for (int ni=0; ni<numTestNotarisations; ni++)
166         {
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);
172             {
173                 std::vector<uint256> moms;
174                 uint256 destNotarisationTxid;
175                 n.MoMoM = CalculateProofRoot(n.symbol, 2, height, moms, destNotarisationTxid);
176             }
177             n.IsBackNotarisation = 1;
178             SendIPC(E_MARSHAL(ss << n));
179         }
180
181         /*
182          * Extend proof
183          */
184         TxProof proof;
185         uint256 txid;
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));
190     };
191
192     const char endpoint[] = "ipc://tmpKomodoTestCrossChainSock";
193
194     if (!childPid) {
195         assert(0 == zmq_connect(socket, endpoint));
196         usleep(20000);
197         int out = RunTestAssetchain();
198         if (!out) printf("Assetchain success\n");
199         exit(out);
200     }
201     else {
202         assert(0 == zmq_bind(socket, endpoint));
203         RunTestKmd();
204         int returnStatus;
205         waitpid(childPid, &returnStatus, 0);
206         unlink("tmpKomodoTestCrossChainSock");
207         ASSERT_EQ(0, returnStatus);
208     }
209
210 }
211
212
213 } /* namespace TestCrossChainProof */
This page took 0.036959 seconds and 4 git commands to generate.