mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-13 12:33:42 +02:00
Add dynafed helper functions
This commit is contained in:
parent
4aa5f991f4
commit
f17d7de526
5 changed files with 127 additions and 0 deletions
|
|
@ -134,6 +134,7 @@ BITCOIN_CORE_H = \
|
|||
core_io.h \
|
||||
core_memusage.h \
|
||||
cuckoocache.h \
|
||||
dynafed.h \
|
||||
fs.h \
|
||||
httprpc.h \
|
||||
httpserver.h \
|
||||
|
|
@ -401,10 +402,13 @@ libbitcoin_consensus_a_SOURCES = \
|
|||
arith_uint256.cpp \
|
||||
arith_uint256.h \
|
||||
asset.cpp \
|
||||
chain.h \
|
||||
chain.cpp \
|
||||
consensus/merkle.cpp \
|
||||
consensus/merkle.h \
|
||||
consensus/params.h \
|
||||
consensus/validation.h \
|
||||
dynafed.cpp \
|
||||
hash.cpp \
|
||||
hash.h \
|
||||
prevector.h \
|
||||
|
|
@ -433,6 +437,8 @@ libbitcoin_consensus_a_SOURCES = \
|
|||
script/script.h \
|
||||
script/script_error.cpp \
|
||||
script/script_error.h \
|
||||
script/standard.h \
|
||||
script/standard.cpp \
|
||||
serialize.h \
|
||||
span.h \
|
||||
tinyformat.h \
|
||||
|
|
|
|||
|
|
@ -482,6 +482,9 @@ class CCustomParams : public CRegTestParams {
|
|||
|
||||
consensus.nMinimumChainWork = uint256S(args.GetArg("-con_nminimumchainwork", "0x0"));
|
||||
consensus.defaultAssumeValid = uint256S(args.GetArg("-con_defaultassumevalid", "0x00"));
|
||||
// TODO: pass in serialized vector of byte vectors, parse into extension space
|
||||
// Junk keys for testing
|
||||
consensus.first_extension_space = {ParseHex("02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f")};
|
||||
|
||||
nPruneAfterHeight = (uint64_t)args.GetArg("-npruneafterheight", nPruneAfterHeight);
|
||||
fDefaultConsistencyChecks = args.GetBoolArg("-fdefaultconsistencychecks", fDefaultConsistencyChecks);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ struct Params {
|
|||
CScript signblockscript;
|
||||
uint32_t max_block_signature_size;
|
||||
// g_signed_blocks - Whether blocks are signed or not, get around circular dep
|
||||
// Used to seed the extension space for first dynamic blocks
|
||||
std::vector<std::vector<unsigned char>> first_extension_space;
|
||||
};
|
||||
} // namespace Consensus
|
||||
|
||||
|
|
|
|||
97
src/dynafed.cpp
Normal file
97
src/dynafed.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
#include <dynafed.h>
|
||||
#include <script/standard.h>
|
||||
|
||||
bool NextBlockIsParameterTransition(const CBlockIndex* pindexPrev, const Consensus::Params& consensus, ConsensusParamEntry& winning_entry)
|
||||
{
|
||||
uint32_t next_height = pindexPrev->nHeight + 1;
|
||||
assert(consensus.dynamic_epoch_length != 0);
|
||||
if (next_height % consensus.dynamic_epoch_length != 0) {
|
||||
winning_entry.SetNull();
|
||||
return false;
|
||||
}
|
||||
std::map<uint256, uint32_t> vote_tally;
|
||||
assert(next_height >= consensus.dynamic_epoch_length);
|
||||
for (int32_t height = next_height - 1; height >= (int32_t)(next_height - consensus.dynamic_epoch_length); --height) {
|
||||
const CBlockIndex* p_epoch_walk = pindexPrev->GetAncestor(height);
|
||||
assert(p_epoch_walk);
|
||||
const ConsensusParamEntry& proposal = p_epoch_walk->d_params.m_proposed;
|
||||
const uint256 proposal_root = proposal.CalculateRoot();
|
||||
vote_tally[proposal_root]++;
|
||||
// Short-circuit once 4/5 threshhold is reached
|
||||
if (vote_tally[proposal_root] >=
|
||||
(consensus.dynamic_epoch_length*4)/5) {
|
||||
winning_entry = proposal;
|
||||
return true;
|
||||
}
|
||||
// Also stop early if "no-vote" crosses 1/4
|
||||
if (proposal_root.IsNull() &&
|
||||
vote_tally[proposal_root] > consensus.dynamic_epoch_length/5) {
|
||||
winning_entry.SetNull();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
winning_entry.SetNull();
|
||||
return false;
|
||||
}
|
||||
|
||||
ConsensusParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus)
|
||||
{
|
||||
assert(pindexPrev);
|
||||
|
||||
uint32_t next_height = pindexPrev->nHeight+1;
|
||||
const uint32_t epoch_length = consensus.dynamic_epoch_length;
|
||||
uint32_t epoch_age = next_height % epoch_length;
|
||||
|
||||
ConsensusParamEntry winning_proposal;
|
||||
// Early return when there is a winning proposal
|
||||
if (NextBlockIsParameterTransition(pindexPrev, consensus, winning_proposal)) {
|
||||
assert(epoch_age == 0);
|
||||
return winning_proposal;
|
||||
}
|
||||
|
||||
// Since no transition took place, find most recent epoch start
|
||||
|
||||
// If next block is start of new epoch, walk backwards one epoch
|
||||
uint32_t epoch_start_height = next_height - epoch_age;
|
||||
if (epoch_age == 0) {
|
||||
epoch_start_height -= epoch_length;
|
||||
}
|
||||
|
||||
// We need to put in place the previous epoch's current which
|
||||
// may be pre-dynafed params
|
||||
const CBlockIndex* p_epoch_start = pindexPrev->GetAncestor(epoch_start_height);
|
||||
assert(p_epoch_start);
|
||||
if (p_epoch_start->d_params.IsNull()) {
|
||||
// We need to construct the "full" current parameters of pre-dynafed
|
||||
// consensus
|
||||
|
||||
// Convert signblockscript to P2WSH
|
||||
CScript p2wsh_signblock_script = GetScriptForDestination(WitnessV0ScriptHash(p_epoch_start->proof.challenge));
|
||||
winning_proposal = ConsensusParamEntry(p2wsh_signblock_script, consensus.max_block_signature_size+consensus.signblockscript.size(), consensus.fedpegScript, consensus.first_extension_space);
|
||||
} else {
|
||||
winning_proposal = p_epoch_start->d_params.m_current;
|
||||
}
|
||||
return winning_proposal;
|
||||
}
|
||||
|
||||
// TODO cache this in CBlockIndex itself?
|
||||
ConsensusParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus)
|
||||
{
|
||||
assert(pindexPrev);
|
||||
|
||||
ConsensusParamEntry entry = ComputeNextBlockFullCurrentParameters(pindexPrev, consensus);
|
||||
|
||||
uint32_t next_height = pindexPrev->nHeight+1;
|
||||
const uint32_t epoch_length = consensus.dynamic_epoch_length;
|
||||
uint32_t epoch_age = next_height % epoch_length;
|
||||
|
||||
// Return appropriate format based on epoch age
|
||||
if (epoch_age > 0) {
|
||||
// TODO implement "prune" function to remove fields in place and change serialize type
|
||||
return ConsensusParamEntry(entry.m_signblockscript, entry.m_sbs_wit_limit);
|
||||
} else {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
19
src/dynafed.h
Normal file
19
src/dynafed.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#ifndef BITCOIN_DYNAFED_H
|
||||
#define BITCOIN_DYNAFED_H
|
||||
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <primitives/block.h>
|
||||
|
||||
|
||||
bool NextBlockIsParameterTransition(const CBlockIndex* pindexPrev, const Consensus::Params& consensus, ConsensusParamEntry& winning_entry);
|
||||
|
||||
/* Compute the next block's enforced parameters */
|
||||
ConsensusParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus);
|
||||
/* Compute the next block's expected published parameters. Blocks at "epoch_age" of non-0 only
|
||||
* publish signblockscript-related fields */
|
||||
ConsensusParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus);
|
||||
|
||||
|
||||
#endif // BITCOIN_DYNAFED_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue