1 #include "importcoin.h"
6 #include "primitives/transaction.h"
10 * Generate ImportCoin transaction.
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.
16 CTransaction MakeImportCoinTransaction(const MomoProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts)
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));
23 return CTransaction(mtx);
26 CTxOut MakeBurnOutput(CAmount value, int targetChain, const std::vector<CTxOut> payouts)
28 std::vector<uint8_t> opret = E_MARSHAL(ss << VARINT(targetChain); ss << SerializeHash(payouts));
29 return CTxOut(value, CScript() << OP_RETURN << opret);
33 static bool UnmarshalImportTx(const CTransaction &importTx, MomoProof &proof, CTransaction &burnTx)
35 CScript scriptSig = importTx.vin[0].scriptSig;
36 auto pc = scriptSig.begin();
38 std::vector<uint8_t> evalScript;
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;
52 CAmount GetCoinImportValue(const CTransaction &tx)
56 if (UnmarshalImportTx(tx, proof, burnTx)) {
57 return burnTx.vout.size() ? burnTx.vout[0].nValue : 0;
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.
67 bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& checker, CValidationState &state)
69 auto pc = scriptSig.begin();
71 std::vector<uint8_t> evalScript;
74 if (!scriptSig.GetOp(pc, opcode, evalScript))
76 if (pc != scriptSig.end())
78 if (evalScript.size() == 0)
80 if (evalScript.begin()[0] != EVAL_IMPORTCOIN)
82 // Ok, all looks good so far...
83 CC *cond = CCNewEval(evalScript);
84 bool out = checker.CheckEvalCondition(cond);
89 return f() ? true : state.Invalid(false, 0, "invalid-coin-import");
93 void AddImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs, int nHeight)
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));
103 void RemoveImportTombstone(const CTransaction &importTx, CCoinsViewCache &inputs)
105 uint256 burnHash = importTx.vin[0].prevout.hash;
106 inputs.ModifyCoins(burnHash)->Clear();
110 int ExistsImportTombstone(const CTransaction &importTx, const CCoinsViewCache &inputs)
112 uint256 burnHash = importTx.vin[0].prevout.hash;
113 return inputs.HaveCoins(burnHash);