]> Git Repo - VerusCoin.git/blob - src/importcoin.cpp
wip
[VerusCoin.git] / src / importcoin.cpp
1 #include "importcoin.h"
2 #include "cc/utils.h"
3 #include "coins.h"
4 #include "hash.h"
5 #include "script/cc.h"
6 #include "primitives/transaction.h"
7
8
9 /*
10  * Generate ImportCoin transaction.
11  *
12  * Contains an empty OP_RETURN as first output; this is critical for preventing a double
13  * import. If it doesn't contain this it's invalid. The empty OP_RETURN will hang around
14  * in the UTXO set and the transaction will be detected as a duplicate.
15  */
16 CTransaction MakeImportCoinTransaction(const MomoProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts)
17 {
18     std::vector<uint8_t> payload =
19         E_MARSHAL(ss << EVAL_IMPORTCOIN; ss << proof; ss << burnTx);
20     CMutableTransaction mtx;
21     mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload));
22     mtx.vout = payouts;
23     return CTransaction(mtx);
24 }
25
26 CTxOut MakeBurnOutput(CAmount value, int targetChain, const std::vector<CTxOut> payouts)
27 {
28     std::vector<uint8_t> opret = E_MARSHAL(ss << VARINT(targetChain); ss << SerializeHash(payouts));
29     return CTxOut(value, CScript() << OP_RETURN << opret);
30 }
31
32
33 static bool UnmarshalImportTx(const CTransaction &importTx, MomoProof &proof, CTransaction &burnTx)
34 {
35     CScript scriptSig = importTx.vin[0].scriptSig;
36     auto pc = scriptSig.begin();
37     opcodetype opcode;
38     std::vector<uint8_t> evalScript;
39     int code;
40     bool out = false;
41     if (scriptSig.GetOp(pc, opcode, evalScript))
42         if (pc == scriptSig.end())
43             out = E_UNMARSHAL(evalScript, ss >> VARINT(code); ss >> proof; ss >> burnTx);
44     return code == EVAL_IMPORTCOIN && out;
45 }
46
47
48 /*
49  * Required by main
50  * TODO: test
51  */
52 CAmount GetCoinImportValue(const CTransaction &tx)
53 {
54     MomoProof proof;
55     CTransaction burnTx;
56     if (UnmarshalImportTx(tx, proof, burnTx)) {
57         return burnTx.vout.size() ? burnTx.vout[0].nValue : 0;
58     }
59     return 0;
60 }
61
62
63 /*
64  * CoinImport is different enough from normal script execution that it's not worth
65  * making all the mods neccesary in the interpreter to do the dispatch correctly.
66  */
67 bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state)
68 {
69     auto pc = scriptSig.begin();
70     opcodetype opcode;
71     std::vector<uint8_t> evalScript;
72     
73     auto f = [&] () {
74         if (!scriptSig.GetOp(pc, opcode, evalScript))
75             return false;
76         if (pc != scriptSig.end())
77             return false;
78         if (evalScript.size() == 0)
79             return false;
80         if (evalScript.begin()[0] != EVAL_IMPORTCOIN)
81             return false;
82         // Ok, all looks good so far...
83         CC *cond = CCNewEval(evalScript);
84         bool out = checker.CheckEvalCondition(cond);
85         cc_free(cond);
86         return out;
87     };
88
89     return f() ? true : state.Invalid(false, 0, "invalid-coin-import");
90 }
91
92
93 void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight)
94 {
95     uint256 burnHash = importTx.vin[0].prevout.hash;
96     CCoinsModifier modifier = inputs.ModifyCoins(burnHash);
97     modifier->nHeight = nHeight;
98     modifier->nVersion = 1;
99     modifier->vout.push_back(CTxOut(0, CScript() << OP_0));
100 }
101
102
103 void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs)
104 {
105     uint256 burnHash = importTx.vin[0].prevout.hash;
106     inputs.ModifyCoins(burnHash)->Clear();
107 }
108
109
110 int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs)
111 {
112     uint256 burnHash = importTx.vin[0].prevout.hash;
113     return inputs.HaveCoins(burnHash);
114 }
This page took 0.029348 seconds and 4 git commands to generate.