forked from PIVX-Project/PIVX
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblockassembler.h
219 lines (186 loc) · 8.09 KB
/
blockassembler.h
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2021 The Bitcoin Core developers
// Copyright (c) 2021 The PIVX Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.
#ifndef PIVX_BLOCKASSEMBLER_H
#define PIVX_BLOCKASSEMBLER_H
#include "primitives/block.h"
#include "txmempool.h"
#include <stdint.h>
#include <memory>
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/ordered_index.hpp"
class CBlockIndex;
class CChainParams;
class CReserveKey;
class CStakeableOutput;
class CScript;
class CWallet;
namespace Consensus { struct Params; };
struct CBlockTemplate
{
CBlock block;
std::vector<CAmount> vTxFees;
std::vector<int64_t> vTxSigOps;
};
// Container for tracking updates to ancestor feerate as we include (parent)
// transactions in a block
struct CTxMemPoolModifiedEntry {
CTxMemPoolModifiedEntry(CTxMemPool::txiter entry)
{
iter = entry;
nSizeWithAncestors = entry->GetSizeWithAncestors();
nModFeesWithAncestors = entry->GetModFeesWithAncestors();
nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors();
}
CTxMemPool::txiter iter;
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
unsigned int nSigOpCountWithAncestors;
};
/** Comparator for CTxMemPool::txiter objects.
* It simply compares the internal memory address of the CTxMemPoolEntry object
* pointed to. This means it has no meaning, and is only useful for using them
* as key in other indexes.
*/
struct CompareCTxMemPoolIter {
bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const
{
return &(*a) < &(*b);
}
};
struct modifiedentry_iter {
typedef CTxMemPool::txiter result_type;
result_type operator() (const CTxMemPoolModifiedEntry &entry) const
{
return entry.iter;
}
};
// This matches the calculation in CompareTxMemPoolEntryByAncestorFee,
// except operating on CTxMemPoolModifiedEntry.
// TODO: refactor to avoid duplication of this logic.
struct CompareModifiedEntry {
bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) const
{
double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors;
double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors;
if (f1 == f2) {
return CTxMemPool::CompareIteratorByHash()(a.iter, b.iter);
}
return f1 > f2;
}
};
// A comparator that sorts transactions based on number of ancestors.
// This is sufficient to sort an ancestor package in an order that is valid
// to appear in a block.
struct CompareTxIterByAncestorCount {
bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) const
{
if (a->GetCountWithAncestors() != b->GetCountWithAncestors())
return a->GetCountWithAncestors() < b->GetCountWithAncestors();
return CTxMemPool::CompareIteratorByHash()(a, b);
}
};
typedef boost::multi_index_container<
CTxMemPoolModifiedEntry,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
modifiedentry_iter,
CompareCTxMemPoolIter
>,
// sorted by modified ancestor fee rate
boost::multi_index::ordered_non_unique<
// Reuse same tag from CTxMemPool's similar index
boost::multi_index::tag<ancestor_score>,
boost::multi_index::identity<CTxMemPoolModifiedEntry>,
CompareModifiedEntry
>
>
> indexed_modified_transaction_set;
typedef indexed_modified_transaction_set::nth_index<0>::type::iterator modtxiter;
typedef indexed_modified_transaction_set::index<ancestor_score>::type::iterator modtxscoreiter;
struct update_for_parent_inclusion
{
update_for_parent_inclusion(CTxMemPool::txiter it) : iter(it) {}
void operator() (CTxMemPoolModifiedEntry &e)
{
e.nModFeesWithAncestors -= iter->GetFee();
e.nSizeWithAncestors -= iter->GetTxSize();
e.nSigOpCountWithAncestors -= iter->GetSigOpCount();
}
CTxMemPool::txiter iter;
};
/** Generate a new block */
class BlockAssembler
{
private:
// The constructed block template
std::unique_ptr<CBlockTemplate> pblocktemplate;
// A convenience pointer that always refers to the CBlock in pblocktemplate
CBlock* pblock{nullptr};
// Configuration parameters for the block max size
unsigned int nBlockMaxSize{0};
// Information on the current status of the block
uint64_t nBlockSize{0};
uint64_t nBlockTx{0};
unsigned int nBlockSigOps{0};
CAmount nFees{0};
CTxMemPool::setEntries inBlock;
// Chain context for the block
int nHeight{0};
const CChainParams& chainparams;
// Keep track of block space used for shield txes
unsigned int nSizeShielded{0};
// Whether should print priority by default or not
const bool defaultPrintPriority{false};
public:
BlockAssembler(const CChainParams& chainparams, const bool defaultPrintPriority);
/** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn,
CWallet* pwallet = nullptr,
bool fProofOfStake = false,
std::vector<CStakeableOutput>* availableCoins = nullptr,
bool fNoMempoolTx = false,
bool fTestValidity = true,
CBlockIndex* prevBlock = nullptr,
bool stopPoSOnNewBlock = true,
bool fIncludeQfc = true);
private:
// utility functions
/** Clear the block's state and prepare for assembling a new block */
void resetBlock();
/** Add a tx to the block */
void AddToBlock(CTxMemPool::txiter iter);
// Methods for how to add transactions to a block.
/** Add transactions based on feerate including unconfirmed ancestors */
void addPackageTxs();
/** Add the tip updated incremental merkle tree to the header */
void appendSaplingTreeRoot();
// helper functions for addPackageTxs()
/** Remove confirmed (inBlock) entries from given set */
void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
/** Test if a new package would "fit" in the block */
bool TestPackage(uint64_t packageSize, unsigned int packageSigOps);
/** Test if a set of transactions are all final */
bool TestPackageFinality(const CTxMemPool::setEntries& package);
/** Return true if given transaction from mapTx has already been evaluated,
* or if the transaction's cached data in mapTx is incorrect. */
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);
/** Sort the package in an order that is valid to appear in a block */
void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector<CTxMemPool::txiter>& sortedEntries);
/** Add descendants of given transactions to mapModifiedTx with ancestor
* state updated assuming given transactions are inBlock. */
void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
};
/** Modify the nonce/extranonce in a block */
bool SolveBlock(std::shared_ptr<CBlock>& pblock, int nHeight);
void IncrementExtraNonce(std::shared_ptr<CBlock>& pblock, int nHeight, unsigned int& nExtraNonce);
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
int32_t ComputeBlockVersion(const Consensus::Params& consensusParams, int nHeight);
// Visible for testing purposes only
bool CreateCoinbaseTx(CBlock* pblock, const CScript& scriptPubKeyIn, CBlockIndex* pindexPrev);
CMutableTransaction CreateCoinbaseTx(const CScript& scriptPubKeyIn, CBlockIndex* pindexPrev);
// Visible for testing purposes only
uint256 CalculateSaplingTreeRoot(CBlock* pblock, int nHeight, const CChainParams& chainparams);
#endif // PIVX_BLOCKASSEMBLER_H