Fix funding stream end-height-exclusion bugs

This commit is contained in:
Kris Nuttycombe 2020-07-06 10:31:07 -06:00
parent fccf37844b
commit 8b363e9a70
5 changed files with 44 additions and 19 deletions

View File

@ -59,8 +59,8 @@ int GetMaxFundingStreamHeight(const Consensus::Params& params) {
int result = 0;
for (int idx = Consensus::FIRST_FUNDING_STREAM; idx < Consensus::MAX_FUNDING_STREAMS; idx++) {
auto fs = params.vFundingStreams[idx];
if (fs && result < fs.get().GetEndHeight()) {
result = fs.get().GetEndHeight();
if (fs && result < fs.get().GetEndHeight() - 1) {
result = fs.get().GetEndHeight() - 1;
}
}

View File

@ -100,9 +100,9 @@ namespace Consensus {
boost::variant<FundingStream, FundingStreamError> FundingStream::ValidateFundingStream(
const Consensus::Params& params,
int startHeight,
int endHeight,
std::vector<FundingStreamAddress> addresses
const int startHeight,
const int endHeight,
const std::vector<FundingStreamAddress>& addresses
) {
if (!params.NetworkUpgradeActive(startHeight, Consensus::UPGRADE_CANOPY)) {
return FundingStreamError::CANOPY_NOT_ACTIVE;
@ -112,7 +112,7 @@ namespace Consensus {
return FundingStreamError::ILLEGAL_RANGE;
}
if (params.FundingPeriodIndex(startHeight, endHeight) >= addresses.size()) {
if (params.FundingPeriodIndex(startHeight, endHeight - 1) >= addresses.size()) {
return FundingStreamError::INSUFFICIENT_ADDRESSES;
}
@ -141,8 +141,8 @@ namespace Consensus {
FundingStream FundingStream::ParseFundingStream(
const Consensus::Params& params,
int startHeight,
int endHeight,
const int startHeight,
const int endHeight,
const std::vector<std::string> strAddresses)
{
// Parse the address strings into concrete types.

View File

@ -116,15 +116,15 @@ public:
static boost::variant<FundingStream, FundingStreamError> ValidateFundingStream(
const Consensus::Params& params,
int startHeight,
int endHeight,
std::vector<FundingStreamAddress> addresses
const int startHeight,
const int endHeight,
const std::vector<FundingStreamAddress>& addresses
);
static FundingStream ParseFundingStream(
const Consensus::Params& params,
int startHeight,
int endHeight,
const int startHeight,
const int endHeight,
const std::vector<std::string> strAddresses);
int GetStartHeight() const { return startHeight; };

View File

@ -234,7 +234,7 @@ TEST(FundingStreamsRewardTest, Zip207Distribution) {
Consensus::FundingStream::ParseFundingStream(
consensus,
minHeight,
minHeight + 100,
minHeight + 12,
{
"t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi",
EncodePaymentAddress(sk.default_address())
@ -256,3 +256,23 @@ TEST(FundingStreamsRewardTest, Zip207Distribution) {
EXPECT_EQ(totalFunding, blockSubsidy / 5);
}
}
TEST(FundingStreamsRewardTest, ParseFundingStream) {
auto consensus = RegtestActivateCanopy(false, 200);
int minHeight = GetLastFoundersRewardHeight(consensus) + 1;
auto sk = libzcash::SaplingSpendingKey(uint256());
ASSERT_THROW(
Consensus::FundingStream::ParseFundingStream(
consensus,
minHeight,
minHeight + 13,
{
"t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi",
EncodePaymentAddress(sk.default_address())
}
),
std::runtime_error
);
}

View File

@ -906,11 +906,16 @@ bool ContextualCheckTransaction(
// From Canopy onward, coinbase transaction must include outputs corresponding to the
// ZIP 207 consensus funding streams active at the current block height. To avoid
// double-decrypting, we detect any shielded funding streams during the Heartwood
// consensus check. If Canopy is not yet active, requiredStream will be empty.
auto fundingStreamElements = Consensus::GetActiveFundingStreamElements(
nHeight,
GetBlockSubsidy(nHeight, chainparams.GetConsensus()),
chainparams.GetConsensus());
// consensus check. If Canopy is not yet active, requiredStreams will be empty.
std::set<Consensus::FundingStreamElement> fundingStreamElements;
if (canopyActive) {
fundingStreamElements = Consensus::GetActiveFundingStreamElements(
nHeight,
// GetBlockSubsidy must be guarded because it will throw
// if called at slow-start period heights.
GetBlockSubsidy(nHeight, chainparams.GetConsensus()),
chainparams.GetConsensus());
}
// Rules that apply to Heartwood or later:
if (heartwoodActive) {