Skip to content

Commit 7277289

Browse files
committed
Try to stake shield notes
1 parent a73c70d commit 7277289

File tree

11 files changed

+137
-72
lines changed

11 files changed

+137
-72
lines changed

src/blockassembler.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "policy/policy.h"
2020
#include "pow.h"
2121
#include "primitives/transaction.h"
22+
#include "sapling/saplingscriptpubkeyman.h"
2223
#include "spork.h"
2324
#include "timedata.h"
2425
#include "util/system.h"
@@ -66,8 +67,7 @@ static CMutableTransaction NewCoinbase(const int nHeight, const CScript* pScript
6667
return txCoinbase;
6768
}
6869

69-
bool SolveProofOfStake(CBlock* pblock, CBlockIndex* pindexPrev, CWallet* pwallet,
70-
std::vector<CStakeableOutput>* availableCoins, bool stopPoSOnNewBlock)
70+
bool SolveProofOfStake(CBlock* pblock, CBlockIndex* pindexPrev, CWallet* pwallet, std::vector<CStakeableOutput>* availableCoins, std::vector<CStakeableShieldNote>* availableShieldNotes, bool stopPoSOnNewBlock)
7171
{
7272
boost::this_thread::interruption_point();
7373

@@ -80,12 +80,12 @@ bool SolveProofOfStake(CBlock* pblock, CBlockIndex* pindexPrev, CWallet* pwallet
8080
CMutableTransaction txCoinStake;
8181
int64_t nTxNewTime = 0;
8282
if (!pwallet->CreateCoinStake(pindexPrev,
83-
pblock->nBits,
84-
txCoinStake,
85-
nTxNewTime,
86-
availableCoins,
87-
stopPoSOnNewBlock
88-
)) {
83+
pblock->nBits,
84+
txCoinStake,
85+
nTxNewTime,
86+
availableCoins,
87+
availableShieldNotes,
88+
stopPoSOnNewBlock)) {
8989
LogPrint(BCLog::STAKING, "%s : stake not found\n", __func__);
9090
return false;
9191
}
@@ -156,14 +156,15 @@ void BlockAssembler::resetBlock()
156156
}
157157

158158
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn,
159-
CWallet* pwallet,
160-
bool fProofOfStake,
161-
std::vector<CStakeableOutput>* availableCoins,
162-
bool fNoMempoolTx,
163-
bool fTestValidity,
164-
CBlockIndex* prevBlock,
165-
bool stopPoSOnNewBlock,
166-
bool fIncludeQfc)
159+
CWallet* pwallet,
160+
bool fProofOfStake,
161+
std::vector<CStakeableOutput>* availableCoins,
162+
std::vector<CStakeableShieldNote>* availableShieldNotes,
163+
bool fNoMempoolTx,
164+
bool fTestValidity,
165+
CBlockIndex* prevBlock,
166+
bool stopPoSOnNewBlock,
167+
bool fIncludeQfc)
167168
{
168169
resetBlock();
169170

@@ -187,8 +188,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
187188
}
188189

189190
// Depending on the tip height, try to find a coinstake who solves the block or create a coinbase tx.
190-
if (!(fProofOfStake ? SolveProofOfStake(pblock, pindexPrev, pwallet, availableCoins, stopPoSOnNewBlock)
191-
: CreateCoinbaseTx(pblock, scriptPubKeyIn, pindexPrev))) {
191+
if (!(fProofOfStake ? SolveProofOfStake(pblock, pindexPrev, pwallet, availableCoins, availableShieldNotes, stopPoSOnNewBlock) : CreateCoinbaseTx(pblock, scriptPubKeyIn, pindexPrev))) {
192192
return nullptr;
193193
}
194194

src/blockassembler.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#define PIVX_BLOCKASSEMBLER_H
99

1010
#include "primitives/block.h"
11+
#include "sapling/saplingscriptpubkeyman.h"
12+
#include "stakeinput.h"
1113
#include "txmempool.h"
1214

1315
#include <stdint.h>
@@ -163,14 +165,15 @@ class BlockAssembler
163165
BlockAssembler(const CChainParams& chainparams, const bool defaultPrintPriority);
164166
/** Construct a new block template with coinbase to scriptPubKeyIn */
165167
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn,
166-
CWallet* pwallet = nullptr,
167-
bool fProofOfStake = false,
168-
std::vector<CStakeableOutput>* availableCoins = nullptr,
169-
bool fNoMempoolTx = false,
170-
bool fTestValidity = true,
171-
CBlockIndex* prevBlock = nullptr,
172-
bool stopPoSOnNewBlock = true,
173-
bool fIncludeQfc = true);
168+
CWallet* pwallet = nullptr,
169+
bool fProofOfStake = false,
170+
std::vector<CStakeableOutput>* availableCoins = nullptr,
171+
std::vector<CStakeableShieldNote>* availableShieldNotes = nullptr,
172+
bool fNoMempoolTx = false,
173+
bool fTestValidity = true,
174+
CBlockIndex* prevBlock = nullptr,
175+
bool stopPoSOnNewBlock = true,
176+
bool fIncludeQfc = true);
174177

175178
private:
176179
// utility functions

src/kernel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ CStakeKernel::CStakeKernel(const CBlockIndex* const pindexPrev, CStakeInput* sta
4848
nTimeBlockFrom = pindexFrom->nTime;
4949
} else {
5050
if (!Params().GetConsensus().NetworkUpgradeActive(pindexPrev->nHeight + 1, Consensus::UPGRADE_SHIELD_STAKING)) {
51+
std::cout << "Data: " << stakeInput->GetValue() << std::endl;
5152
LogPrintf("%s : ShieldStaking is not yet active!", __func__);
5253
} else {
5354
stakeModifier << pindexPrev->GetStakeModifierV2();

src/miner.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ bool ProcessBlockFound(const std::shared_ptr<const CBlock>& pblock, CWallet& wal
9696
bool fGenerateBitcoins = false;
9797
bool fStakeableCoins = false;
9898

99-
void CheckForCoins(CWallet* pwallet, std::vector<CStakeableOutput>* availableCoins)
99+
void CheckForCoins(CWallet* pwallet, std::vector<CStakeableOutput>* availableCoins, std::vector<CStakeableShieldNote>* availableShieldNotes)
100100
{
101101
if (!pwallet || !pwallet->pStakerStatus)
102102
return;
@@ -108,6 +108,7 @@ void CheckForCoins(CWallet* pwallet, std::vector<CStakeableOutput>* availableCoi
108108
return;
109109
}
110110
fStakeableCoins = pwallet->StakeableCoins(availableCoins);
111+
pwallet->StakeableShieldNotes(availableShieldNotes);
111112
}
112113

113114
void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
@@ -123,6 +124,7 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
123124

124125
// Available UTXO set
125126
std::vector<CStakeableOutput> availableCoins;
127+
std::vector<CStakeableShieldNote> availableShieldNotes;
126128
unsigned int nExtraNonce = 0;
127129

128130
while (fGenerateBitcoins || fProofOfStake) {
@@ -139,13 +141,13 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
139141
}
140142

141143
// update fStakeableCoins
142-
CheckForCoins(pwallet, &availableCoins);
144+
CheckForCoins(pwallet, &availableCoins, &availableShieldNotes);
143145

144146
while ((g_connman && g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0 && Params().MiningRequiresPeers())
145147
|| pwallet->IsLocked() || !fStakeableCoins || masternodeSync.NotCompleted()) {
146148
MilliSleep(5000);
147149
// Do another check here to ensure fStakeableCoins is updated
148-
if (!fStakeableCoins) CheckForCoins(pwallet, &availableCoins);
150+
if (!fStakeableCoins) CheckForCoins(pwallet, &availableCoins, &availableShieldNotes);
149151
}
150152

151153
//search our map of hashed blocks, see if bestblock has been hashed yet
@@ -168,8 +170,8 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
168170
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
169171

170172
std::unique_ptr<CBlockTemplate> pblocktemplate((fProofOfStake ?
171-
BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(CScript(), pwallet, true, &availableCoins) :
172-
CreateNewBlockWithKey(pReservekey, pwallet)));
173+
BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(CScript(), pwallet, true, &availableCoins, &availableShieldNotes) :
174+
CreateNewBlockWithKey(pReservekey, pwallet)));
173175
if (!pblocktemplate) continue;
174176
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
175177

src/rpc/mining.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ UniValue generateBlocks(const Consensus::Params& consensus,
4242

4343
// Get available coins
4444
std::vector<CStakeableOutput> availableCoins;
45+
std::vector<CStakeableShieldNote> availableShieldNotes;
46+
pwallet->StakeableShieldNotes(&availableShieldNotes);
4547
if (fPoS && !pwallet->StakeableCoins(&availableCoins)) {
4648
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "No available coins to stake");
4749
}
4850

4951
std::unique_ptr<CBlockTemplate> pblocktemplate(fPoS ?
50-
BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(CScript(), pwallet, true, &availableCoins) :
51-
CreateNewBlockWithScript(*coinbaseScript, pwallet));
52+
BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(CScript(), pwallet, true, &availableCoins, &availableShieldNotes) :
53+
CreateNewBlockWithScript(*coinbaseScript, pwallet));
5254
if (!pblocktemplate.get()) break;
5355
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
5456

src/sapling/saplingscriptpubkeyman.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ void SaplingScriptPubKeyMan::GetFilteredNotes(
541541
}
542542
}
543543
}
544-
void SaplingScriptPubKeyMan::GetStakableNotes(std::vector<CShieldStake>& shieldInputs, int minDepth)
544+
void SaplingScriptPubKeyMan::GetStakeableNotes(std::vector<CStakeableShieldNote>* shieldInputs, int minDepth)
545545
{
546546
LOCK(wallet->cs_wallet);
547547
for (auto& p : wallet->mapWallet) {
@@ -580,7 +580,8 @@ void SaplingScriptPubKeyMan::GetStakableNotes(std::vector<CShieldStake>& shieldI
580580
if (nd.nullifier && IsSaplingSpent(*nd.nullifier)) {
581581
continue;
582582
}
583-
shieldInputs.emplace_back(CShieldStake(note.value(), *nd.nullifier));
583+
SaplingNoteEntry noteEntry = SaplingNoteEntry(op, pa, note, notePt.memo(), depth);
584+
shieldInputs->emplace_back(CStakeableShieldNote(noteEntry, *nd.nullifier));
584585
}
585586
}
586587
}

src/sapling/saplingscriptpubkeyman.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ struct SaplingNoteEntry
3737
int confirmations;
3838
};
3939

40+
struct CStakeableShieldNote {
41+
explicit CStakeableShieldNote(const SaplingNoteEntry& _note, const uint256 _nullifier) : note(_note), nullifier(_nullifier) {}
42+
SaplingNoteEntry note;
43+
uint256 nullifier;
44+
};
45+
4046
class SaplingNoteData
4147
{
4248
public:
@@ -295,7 +301,7 @@ class SaplingScriptPubKeyMan {
295301
bool ignoreLocked=true) const;
296302

297303
/* Return a list of notes that are stakable */
298-
void GetStakableNotes(std::vector<CShieldStake>& shieldInputs, int minDepth);
304+
void GetStakeableNotes(std::vector<CStakeableShieldNote>* shieldInputs, int minDepth);
299305

300306
/* Return list of available notes grouped by sapling address. */
301307
std::map<libzcash::SaplingPaymentAddress, std::vector<SaplingNoteEntry>> ListNotes() const;

src/test/test_pivx.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,17 @@ CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns,
201201
CBlockIndex* customPrevBlock)
202202
{
203203
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
204-
Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptPubKey,
205-
nullptr, // wallet
206-
false, // fProofOfStake
207-
nullptr, // availableCoins
208-
fNoMempoolTx,
209-
fTestBlockValidity,
210-
customPrevBlock,
211-
true,
212-
fIncludeQfc);
204+
Params(), DEFAULT_PRINTPRIORITY)
205+
.CreateNewBlock(scriptPubKey,
206+
nullptr, // wallet
207+
false, // fProofOfStake
208+
nullptr, // availableCoins
209+
nullptr, // availableShieldCoins
210+
fNoMempoolTx,
211+
fTestBlockValidity,
212+
customPrevBlock,
213+
true,
214+
fIncludeQfc);
213215
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
214216

215217
// Add passed-in txns:

src/wallet/test/pos_validations_tests.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,17 @@ BOOST_FIXTURE_TEST_CASE(coinstake_tests, TestPoSChainSetup)
4444

4545
// Let's create the block
4646
std::vector<CStakeableOutput> availableCoins;
47+
std::vector<CStakeableShieldNote> availableShieldNotes;
4748
BOOST_CHECK(pwalletMain->StakeableCoins(&availableCoins));
49+
pwalletMain->StakeableShieldNotes(&availableShieldNotes);
4850
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
49-
Params(), false).CreateNewBlock(CScript(),
50-
pwalletMain.get(),
51-
true,
52-
&availableCoins,
53-
true);
51+
Params(), false)
52+
.CreateNewBlock(CScript(),
53+
pwalletMain.get(),
54+
true,
55+
&availableCoins,
56+
&availableShieldNotes,
57+
true);
5458
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
5559
BOOST_CHECK(pblock->IsProofOfStake());
5660

@@ -143,8 +147,9 @@ std::shared_ptr<CBlock> CreateBlockInternal(CWallet* pwalletMain, const std::vec
143147
std::initializer_list<std::shared_ptr<CBlock>> forkchain = {})
144148
{
145149
std::vector<CStakeableOutput> availableCoins;
150+
std::vector<CStakeableShieldNote> availableShieldNotes;
146151
BOOST_CHECK(pwalletMain->StakeableCoins(&availableCoins));
147-
152+
pwalletMain->StakeableShieldNotes(&availableShieldNotes);
148153
// Remove any utxo which is not deeper than 120 blocks (for the same reasoning
149154
// used when selecting tx inputs in CreateAndCommitTx)
150155
// Also, as the wallet is not prepared to follow several chains at the same time,
@@ -160,14 +165,16 @@ std::shared_ptr<CBlock> CreateBlockInternal(CWallet* pwalletMain, const std::vec
160165
}
161166

162167
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(
163-
Params(), false).CreateNewBlock(CScript(),
164-
pwalletMain,
165-
true,
166-
&availableCoins,
167-
true,
168-
false,
169-
customPrevBlock,
170-
false);
168+
Params(), false)
169+
.CreateNewBlock(CScript(),
170+
pwalletMain,
171+
true,
172+
&availableCoins,
173+
&availableShieldNotes,
174+
true,
175+
false,
176+
customPrevBlock,
177+
false);
171178
BOOST_ASSERT(pblocktemplate);
172179
auto pblock = std::make_shared<CBlock>(pblocktemplate->block);
173180
if (!txns.empty()) {

src/wallet/wallet.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,6 +2695,12 @@ bool CWallet::StakeableCoins(std::vector<CStakeableOutput>* pCoins)
26952695
return (pCoins && !pCoins->empty());
26962696
}
26972697

2698+
void CWallet::StakeableShieldNotes(std::vector<CStakeableShieldNote>* shieldCoins)
2699+
{
2700+
shieldCoins->clear();
2701+
m_sspk_man->GetStakeableNotes(shieldCoins, Params().GetConsensus().nStakeMinDepth);
2702+
}
2703+
26982704
bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*, unsigned int> >& setCoinsRet, CAmount& nValueRet) const
26992705
{
27002706
setCoinsRet.clear();
@@ -3309,12 +3315,13 @@ bool CWallet::CreateCoinstakeOuts(const CPivStake& stakeInput, std::vector<CTxOu
33093315
}
33103316

33113317
bool CWallet::CreateCoinStake(
3312-
const CBlockIndex* pindexPrev,
3313-
unsigned int nBits,
3314-
CMutableTransaction& txNew,
3315-
int64_t& nTxNewTime,
3316-
std::vector<CStakeableOutput>* availableCoins,
3317-
bool stopOnNewBlock) const
3318+
const CBlockIndex* pindexPrev,
3319+
unsigned int nBits,
3320+
CMutableTransaction& txNew,
3321+
int64_t& nTxNewTime,
3322+
std::vector<CStakeableOutput>* availableCoins,
3323+
std::vector<CStakeableShieldNote>* availableShieldNotes,
3324+
bool stopOnNewBlock) const
33183325
{
33193326
// shuffle coins
33203327
if (availableCoins && Params().IsRegTestNet()) {
@@ -3336,6 +3343,7 @@ bool CWallet::CreateCoinStake(
33363343
CScript scriptPubKeyKernel;
33373344
bool fKernelFound = false;
33383345
int nAttempts = 0;
3346+
int nShieldAttempts = 0;
33393347
for (auto it = availableCoins->begin(); it != availableCoins->end();) {
33403348
COutPoint outPoint = COutPoint(it->tx->GetHash(), it->i);
33413349
CPivStake stakeInput(it->tx->tx->vout[it->i],
@@ -3409,9 +3417,36 @@ bool CWallet::CreateCoinStake(
34093417
if (nBytes >= DEFAULT_BLOCK_MAX_SIZE / 5)
34103418
return error("%s : exceeded coinstake size limit", __func__);
34113419

3412-
break;
3420+
LogPrint(BCLog::STAKING, "%s: shield attempted staking %d times\n", __func__, nShieldAttempts);
3421+
return fKernelFound;
3422+
}
3423+
LogPrint(BCLog::STAKING, "%s: transparent attempted staking %d times\n", __func__, nAttempts);
3424+
// Resetting tx values
3425+
txNew.vin.clear();
3426+
txNew.vout.clear();
3427+
for (auto it = availableShieldNotes->begin(); it != availableShieldNotes->end();) {
3428+
CShieldStake noteStake = CShieldStake(it->note.note.value(), it->nullifier);
3429+
// New block came in, move on
3430+
if (stopOnNewBlock && GetLastBlockHeightLockWallet() != pindexPrev->nHeight) return false;
3431+
3432+
// Make sure the wallet is unlocked and shutdown hasn't been requested
3433+
if (IsLocked() || ShutdownRequested()) return false;
3434+
3435+
// TODO: check that the note IS NOT spent
3436+
nShieldAttempts++;
3437+
nCredit = 0;
3438+
bool fKernelFound = false;
3439+
fKernelFound = Stake(pindexPrev, &noteStake, nBits, nTxNewTime);
3440+
// update staker status (time, attempts)
3441+
pStakerStatus->SetLastTime(nTxNewTime);
3442+
pStakerStatus->SetLastTries(nAttempts + nShieldAttempts);
3443+
3444+
if (!fKernelFound) {
3445+
it++;
3446+
continue;
3447+
}
34133448
}
3414-
LogPrint(BCLog::STAKING, "%s: attempted staking %d times\n", __func__, nAttempts);
3449+
LogPrint(BCLog::STAKING, "%s: shield attempted staking %d times\n", __func__, nShieldAttempts);
34153450

34163451
return fKernelFound;
34173452
}

0 commit comments

Comments
 (0)