Skip to content

Commit

Permalink
Make spark coinbase imature untill 100blocks passed
Browse files Browse the repository at this point in the history
  • Loading branch information
levonpetrosyan93 committed Nov 11, 2024
1 parent dc29f5b commit 05d5c84
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 48 deletions.
14 changes: 12 additions & 2 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ class CBlockIndex
//! Map id to <hash of the set>
std::map<int, std::vector<unsigned char>> anonymitySetHash;
//! Map id to spark coin
std::map<int, std::vector<spark::Coin>> sparkMintedCoins;
std::map<int, std::vector<std::pair<spark::Coin, bool>>> sparkMintedCoins;
//! Map id to <hash of the set>
std::map<int, std::vector<unsigned char>> sparkSetHash;
//! map spark coin S to tx hash, this is used when you run with -mobile
Expand Down Expand Up @@ -560,7 +560,17 @@ class CDiskBlockIndex : public CBlockIndex

if (!(s.GetType() & SER_GETHASH)
&& nHeight >= params.nSparkStartBlock) {
READWRITE(sparkMintedCoins);
if (nHeight >=params.nSparkCoinbase) {
READWRITE(sparkMintedCoins);
} else {
std::map<int, std::vector<spark::Coin>> sparkCoins;
READWRITE(sparkCoins);
for (auto& itr : sparkCoins) {
sparkMintedCoins[itr.first].reserve(itr.second.size());
for (auto& mint : itr.second)
sparkMintedCoins[itr.first].emplace_back(std::make_pair(mint, false));
}
}
READWRITE(sparkSetHash);
READWRITE(spentLTags);

Expand Down
4 changes: 2 additions & 2 deletions src/libspark/coin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ IdentifiedCoinData Coin::identify(const IncomingViewKey& incoming_view_key) {
IdentifiedCoinData data;

// Deserialization means this process depends on the coin type
if (this->type == COIN_TYPE_MINT) {
if (this->type == COIN_TYPE_MINT || this->type == COIN_TYPE_COINBASE) {
MintCoinRecipientData r;

try {
Expand Down Expand Up @@ -225,7 +225,7 @@ void Coin::setParams(const Params* params) {
}

bool Coin::isValidMNPayment(const spark::Address& addr, const std::vector<unsigned char>& serialContext) const {
Coin c(this->params, COIN_TYPE_MINT, k, addr, v, "BlockReward", serial_context);
Coin c(this->params, COIN_TYPE_COINBASE, k, addr, v, "BlockReward", serial_context);
return this->getHash() == c.getHash();
}

Expand Down
2 changes: 1 addition & 1 deletion src/libspark/mint_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ MintTransaction::MintTransaction(
k.randomize();
this->coins.emplace_back(Coin(
this->params,
COIN_TYPE_MINT,
output.type,
k,
output.address,
output.v,
Expand Down
1 change: 1 addition & 0 deletions src/libspark/mint_transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct MintedCoinData {
Address address;
uint64_t v;
std::string memo;
char type;
};

class MintTransaction {
Expand Down
1 change: 1 addition & 0 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
if (spark::IsPayToSparkAddress(out.scriptPubKey)) {
spark::MintedCoinData mintedCoinData;
mintedCoinData.v = out.nValue;
mintedCoinData.type = spark::COIN_TYPE_COINBASE;
std::vector<unsigned char> vch(out.scriptPubKey.begin() + 2, out.scriptPubKey.end() - 1);
try {
mintedCoinData.address.fromByteVector(vch);
Expand Down
35 changes: 28 additions & 7 deletions src/spark/sparkwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

const uint32_t DEFAULT_SPARK_NCOUNT = 1;

CSparkWallet::CSparkWallet(const std::string& strWalletFile) {
CSparkWallet::CSparkWallet(const std::string& strWalletFile, const uint32_t& height) {

CWalletDB walletdb(strWalletFile);
this->strWalletFile = strWalletFile;
Expand Down Expand Up @@ -77,6 +77,8 @@ CSparkWallet::CSparkWallet(const std::string& strWalletFile) {

if (fWalletJustUnlocked)
pwalletMain->Lock();

this->height = height;
}

CSparkWallet::~CSparkWallet() {
Expand Down Expand Up @@ -108,6 +110,9 @@ CAmount CSparkWallet::getAvailableBalance() {
if (mint.nHeight < 1)
continue;

if (mint.type == spark::COIN_TYPE_COINBASE && (height - mint.nHeight) < COINBASE_MATURITY)
continue;

result += mint.v;
}

Expand All @@ -123,7 +128,10 @@ CAmount CSparkWallet::getUnconfirmedBalance() {
continue;

// Continue if confirmed
if (mint.nHeight > 1)
if (mint.nHeight > 1 && mint.type != spark::COIN_TYPE_COINBASE)
continue;

if (mint.type == spark::COIN_TYPE_COINBASE && (height - mint.nHeight) > COINBASE_MATURITY)
continue;

result += mint.v;
Expand Down Expand Up @@ -152,6 +160,9 @@ CAmount CSparkWallet::getAddressAvailableBalance(const spark::Address& address)
if (address.get_d() != mint.d)
continue;

if (mint.type == spark::COIN_TYPE_COINBASE && (height - mint.nHeight) < COINBASE_MATURITY)
continue;

result += mint.v;
}

Expand All @@ -175,6 +186,9 @@ CAmount CSparkWallet::getAddressUnconfirmedBalance(const spark::Address& address
continue;

result += mint.v;

if (mint.type == spark::COIN_TYPE_COINBASE && (height - mint.nHeight) > COINBASE_MATURITY)
continue;
}

return result;
Expand Down Expand Up @@ -297,7 +311,7 @@ std::vector<CSparkMintMeta> CSparkWallet::ListSparkMints(bool fUnusedOnly, bool
continue;

// Not confirmed
if (fMatureOnly && mint.nHeight < 1)
if (fMatureOnly && (mint.nHeight < 1 || (mint.type == spark::COIN_TYPE_COINBASE && (height - mint.nHeight) < COINBASE_MATURITY)))
continue;

setMints.push_back(mint);
Expand Down Expand Up @@ -488,6 +502,7 @@ void CSparkWallet::UpdateSpendStateFromMempool(const std::vector<GroupElement>&
}

void CSparkWallet::UpdateSpendStateFromBlock(const CBlock& block) {
height = block.nHeight;
const auto& transactions = block.vtx;
((ParallelOpThreadPool<void>*)threadPool)->PostTask([=]() {
LOCK(cs_spark_wallet);
Expand Down Expand Up @@ -647,11 +662,11 @@ void CSparkWallet::UpdateMintStateFromBlock(const CBlock& block) {
});
}

void CSparkWallet::RemoveSparkMints(const std::vector<spark::Coin>& mints) {
void CSparkWallet::RemoveSparkMints(const std::vector<std::pair<spark::Coin, bool>>& mints) {
for (auto coin : mints) {
try {
spark::IdentifiedCoinData identifiedCoinData = coin.identify(this->viewKey);
spark::RecoveredCoinData recoveredCoinData = coin.recover(this->fullViewKey, identifiedCoinData);
spark::IdentifiedCoinData identifiedCoinData = coin.first.identify(this->viewKey);
spark::RecoveredCoinData recoveredCoinData = coin.first.recover(this->fullViewKey, identifiedCoinData);

CWalletDB walletdb(strWalletFile);
uint256 lTagHash = primitives::GetLTagHash(recoveredCoinData.T);
Expand Down Expand Up @@ -679,7 +694,11 @@ void CSparkWallet::RemoveSparkSpends(const std::unordered_map<GroupElement, int>
}

void CSparkWallet::AbandonSparkMints(const std::vector<spark::Coin>& mints) {
RemoveSparkMints(mints);
std::vector<std::pair<spark::Coin, bool>> mints_;
mints_.reserve(mints.size());
for (auto& mint : mints)
mints_.emplace_back(std::make_pair(mint, false));
RemoveSparkMints(mints_);
}

void CSparkWallet::AbandonSpends(const std::vector<GroupElement>& spends) {
Expand Down Expand Up @@ -850,6 +869,7 @@ bool CSparkWallet::CreateSparkMintTransactions(
if (autoMintAll) {
spark::MintedCoinData mintedCoinData;
mintedCoinData.v = mintedValue;
mintedCoinData.type = spark::COIN_TYPE_MINT;
mintedCoinData.memo = "";
mintedCoinData.address = getDefaultAddress();
singleTxOutputs.push_back(mintedCoinData);
Expand All @@ -860,6 +880,7 @@ bool CSparkWallet::CreateSparkMintTransactions(
uint64_t singleMintValue = std::min(remainingMintValue, remainingOutputs.begin()->v);
spark::MintedCoinData mintedCoinData;
mintedCoinData.v = singleMintValue;
mintedCoinData.type = spark::COIN_TYPE_MINT;
mintedCoinData.address = remainingOutputs.begin()->address;
mintedCoinData.memo = remainingOutputs.begin()->memo;
singleTxOutputs.push_back(mintedCoinData);
Expand Down
6 changes: 4 additions & 2 deletions src/spark/sparkwallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const uint32_t SPARK_CHANGE_D = 0x270F;

class CSparkWallet {
public:
CSparkWallet(const std::string& strWalletFile);
CSparkWallet(const std::string& strWalletFile, const uint32_t& height);
~CSparkWallet();
// increment diversifier and generate address for that
spark::Address generateNextAddress();
Expand Down Expand Up @@ -98,7 +98,7 @@ class CSparkWallet {
void UpdateMintState(const std::vector<spark::Coin>& coins, const uint256& txHash, CWalletDB& walletdb);
void UpdateMintStateFromMempool(const std::vector<spark::Coin>& coins, const uint256& txHash);
void UpdateMintStateFromBlock(const CBlock& block);
void RemoveSparkMints(const std::vector<spark::Coin>& mints);
void RemoveSparkMints(const std::vector<std::pair<spark::Coin, bool>>& mints);
void RemoveSparkSpends(const std::unordered_map<GroupElement, int>& spends);
void AbandonSparkMints(const std::vector<spark::Coin>& mints);
void AbandonSpends(const std::vector<GroupElement>& spends);
Expand Down Expand Up @@ -163,6 +163,8 @@ class CSparkWallet {
std::unordered_map<uint256, CSparkMintMeta> coinMeta;

void* threadPool;

uint32_t height;
};


Expand Down
44 changes: 27 additions & 17 deletions src/spark/state.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "state.h"
#include "../validation.h"
#include "../batchproof_container.h"
#include "../consensus/consensus.h"

namespace spark {

Expand Down Expand Up @@ -438,7 +439,8 @@ bool CheckSparkMintTransaction(
CValidationState &state,
uint256 hashTx,
bool fStatefulSigmaCheck,
CSparkTxInfo* sparkTxInfo) {
CSparkTxInfo* sparkTxInfo,
bool isCoinbase) {

LogPrintf("CheckSparkMintTransaction txHash = %s\n", hashTx.GetHex());
const spark::Params* params = spark::Params::get_default();
Expand Down Expand Up @@ -490,7 +492,7 @@ bool CheckSparkMintTransaction(

if (sparkTxInfo != NULL && !sparkTxInfo->fInfoIsComplete) {
// Update coin list in the info
sparkTxInfo->mints.push_back(coin);
sparkTxInfo->mints.push_back(std::make_pair(coin, isCoinbase));
sparkTxInfo->spTransactions.insert(hashTx);
}
}
Expand Down Expand Up @@ -526,7 +528,7 @@ bool CheckSparkSMintTransaction(
for (auto& coin : out_coins) {
if (sparkTxInfo != NULL && !sparkTxInfo->fInfoIsComplete) {
// Update coin list in the info
sparkTxInfo->mints.push_back(coin);
sparkTxInfo->mints.push_back(std::make_pair(coin, false));
}
}

Expand Down Expand Up @@ -641,6 +643,7 @@ bool CheckSparkSpendTransaction(
// find index for block with hash of accumulatorBlockHash or set index to the coinGroup.firstBlock if not found
while (index != coinGroup.firstBlock && index->GetBlockHash() != idAndHash.second)
index = index->pprev;
CBlockIndex *lastBlock = index;

// take the hash from last block of anonymity set
std::vector<unsigned char> set_hash = GetAnonymitySetHash(index, idAndHash.first);
Expand All @@ -664,8 +667,11 @@ bool CheckSparkSpendTransaction(
const auto& coin,
index->sparkMintedCoins[id]) {
set_size++;
if (!useBatching)
cover_set.push_back(coin);
if (!useBatching) {
if ((coin.second && lastBlock->nHeight > COINBASE_MATURITY) || !coin.second) {
cover_set.push_back(coin.first);
}
}
}
}
}
Expand Down Expand Up @@ -783,7 +789,7 @@ bool CheckSparkTransaction(
}
if (!txOuts.empty()) {
try {
if (!CheckSparkMintTransaction(txOuts, state, hashTx, fStatefulSigmaCheck, sparkTxInfo)) {
if (!CheckSparkMintTransaction(txOuts, state, hashTx, fStatefulSigmaCheck, sparkTxInfo, tx.IsCoinBase())) {
LogPrintf("CheckSparkTransaction::Mint verification failed.\n");
return false;
}
Expand Down Expand Up @@ -1055,7 +1061,7 @@ void CSparkState::AddMintsToStateAndBlockIndex(
CBlockIndex *index,
const CBlock* pblock) {

std::vector<spark::Coin> blockMints = pblock->sparkTxInfo->mints;
std::vector<std::pair<spark::Coin, bool>> blockMints = pblock->sparkTxInfo->mints;

latestCoinId = std::max(1, latestCoinId);
auto &coinGroup = coinGroups[latestCoinId];
Expand Down Expand Up @@ -1086,18 +1092,18 @@ void CSparkState::AddMintsToStateAndBlockIndex(
}

for (const auto& mint : blockMints) {
AddMint(mint, CMintedCoinInfo::make(latestCoinId, index->nHeight));
AddMint(mint.first, CMintedCoinInfo::make(latestCoinId, index->nHeight));
LogPrintf("AddMintsToStateAndBlockIndex: Spark mint added id=%d\n", latestCoinId);
index->sparkMintedCoins[latestCoinId].push_back(mint);
if (GetBoolArg("-mobile", false)) {
COutPoint outPoint;
GetOutPointFromBlock(outPoint, mint, *pblock);
GetOutPointFromBlock(outPoint, mint.first, *pblock);
CTransactionRef tx;
for (CTransactionRef itr : pblock->vtx) {
if (outPoint.hash == itr->GetHash())
tx = itr;
}
index->sparkTxHashContext[mint.S] = {outPoint.hash, getSerialContext(*tx)};
index->sparkTxHashContext[mint.first.S] = {outPoint.hash, getSerialContext(*tx)};
}
}
}
Expand Down Expand Up @@ -1142,7 +1148,7 @@ void CSparkState::AddBlock(CBlockIndex *index) {

latestCoinId = coins.first;
for (auto const &coin : coins.second) {
AddMint(coin, CMintedCoinInfo::make(coins.first, index->nHeight));
AddMint(coin.first, CMintedCoinInfo::make(coins.first, index->nHeight));
}
}

Expand Down Expand Up @@ -1208,7 +1214,7 @@ void CSparkState::RemoveBlock(CBlockIndex *index) {
// roll back mints
for (auto const&coins : index->sparkMintedCoins) {
for (auto const& coin : coins.second) {
auto mintCoins = GetMints().equal_range(coin);
auto mintCoins = GetMints().equal_range(coin.first);
auto coinIt = find_if(
mintCoins.first, mintCoins.second,
[&coins](const std::unordered_map<spark::Coin, CMintedCoinInfo, spark::CoinHash>::value_type& v) {
Expand Down Expand Up @@ -1327,7 +1333,9 @@ int CSparkState::GetCoinSetForSpend(
numberOfCoins += block->sparkMintedCoins[id].size();
if (block->sparkMintedCoins.count(id) > 0) {
for (const auto &coin : block->sparkMintedCoins[id]) {
coins_out.push_back(coin);
if ((coin.second && coinGroup.lastBlock->nHeight > COINBASE_MATURITY) || !coin.second) {
coins_out.push_back(coin.first);
}
}
}
}
Expand Down Expand Up @@ -1379,10 +1387,12 @@ void CSparkState::GetCoinsForRecovery(
numberOfCoins += block->sparkMintedCoins[id].size();
if (block->sparkMintedCoins.count(id) > 0) {
for (const auto &coin : block->sparkMintedCoins[id]) {
std::pair<uint256, std::vector<unsigned char>> txHashContext;
if (block->sparkTxHashContext.count(coin.S))
txHashContext = block->sparkTxHashContext[coin.S];
coins.push_back({coin, txHashContext});
if ((coin.second && coinGroup.lastBlock->nHeight > COINBASE_MATURITY) || !coin.second) {
std::pair<uint256, std::vector<unsigned char>> txHashContext;
if (block->sparkTxHashContext.count(coin.first.S))
txHashContext = block->sparkTxHashContext[coin.first.S];
coins.push_back({coin.first, txHashContext});
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/spark/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class CSparkTxInfo {
// all the spark transactions encountered so far
std::set<uint256> spTransactions;

// Vector of all mints
std::vector<spark::Coin> mints;
// Vector of all mints, paired with bool,indicating if it is coinbase or not
std::vector<std::pair<spark::Coin, bool>> mints;

// linking tag for every spend (map from lTag to coin group id)
std::unordered_map<GroupElement, int> spentLTags;
Expand Down
Loading

0 comments on commit 05d5c84

Please sign in to comment.