Skip to content

Commit

Permalink
genesis block has actual fee issuance in regtest
Browse files Browse the repository at this point in the history
  • Loading branch information
instagibbs committed Nov 6, 2017
1 parent 65ed777 commit 9a9ac25
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 39 deletions.
8 changes: 6 additions & 2 deletions qa/rpc-tests/confidential_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ def run_test(self):

print("Assets tests...")

# Bitcoin is the first issuance
assert_equal(self.nodes[0].listissuances()[0]["assetlabel"], "bitcoin")
assert_equal(len(self.nodes[0].listissuances()), 1)

# Unblinded issuance of asset
issued = self.nodes[0].issueasset(1, 1, False)
assert_equal(self.nodes[0].getwalletinfo()["balance"][issued["asset"]], 1)
Expand Down Expand Up @@ -351,13 +355,13 @@ def run_test(self):
addr2 = txdet2[len(txdet2)-1]["address"]
addr3 = txdet3[len(txdet3)-1]["address"]

assert_equal(len(self.nodes[0].listissuances()), 5);
assert_equal(len(self.nodes[0].listissuances()), 6);
self.nodes[0].importaddress(addr1)
self.nodes[0].importaddress(addr2)
self.nodes[0].importaddress(addr3)

issuances = self.nodes[0].listissuances()
assert_equal(len(issuances), 8)
assert_equal(len(issuances), 9)

for issue in issuances:
if issue['txid'] == redata1["txid"] and issue['vin'] == redata1["vin"]:
Expand Down
16 changes: 6 additions & 10 deletions qa/rpc-tests/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,15 @@ def setup_network(self, split=False):

def run_test (self):

# Check that there's no UTXO on none of the nodes
assert_equal(len(self.nodes[0].listunspent()), 0)
assert_equal(len(self.nodes[1].listunspent()), 0)
assert_equal(len(self.nodes[2].listunspent()), 0)
# Check that there's 100 UTXOs on each of the nodes
assert_equal(len(self.nodes[0].listunspent()), 100)
assert_equal(len(self.nodes[1].listunspent()), 100)
assert_equal(len(self.nodes[2].listunspent()), 100)

print("Mining blocks...")

self.nodes[0].generate(1)
walletinfo = self.nodes[0].getwalletinfo()
assert_equal(walletinfo['immature_balance']["bitcoin"], 21000000)
assert("bitcoin" not in walletinfo['balance'])
assert_equal(walletinfo['balance']["bitcoin"], 21000000)

self.sync_all()
print("Mining blocks...")
self.nodes[1].generate(101)
self.sync_all()

Expand Down
52 changes: 41 additions & 11 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,15 @@ static CScript StrHexToScriptWithDefault(std::string strScript, const CScript de
return returnScript;
}

static CBlock CreateGenesisBlock(const Consensus::Params& params, const std::string& networkID, const CScript& genesisOutputScript, uint32_t nTime, const CScript& scriptChallenge, int32_t nVersion, const CAmount& genesisReward, const uint32_t rewardShards, const CAsset& asset)
static CBlock CreateGenesisBlock(const Consensus::Params& params, const std::string& networkID, uint32_t nTime, const CScript& scriptChallenge, int32_t nVersion)
{
// Shards must be evenly divisible
assert(MAX_MONEY % rewardShards == 0);
CMutableTransaction txNew;
txNew.nVersion = 1;
txNew.vin.resize(1);
txNew.vout.resize(rewardShards);
// Any consensus-related values that are command-line set can be added here for anti-footgun
txNew.vin[0].scriptSig = CScript(CommitToArguments(params, networkID, scriptChallenge));
for (unsigned int i = 0; i < rewardShards; i++) {
txNew.vout[i].nValue = genesisReward/rewardShards;
txNew.vout[i].nAsset = asset;
txNew.vout[i].scriptPubKey = genesisOutputScript;
}
txNew.vout.clear();
txNew.vout.push_back(CTxOut(CAsset(), 0, CScript() << OP_RETURN));

CBlock genesis;
genesis.nTime = nTime;
Expand All @@ -67,6 +61,41 @@ static CBlock CreateGenesisBlock(const Consensus::Params& params, const std::str
return genesis;
}

/** 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. */
static 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 = asset_values*asset_outputs;
txNew.vin[0].assetIssuance.nInflationKeys = reissuance_values*reissuance_outputs;

for (unsigned int i = 0; i < asset_outputs; i++) {
txNew.vout.push_back(CTxOut(asset, asset_values, issuance_destination));
}
for (unsigned int i = 0; i < reissuance_outputs; i++) {
txNew.vout.push_back(CTxOut(reissuance, reissuance_values, issuance_destination));
}

genesis_block.vtx.push_back(MakeTransactionRef(std::move(txNew)));
genesis_block.hashMerkleRoot = BlockMerkleRoot(genesis_block);
}

void CChainParams::UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
consensus.vDeployments[d].nStartTime = nStartTime;
Expand Down Expand Up @@ -149,7 +178,7 @@ class CElementsParams : public CChainParams {
CalculateAsset(consensus.pegged_asset, entropy);

CScript scriptDestination(CScript() << std::vector<unsigned char>(parentGenesisBlockHash.begin(), parentGenesisBlockHash.end()) << OP_WITHDRAWPROOFVERIFY);
genesis = CreateGenesisBlock(consensus, strNetworkID, scriptDestination, 1231006505, genesisChallengeScript, 1, MAX_MONEY, 100, consensus.pegged_asset);
genesis = CreateGenesisBlock(consensus, strNetworkID, 1231006505, genesisChallengeScript, 1);
consensus.hashGenesisBlock = genesis.GetHash();

scriptCoinbaseDestination = CScript() << ParseHex("0229536c4c83789f59c30b93eb40d4abbd99b8dcc99ba8bd748f29e33c1d279e3c") << OP_CHECKSIG;
Expand Down Expand Up @@ -259,7 +288,8 @@ class CRegTestParams : public CChainParams {
GenerateAssetEntropy(entropy, COutPoint(uint256(commit), 0), parentGenesisBlockHash);
CalculateAsset(consensus.pegged_asset, entropy);

genesis = CreateGenesisBlock(consensus, strNetworkID, defaultRegtestScript, 1296688602, genesisChallengeScript, 1, MAX_MONEY, 100, consensus.pegged_asset);
genesis = CreateGenesisBlock(consensus, strNetworkID, 1296688602, genesisChallengeScript, 1);
AppendInitialIssuance(genesis, COutPoint(uint256(commit), 0), parentGenesisBlockHash, 100, 21000000000000, 0, 0, CScript() << OP_TRUE);
consensus.hashGenesisBlock = genesis.GetHash();


Expand Down
17 changes: 10 additions & 7 deletions src/test/test_bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha

RegisterAllCoreRPCCommands(tableRPC);

// Make genesis coinbase use out spend-key
int gen_size = Params().GenesisBlock().vtx.size();

// Make genesis second transaction(with spendable outputs) use out spend-key
coinbaseKey.MakeNewKey(true);
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
CMutableTransaction newCoinbase(*(Params().GenesisBlock().vtx[0]));
for (unsigned int i = 0; i < Params().GenesisBlock().vtx[0]->vout.size(); i++)
newCoinbase.vout[i].scriptPubKey = scriptPubKey;
const_cast<CBlock&>(Params().GenesisBlock()).vtx[0] = MakeTransactionRef(newCoinbase);
CMutableTransaction newTransaction(*(Params().GenesisBlock().vtx[gen_size-1]));
for (unsigned int i = 0; i < Params().GenesisBlock().vtx[gen_size-1]->vout.size(); i++)
newTransaction.vout[i].scriptPubKey = scriptPubKey;
const_cast<CBlock&>(Params().GenesisBlock()).vtx[gen_size-1] = MakeTransactionRef(newTransaction);
const_cast<CBlock&>(Params().GenesisBlock()).hashMerkleRoot = BlockMerkleRoot(Params().GenesisBlock());
const_cast<CBlock&>(Params().GenesisBlock()).proof = CProof(CScript()<<OP_TRUE, CScript());
const_cast<Consensus::Params&>(Params().GetConsensus()).hashGenesisBlock = Params().GenesisBlock().GetHash();
Expand Down Expand Up @@ -114,8 +116,9 @@ TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
{
// Generate a 100-block chain:
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
assert(Params().GenesisBlock().vtx[0]->vout[0].scriptPubKey == scriptPubKey);
coinbaseTxns.push_back(*(Params().GenesisBlock().vtx[0]));
assert(Params().GenesisBlock().vtx[Params().GenesisBlock().vtx.size()-1]->vout[0].scriptPubKey == scriptPubKey);
// Get spendable outputs from genesis block, which is non-coinbase for regtest
coinbaseTxns.push_back(*(Params().GenesisBlock().vtx[Params().GenesisBlock().vtx.size()-1]));
for (int i = 0; i < COINBASE_MATURITY; i++)
{
std::vector<CMutableTransaction> noTxns;
Expand Down
15 changes: 6 additions & 9 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2267,19 +2267,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
assert(hashPrevBlock == view.GetBestBlock());

// Gesesis coinbase *is* spendable
// Add genesis outputs. The assumption made here is that there are no real spends
// occurring in this block.
if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) {
if (!fJustCheck) {
assert(block.vtx.size() == 1);
assert(block.nHeight == 0);
for (const auto& tx : block.vtx) {

std::vector<std::pair<uint256, CDiskTxPos> > vPos;
std::multimap<uint256, std::pair<COutPoint, CAmount> > mLocksCreated;
const CTransaction tx = *(block.vtx[0]);

CTxUndo undoDummy;
UpdateCoins(tx, view, undoDummy, pindex->nHeight);

// Directly add new coins to DB
view.ModifyNewCoins(tx->GetHash(), tx->IsCoinBase())->FromTx(*tx, pindex->nHeight);
}
view.SetBestBlock(pindex->GetBlockHash());
}
return true;
Expand Down

0 comments on commit 9a9ac25

Please sign in to comment.