Skip to content

Commit f449aec

Browse files
Merge pull request #523 from aguycalled/coldstaking-pool-fee
Coldstaking pool fee
2 parents 06109e8 + 6c83d95 commit f449aec

File tree

13 files changed

+178
-31
lines changed

13 files changed

+178
-31
lines changed

qa/pull-tester/rpc-tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
'getstakinginfo.py',
177177
'coldstaking_staking.py',
178178
'coldstaking_spending.py',
179+
'coldstaking_fee.py',
179180
'staticr-staking-amount.py',
180181
'hardfork-451.py',
181182
'hardfork-452.py',

qa/rpc-tests/coldstaking_fee.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2019 The Navcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
from test_framework.test_framework import NavCoinTestFramework
7+
from test_framework.util import *
8+
9+
class ColdStakingFeeTest(NavCoinTestFramework):
10+
def __init__(self):
11+
super().__init__()
12+
self.setup_clean_chain = True
13+
self.num_nodes = 3
14+
15+
def setup_network(self, split=False):
16+
self.nodes = []
17+
self.nodes.append(start_node(0, self.options.tmpdir, ["-addressindex","-pooladdress=n1hcSEk4ReyLwbStTKodGCq4kEwhJVxXwC","-poolfee=50"]))
18+
self.nodes.append(start_node(1, self.options.tmpdir, ["-addressindex","-pooladdress=n1hcSEk4ReyLwbStTKodGCq4kEwhJVxXwC","-poolfee=100"]))
19+
self.nodes.append(start_node(2, self.options.tmpdir, ["-addressindex","-pooladdress=n1hcSEk4ReyLwbStTKodGCq4kEwhJVxXwC","-poolfee=101"]))
20+
21+
def run_test(self):
22+
slow_gen(self.nodes[0], 300)
23+
assert (get_bip9_status(self.nodes[0], "coldstaking")["status"] == "active")
24+
slow_gen(self.nodes[1], 300)
25+
assert (get_bip9_status(self.nodes[1], "coldstaking")["status"] == "active")
26+
slow_gen(self.nodes[2], 300)
27+
assert (get_bip9_status(self.nodes[2], "coldstaking")["status"] == "active")
28+
29+
csaddress1 = self.nodes[0].getcoldstakingaddress(self.nodes[0].getnewaddress(),"n1wgKgwFPZYcQrm8qBtPrBvz2piqCwc1ry")
30+
csaddress2 = self.nodes[1].getcoldstakingaddress(self.nodes[1].getnewaddress(),"n1wgKgwFPZYcQrm8qBtPrBvz2piqCwc1ry")
31+
csaddress3 = self.nodes[2].getcoldstakingaddress(self.nodes[2].getnewaddress(),"n1wgKgwFPZYcQrm8qBtPrBvz2piqCwc1ry")
32+
33+
self.nodes[0].sendtoaddress(csaddress1, self.nodes[0].getbalance(), "", "", "", True)
34+
self.nodes[1].sendtoaddress(csaddress2, self.nodes[1].getbalance(), "", "", "", True)
35+
self.nodes[2].sendtoaddress(csaddress3, self.nodes[2].getbalance(), "", "", "", True)
36+
37+
self.nodes[0].generatetoaddress(100, "n1wgKgwFPZYcQrm8qBtPrBvz2piqCwc1ry")
38+
self.nodes[1].generatetoaddress(100, "n1wgKgwFPZYcQrm8qBtPrBvz2piqCwc1ry")
39+
self.nodes[2].generatetoaddress(100, "n1wgKgwFPZYcQrm8qBtPrBvz2piqCwc1ry")
40+
41+
tx=self.nodes[0].sendtoaddress(csaddress1, self.nodes[0].getbalance(), "", "", "", True)
42+
fees0=self.nodes[0].gettransaction(tx)["fee"]*100000000/2
43+
tx2=self.nodes[1].sendtoaddress(csaddress2, self.nodes[1].getbalance(), "", "", "", True)
44+
fees1=self.nodes[1].gettransaction(tx2)["fee"]*100000000
45+
self.nodes[2].sendtoaddress(csaddress3, self.nodes[2].getbalance(), "", "", "", True)
46+
47+
while self.nodes[0].getblockcount() < 401:
48+
time.sleep(1)
49+
50+
node0balance = self.nodes[0].getaddressbalance('n1hcSEk4ReyLwbStTKodGCq4kEwhJVxXwC')["balance"]
51+
52+
while self.nodes[1].getblockcount() < 401:
53+
time.sleep(1)
54+
55+
node1balance = self.nodes[1].getaddressbalance('n1hcSEk4ReyLwbStTKodGCq4kEwhJVxXwC')["balance"]
56+
57+
assert(node0balance > 0)
58+
assert(node1balance > 0)
59+
assert_equal((node0balance+fees0) % 100000000, 0)
60+
assert_equal((node1balance+fees1) % 200000000, 0)
61+
62+
assert("Coinstake tried to move cold staking coins to a non authorised script" in open(self.options.tmpdir + '/node2/devnet/debug.log').read())
63+
64+
if __name__ == '__main__':
65+
ColdStakingFeeTest().main()

src/chainparams.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ class CMainParams : public CChainParams {
193193
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nStartTime = 1543622400; // Dec 1st, 2018
194194
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nTimeout = 1575158400; // Dec 1st, 2019
195195

196+
// Deployment of Cold Staking Pool Fee
197+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].bit = 18;
198+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nStartTime = 1559390400; // Jun 1st, 2018
199+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nTimeout = 1622548800; // Jun 1st, 2021
200+
201+
196202
/**
197203
* The message start string is designed to be unlikely to occur in normal data.
198204
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
@@ -375,6 +381,11 @@ class CTestNetParams : public CChainParams {
375381
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nStartTime = 1543622400; // Dec 1st, 2018
376382
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nTimeout = 1622548800; // Jun 1st, 2021
377383

384+
// Deployment of Cold Staking Pool Fee
385+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].bit = 18;
386+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nStartTime = 1559390400; // Jun 1st, 2018
387+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nTimeout = 1622548800; // Jun 1st, 2021
388+
378389
/**
379390
* The message start string is designed to be unlikely to occur in normal data.
380391
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
@@ -550,6 +561,11 @@ class CDevNetParams : public CChainParams {
550561
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nStartTime = 1543622400; // Dec 1st, 2018
551562
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nTimeout = 1651363200; // May 1st, 2022
552563

564+
// Deployment of Cold Staking Pool Fee
565+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].bit = 18;
566+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nStartTime = 1559390400; // Jun 1st, 2018
567+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nTimeout = 1622548800; // Jun 1st, 2021
568+
553569
/**
554570
* The message start string is designed to be unlikely to occur in normal data.
555571
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
@@ -735,6 +751,11 @@ class CRegTestParams : public CChainParams {
735751
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nStartTime = 1543622400; // Dec 1st, 2018
736752
consensus.vDeployments[Consensus::DEPLOYMENT_QUORUM_CFUND].nTimeout = 1575158400; // Dec 1st, 2019
737753

754+
// Deployment of Cold Staking Pool Fee
755+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].bit = 18;
756+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nStartTime = 1559390400; // Jun 1st, 2018
757+
consensus.vDeployments[Consensus::DEPLOYMENT_POOL_FEE].nTimeout = 1622548800; // Jun 1st, 2021
758+
738759
/**
739760
* The message start string is designed to be unlikely to occur in normal data.
740761
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce

src/consensus/params.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum DeploymentPos
2929
DEPLOYMENT_NTPSYNC,
3030
DEPLOYMENT_STATIC_REWARD,
3131
DEPLOYMENT_QUORUM_CFUND,
32+
DEPLOYMENT_POOL_FEE,
3233
MAX_VERSION_BITS_DEPLOYMENTS
3334
};
3435

src/main.cpp

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,7 +2915,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
29152915
if (pindex->IsProofOfStake())
29162916
setStakeSeen.insert(make_pair(pindex->prevoutStake, pindex->nStakeTime));
29172917

2918-
29192918
// Check proof of stake
29202919
if (block.nBits != GetNextTargetRequired(pindex->pprev, block.IsProofOfStake())){
29212920
return state.DoS(1,error("ContextualCheckBlock() : incorrect %s at height %d (%d)", !block.IsProofOfStake() ? "proof-of-work" : "proof-of-stake",pindex->pprev->nHeight, block.nBits), REJECT_INVALID, "bad-diffbits");
@@ -2928,25 +2927,25 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
29282927
{
29292928
arith_uint256 targetProofOfStake;
29302929
// Signature will be checked in CheckInputs(), we can avoid it here (fCheckSignature = false)
2931-
if (!CheckProofOfStake(pindex->pprev, block.vtx[1], block.nBits, hashProof, targetProofOfStake, NULL, false))
2930+
if (!CheckProofOfStake(pindex->pprev, block.vtx[1], block.nBits, hashProof, targetProofOfStake, NULL, view, false))
29322931
{
2933-
return error("ConnectBlock() : check proof-of-stake signature failed for block %s", block.GetHash().GetHex());
2932+
return error("ContextualCheckBlock() : check proof-of-stake signature failed for block %s", block.GetHash().GetHex());
29342933
}
29352934
}
29362935

29372936
if (block.IsProofOfWork())
29382937
hashProof = UintToArith256(block.GetPoWHash());
29392938

29402939
if (!pindex->SetStakeEntropyBit(block.GetStakeEntropyBit()))
2941-
return state.DoS(1,error("ConnectBlock() : SetStakeEntropyBit() failed"), REJECT_INVALID, "bad-entropy-bit");
2940+
return state.DoS(1,error("ContextualCheckBlock() : SetStakeEntropyBit() failed"), REJECT_INVALID, "bad-entropy-bit");
29422941

29432942
// Record proof hash value
29442943
pindex->hashProof = hashProof;
29452944

29462945
uint64_t nStakeModifier = 0;
29472946
bool fGeneratedStakeModifier = false;
29482947
if (!ComputeNextStakeModifier(pindex->pprev, nStakeModifier, fGeneratedStakeModifier))
2949-
return state.DoS(1, error("ConnectBlock() : ComputeNextStakeModifier() failed"), REJECT_INVALID, "bad-stake-modifier");
2948+
return state.DoS(1, error("ContextualCheckBlock() : ComputeNextStakeModifier() failed"), REJECT_INVALID, "bad-stake-modifier");
29502949

29512950
pindex->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
29522951

@@ -4620,6 +4619,12 @@ bool IsColdStakingEnabled(const CBlockIndex* pindexPrev, const Consensus::Params
46204619
return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_COLDSTAKING, versionbitscache) == THRESHOLD_ACTIVE);
46214620
}
46224621

4622+
bool IsColdStakingPoolFeeEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
4623+
{
4624+
LOCK(cs_main);
4625+
return (VersionBitsState(pindexPrev, params, Consensus::DEPLOYMENT_POOL_FEE, versionbitscache) == THRESHOLD_ACTIVE);
4626+
}
4627+
46234628
bool IsStaticRewardLocked(const CBlockIndex* pindexPrev, const Consensus::Params& params)
46244629
{
46254630
LOCK(cs_main);
@@ -8604,24 +8609,54 @@ bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, CBlockInd
86048609
}
86058610

86068611
//Check kernel hash target and coinstake signature
8607-
bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, arith_uint256& hashProofOfStake, arith_uint256& targetProofOfStake, std::vector<CScriptCheck> *pvChecks, bool fCHeckSignature)
8612+
bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, arith_uint256& hashProofOfStake, arith_uint256& targetProofOfStake, std::vector<CScriptCheck> *pvChecks, CCoinsViewCache& view, bool fCHeckSignature)
86088613
{
86098614
if (!tx.IsCoinStake())
8610-
return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString());
8615+
return error("%s: called on non-coinstake %s", __func__, tx.GetHash().ToString());
86118616

86128617
// Kernel (input 0) must match the stake hash target per coin age (nBits)
86138618
const CTxIn& txin = tx.vin[0];
86148619

86158620
CTransaction txPrev;
86168621
uint256 hashBlock = uint256();
86178622
if (!GetTransaction(txin.prevout.hash, txPrev, Params().GetConsensus(), hashBlock, true))
8618-
return error("CheckProofOfStake() : INFO: read txPrev failed %s",txin.prevout.hash.GetHex()); // previous transaction not in main chain, may occur during initial download
8623+
return error("%s: INFO: read txPrev failed %s",__func__, txin.prevout.hash.GetHex()); // previous transaction not in main chain, may occur during initial download
8624+
8625+
bool fColdStaking = txPrev.vout[txin.prevout.n].scriptPubKey.IsColdStaking();
8626+
bool fPoolEnabled = IsColdStakingPoolFeeEnabled(pindexPrev, Params().GetConsensus());
8627+
CScript kernelScript = txPrev.vout[txin.prevout.n].scriptPubKey;
8628+
8629+
if (fPoolEnabled && tx.vin.size() > 1)
8630+
{
8631+
for (unsigned int i = 1; i < tx.vin.size(); i++)
8632+
{
8633+
CTransaction txPrev_;
8634+
uint256 hashBlock_ = uint256();
8635+
if (!GetTransaction(tx.vin[i].prevout.hash, txPrev_, Params().GetConsensus(), hashBlock_, true))
8636+
return error("%s: INFO: read txPrev failed %s",__func__, tx.vin[i].prevout.hash.GetHex()); // previous transaction not in main chain, may occur during initial download
86198637

8620-
if (txPrev.vout[txin.prevout.n].scriptPubKey.IsColdStaking())
8621-
for(unsigned int i = 1; i < tx.vout.size() - 1; i++) // First output is empty, last is CFund contribution
8622-
if(tx.vout[i].scriptPubKey != txPrev.vout[txin.prevout.n].scriptPubKey)
8623-
return error(strprintf("CheckProofOfStake(): Coinstake output %d tried to move cold staking coins to a non authorised script. (%s vs. %s)",
8624-
i, ScriptToAsmStr(txPrev.vout[txin.prevout.n].scriptPubKey), ScriptToAsmStr(tx.vout[i].scriptPubKey)));
8638+
fColdStaking |= txPrev_.vout[tx.vin[i].prevout.n].scriptPubKey.IsColdStaking();
8639+
if (fColdStaking && txPrev_.vout[tx.vin[i].prevout.n].scriptPubKey != kernelScript)
8640+
return error("%s: Coinstake spends inputs from more than one different kernel", __func__);
8641+
}
8642+
}
8643+
8644+
if (fColdStaking)
8645+
{
8646+
CAmount valueIn = view.GetValueIn(tx);
8647+
CAmount valueOut = 0;
8648+
8649+
for(unsigned int i = 1; i < tx.vout.size() - (fPoolEnabled?0:1); i++) // First output is empty, last is CFund contribution
8650+
if(fPoolEnabled && tx.vout[i].scriptPubKey == txPrev.vout[txin.prevout.n].scriptPubKey)
8651+
valueOut += tx.vout[i].nValue;
8652+
else if(!fPoolEnabled && tx.vout[i].scriptPubKey != txPrev.vout[txin.prevout.n].scriptPubKey)
8653+
return error(strprintf("%s: Coinstake output %d tried to move cold staking coins to a non authorised script. (%s vs. %s)",
8654+
__func__, i, ScriptToAsmStr(txPrev.vout[txin.prevout.n].scriptPubKey), ScriptToAsmStr(tx.vout[i].scriptPubKey)));
8655+
8656+
if (fPoolEnabled && valueIn > valueOut)
8657+
return error("%s: Coinstake tried to move cold staking coins to a non authorised script.",__func__);
8658+
8659+
}
86258660

86268661
if (pvChecks)
86278662
pvChecks->reserve(tx.vin.size());
@@ -8641,19 +8676,19 @@ bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned
86418676
pvChecks->push_back(CScriptCheck());
86428677
check.swap(pvChecks->back());
86438678
} else if (!check())
8644-
return error("CheckProofOfStake() : script-verify-failed %s",ScriptErrorString(check.GetScriptError()));
8679+
return error("%s: script-verify-failed %s",__func__, ScriptErrorString(check.GetScriptError()));
86458680
}
86468681

86478682
if (mapBlockIndex.count(hashBlock) == 0)
8648-
return fDebug? error("CheckProofOfStake() : read block failed") : false; // unable to read block of previous transaction
8683+
return fDebug? error("%s: read block failed",__func__) : false; // unable to read block of previous transaction
86498684

86508685
CBlockIndex* pblockindex = mapBlockIndex[hashBlock];
86518686

86528687
if (txin.prevout.hash != txPrev.GetHash())
8653-
return error("CheckProofOfStake(): Coinstake input does not match previous output %s",txin.prevout.hash.GetHex());
8688+
return error("%s: Coinstake input does not match previous output %s",__func__, txin.prevout.hash.GetHex());
86548689

86558690
if (!CheckStakeKernelHash(pindexPrev, nBits, *pblockindex, txPrev, txin.prevout, tx.nTime, hashProofOfStake, targetProofOfStake, fDebug))
8656-
return error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString(), hashProofOfStake.ToString()); // may occur during initial download or if behind on block chain sync
8691+
return error("%s: INFO: check kernel failed on coinstake %s, hashProof=%s",__func__, tx.GetHash().ToString(), hashProofOfStake.ToString()); // may occur during initial download or if behind on block chain sync
86578692

86588693
return true;
86598694
}

src/main.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ bool IsReducedCFundQuorumEnabled(const CBlockIndex* pindexPrev, const Consensus:
529529

530530
/** Check whether ColdStaking has been activated. */
531531
bool IsColdStakingEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
532+
bool IsColdStakingPoolFeeEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
532533

533534
/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
534535
bool RewindBlockIndex(const CChainParams& params);
@@ -616,7 +617,7 @@ bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, CBlockInd
616617

617618
// Check kernel hash target and coinstake signature
618619
// Sets hashProofOfStake on success return
619-
bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, arith_uint256& hashProofOfStake, arith_uint256& targetProofOfStake, std::vector<CScriptCheck> *pvChecks, bool fCHeckSignature = false);
620+
bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, arith_uint256& hashProofOfStake, arith_uint256& targetProofOfStake, std::vector<CScriptCheck> *pvChecks, CCoinsViewCache& view, bool fCHeckSignature = false);
620621

621622
// Check whether the coinstake timestamp meets protocol
622623
bool CheckCoinStakeTimestamp(int nHeight, int64_t nTimeBlock, int64_t nTimeTx);

src/miner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ bool CheckStake(CBlock* pblock, CWallet& wallet, const CChainParams& chainparams
979979
return error("CheckStake(): could not find previous block");
980980

981981
// verify hash target and signature of coinstake tx
982-
if (!CheckProofOfStake(mapBlockIndex[pblock->hashPrevBlock], pblock->vtx[1], pblock->nBits, proofHash, hashTarget, NULL))
982+
if (!CheckProofOfStake(mapBlockIndex[pblock->hashPrevBlock], pblock->vtx[1], pblock->nBits, proofHash, hashTarget, NULL, *pcoinsTip, false))
983983
return error("CheckStake() : proof-of-stake checking failed");
984984

985985
//// debug print

src/qt/transactionrecord.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
3636
{
3737
QList<TransactionRecord> parts;
3838
int64_t nTime = wtx.GetTxTime();
39-
isminefilter dCFilter = (wtx.IsCoinStake() && wtx.vout[1].scriptPubKey.IsColdStaking()) ? wallet->IsMine(wtx.vout[1]) : ISMINE_ALL;
40-
CAmount nCredit = wtx.GetCredit(dCFilter);
39+
isminefilter dCFilter = wtx.IsCoinStake() ? wallet->IsMine(wtx.vout[1]) : ISMINE_ALL;
40+
CAmount nCredit = wtx.GetCredit(dCFilter, false);
4141
CAmount nDebit = wtx.GetDebit(dCFilter);
4242
CAmount nCFundCredit = wtx.GetDebit(ISMINE_ALL);
4343
CAmount nNet = nCredit - nDebit;
@@ -58,8 +58,17 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
5858
unsigned int i = 0;
5959
unsigned int rewardIdx = 0;
6060
if (wtx.IsCoinStake())
61-
// If coinstake has no cfund contribution, get details of last vout or else use second to last
62-
rewardIdx = wtx.vout.size() - (wtx.GetValueOutCFund() == 0 ? 1 : 2);
61+
{
62+
for (unsigned int j = wtx.vout.size(); j--;)
63+
{
64+
if (wallet->IsMine(wtx.vout[j]))
65+
{
66+
rewardIdx = j;
67+
break;
68+
}
69+
70+
}
71+
}
6372

6473
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
6574
{
@@ -101,7 +110,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
101110
}
102111

103112
sub.type = TransactionRecord::Staked;
104-
sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit - wtx.GetValueOutCFund();
113+
sub.credit = nNet;
105114
}
106115
if(wtx.fAnon)
107116
{

0 commit comments

Comments
 (0)