Skip to content

Commit c37a8fe

Browse files
committed
Add dynafed helper functions
1 parent fa1f497 commit c37a8fe

File tree

5 files changed

+127
-0
lines changed

5 files changed

+127
-0
lines changed

src/Makefile.am

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ BITCOIN_CORE_H = \
134134
core_io.h \
135135
core_memusage.h \
136136
cuckoocache.h \
137+
dynafed.h \
137138
fs.h \
138139
httprpc.h \
139140
httpserver.h \
@@ -401,10 +402,13 @@ libbitcoin_consensus_a_SOURCES = \
401402
arith_uint256.cpp \
402403
arith_uint256.h \
403404
asset.cpp \
405+
chain.h \
406+
chain.cpp \
404407
consensus/merkle.cpp \
405408
consensus/merkle.h \
406409
consensus/params.h \
407410
consensus/validation.h \
411+
dynafed.cpp \
408412
hash.cpp \
409413
hash.h \
410414
prevector.h \
@@ -433,6 +437,8 @@ libbitcoin_consensus_a_SOURCES = \
433437
script/script.h \
434438
script/script_error.cpp \
435439
script/script_error.h \
440+
script/standard.h \
441+
script/standard.cpp \
436442
serialize.h \
437443
span.h \
438444
tinyformat.h \

src/chainparams.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ class CCustomParams : public CRegTestParams {
482482

483483
consensus.nMinimumChainWork = uint256S(args.GetArg("-con_nminimumchainwork", "0x0"));
484484
consensus.defaultAssumeValid = uint256S(args.GetArg("-con_defaultassumevalid", "0x00"));
485+
// TODO: pass in serialized vector of byte vectors, parse into extension space
486+
// Junk keys for testing
487+
consensus.first_extension_space = {ParseHex("02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f")};
485488

486489
nPruneAfterHeight = (uint64_t)args.GetArg("-npruneafterheight", nPruneAfterHeight);
487490
fDefaultConsistencyChecks = args.GetBoolArg("-fdefaultconsistencychecks", fDefaultConsistencyChecks);

src/consensus/params.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ struct Params {
9999
CScript signblockscript;
100100
uint32_t max_block_signature_size;
101101
// g_signed_blocks - Whether blocks are signed or not, get around circular dep
102+
// Used to seed the extension space for first dynamic blocks
103+
std::vector<std::vector<unsigned char>> first_extension_space;
102104
};
103105
} // namespace Consensus
104106

src/dynafed.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
#include <dynafed.h>
3+
#include <script/standard.h>
4+
5+
bool NextBlockIsParameterTransition(const CBlockIndex* pindexPrev, const Consensus::Params& consensus, ConsensusParamEntry& winning_entry)
6+
{
7+
uint32_t next_height = pindexPrev->nHeight + 1;
8+
assert(consensus.dynamic_epoch_length != 0);
9+
if (next_height % consensus.dynamic_epoch_length != 0) {
10+
winning_entry.SetNull();
11+
return false;
12+
}
13+
std::map<uint256, uint32_t> vote_tally;
14+
assert(next_height >= consensus.dynamic_epoch_length);
15+
for (int32_t height = next_height - 1; height >= (int32_t)(next_height - consensus.dynamic_epoch_length); --height) {
16+
const CBlockIndex* p_epoch_walk = pindexPrev->GetAncestor(height);
17+
assert(p_epoch_walk);
18+
const ConsensusParamEntry& proposal = p_epoch_walk->d_params.m_proposed;
19+
const uint256 proposal_root = proposal.CalculateRoot();
20+
vote_tally[proposal_root]++;
21+
// Short-circuit once 4/5 threshhold is reached
22+
if (vote_tally[proposal_root] >=
23+
(consensus.dynamic_epoch_length*4)/5) {
24+
winning_entry = proposal;
25+
return true;
26+
}
27+
// Also stop early if "no-vote" crosses 1/4
28+
if (proposal_root.IsNull() &&
29+
vote_tally[proposal_root] > consensus.dynamic_epoch_length/5) {
30+
winning_entry.SetNull();
31+
return false;
32+
}
33+
}
34+
winning_entry.SetNull();
35+
return false;
36+
}
37+
38+
ConsensusParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus)
39+
{
40+
assert(pindexPrev);
41+
42+
uint32_t next_height = pindexPrev->nHeight+1;
43+
const uint32_t epoch_length = consensus.dynamic_epoch_length;
44+
uint32_t epoch_age = next_height % epoch_length;
45+
46+
ConsensusParamEntry winning_proposal;
47+
// Early return when there is a winning proposal
48+
if (NextBlockIsParameterTransition(pindexPrev, consensus, winning_proposal)) {
49+
assert(epoch_age == 0);
50+
return winning_proposal;
51+
}
52+
53+
// Since no transition took place, find most recent epoch start
54+
55+
// If next block is start of new epoch, walk backwards one epoch
56+
uint32_t epoch_start_height = next_height - epoch_age;
57+
if (epoch_age == 0) {
58+
epoch_start_height -= epoch_length;
59+
}
60+
61+
// We need to put in place the previous epoch's current which
62+
// may be pre-dynafed params
63+
const CBlockIndex* p_epoch_start = pindexPrev->GetAncestor(epoch_start_height);
64+
assert(p_epoch_start);
65+
if (p_epoch_start->d_params.IsNull()) {
66+
// We need to construct the "full" current parameters of pre-dynafed
67+
// consensus
68+
69+
// Convert signblockscript to P2WSH
70+
CScript p2wsh_signblock_script = GetScriptForDestination(WitnessV0ScriptHash(p_epoch_start->proof.challenge));
71+
winning_proposal = ConsensusParamEntry(p2wsh_signblock_script, consensus.max_block_signature_size+consensus.signblockscript.size(), consensus.fedpegScript, consensus.first_extension_space);
72+
} else {
73+
winning_proposal = p_epoch_start->d_params.m_current;
74+
}
75+
return winning_proposal;
76+
}
77+
78+
// TODO cache this in CBlockIndex itself?
79+
ConsensusParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus)
80+
{
81+
assert(pindexPrev);
82+
83+
ConsensusParamEntry entry = ComputeNextBlockFullCurrentParameters(pindexPrev, consensus);
84+
85+
uint32_t next_height = pindexPrev->nHeight+1;
86+
const uint32_t epoch_length = consensus.dynamic_epoch_length;
87+
uint32_t epoch_age = next_height % epoch_length;
88+
89+
// Return appropriate format based on epoch age
90+
if (epoch_age > 0) {
91+
// TODO implement "prune" function to remove fields in place and change serialize type
92+
return ConsensusParamEntry(entry.m_signblockscript, entry.m_sbs_wit_limit);
93+
} else {
94+
return entry;
95+
}
96+
}
97+

src/dynafed.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
#ifndef BITCOIN_DYNAFED_H
3+
#define BITCOIN_DYNAFED_H
4+
5+
#include <chain.h>
6+
#include <chainparams.h>
7+
#include <primitives/block.h>
8+
9+
10+
bool NextBlockIsParameterTransition(const CBlockIndex* pindexPrev, const Consensus::Params& consensus, ConsensusParamEntry& winning_entry);
11+
12+
/* Compute the next block's enforced parameters */
13+
ConsensusParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus);
14+
/* Compute the next block's expected published parameters. Blocks at "epoch_age" of non-0 only
15+
* publish signblockscript-related fields */
16+
ConsensusParamEntry ComputeNextBlockCurrentParameters(const CBlockIndex* pindexPrev, const Consensus::Params& consensus);
17+
18+
19+
#endif // BITCOIN_DYNAFED_H

0 commit comments

Comments
 (0)