forked from ElementsProject/elements
-
Notifications
You must be signed in to change notification settings - Fork 0
/
issuance.cpp
82 lines (71 loc) · 3.19 KB
/
issuance.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <issuance.h>
#include <primitives/transaction.h>
#include <amount.h>
void GenerateAssetEntropy(uint256& entropy, const COutPoint& prevout, const uint256& contracthash)
{
// E : entropy
// I : prevout
// C : contract
// E = H( H(I) || H(C) )
std::vector<uint256> leaves;
leaves.reserve(2);
leaves.push_back(SerializeHash(prevout, SER_GETHASH, 0));
leaves.push_back(contracthash);
entropy = ComputeFastMerkleRoot(leaves);
}
void CalculateAsset(CAsset& asset, const uint256& entropy)
{
static const uint256 kZero = uint256S("0x0000000000000000000000000000000000000000000000000000000000000000");
// H_a : asset tag
// E : entropy
// H_a = H( E || 0 )
std::vector<uint256> leaves;
leaves.reserve(2);
leaves.push_back(entropy);
leaves.push_back(kZero);
asset = CAsset(ComputeFastMerkleRoot(leaves));
}
void CalculateReissuanceToken(CAsset& reissuanceToken, const uint256& entropy, bool fConfidential)
{
static const uint256 kOne = uint256S("0x0000000000000000000000000000000000000000000000000000000000000001");
static const uint256 kTwo = uint256S("0x0000000000000000000000000000000000000000000000000000000000000002");
// H_a : asset reissuance tag
// E : entropy
// if not fConfidential:
// H_a = H( E || 1 )
// else
// H_a = H( E || 2 )
std::vector<uint256> leaves;
leaves.reserve(2);
leaves.push_back(entropy);
leaves.push_back(fConfidential ? kTwo : kOne);
reissuanceToken = CAsset(ComputeFastMerkleRoot(leaves));
}
/** Add an issuance transaction to the genesis block. Typically used to pre-issue
* the policyAsset of a blockchain. The genesis block is not actually validated,
* so this transaction simply has to match issuance structure. */
void AppendInitialIssuance(CBlock& genesis_block, const COutPoint& prevout, const uint256& contract, const int64_t asset_outputs, const int64_t asset_values, const int64_t reissuance_outputs, const int64_t reissuance_values, const CScript& issuance_destination) {
uint256 entropy;
GenerateAssetEntropy(entropy, prevout, contract);
CAsset asset;
CalculateAsset(asset, entropy);
// Re-issuance of policyAsset is always unblinded
CAsset reissuance;
CalculateReissuanceToken(reissuance, entropy, false);
// Note: Genesis block isn't actually validated, outputs are entered into utxo db only
CMutableTransaction txNew;
txNew.nVersion = 1;
txNew.vin.resize(1);
txNew.vin[0].prevout = prevout;
txNew.vin[0].assetIssuance.assetEntropy = contract;
txNew.vin[0].assetIssuance.nAmount = CConfidentialValue(asset_values * asset_outputs);
txNew.vin[0].assetIssuance.nInflationKeys = CConfidentialValue(reissuance_values * reissuance_outputs);
for (unsigned int i = 0; i < asset_outputs; i++) {
txNew.vout.push_back(CTxOut(asset, CConfidentialValue(asset_values), issuance_destination));
}
for (unsigned int i = 0; i < reissuance_outputs; i++) {
txNew.vout.push_back(CTxOut(reissuance, CConfidentialValue(reissuance_values), issuance_destination));
}
genesis_block.vtx.push_back(MakeTransactionRef(std::move(txNew)));
genesis_block.hashMerkleRoot = BlockMerkleRoot(genesis_block);
}