Skip to content

Commit

Permalink
fork-choise
Browse files Browse the repository at this point in the history
Signed-off-by: Stanislav Frolov <[email protected]>
  • Loading branch information
frolosofsky committed Oct 31, 2018
1 parent e98b3d6 commit a96f996
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 77 deletions.
99 changes: 72 additions & 27 deletions src/esperanza/finalizationstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@

namespace esperanza {

/**
* UNIT-E: It is now simplistic to imply only one State; to be able to
* handle intra-dynasty forks and continue with a consistent state it's gonna be
* necessary to store a snapshot of the state for each block from at least the
* last justified one.
*/
static std::shared_ptr<FinalizationState> esperanzaState;

static CCriticalSection cs_init_lock;

FinalizationState::Storage FinalizationState::m_storage;
Expand Down Expand Up @@ -897,27 +889,66 @@ uint32_t FinalizationState::GetCurrentDynasty() const {
return m_currentDynasty;
}

FinalizationState *FinalizationState::Storage::FindOrCreate(
const CBlockIndex *index) {
FinalizationState *FinalizationState::Storage::Find(const CBlockIndex *index) {
if (index->nHeight == 0 || index->phashBlock == 0) {
return GetGenesisState();
}
LOCK(cs_storage);
if (index == nullptr || index->pprev == nullptr ||
index->phashBlock == nullptr) {
return esperanzaState.get();
auto it = m_states.find(index->GetBlockHash());
return it == m_states.end() ? nullptr : &it->second;
}

std::tuple<FinalizationState *, bool> FinalizationState::Storage::FindOrCreate(
const CBlockIndex *index) {
if (index == nullptr) {
return {nullptr, false};
}
if (auto state = Find(index)) {
return {state, true};
}
auto const hash = index->GetBlockHash();
auto it = states.find(hash);
if (it == states.end()) {
it = states.emplace(hash, FinalizationState(*FindOrCreate(index->pprev)))
.first;
auto prev = Find(index->pprev);
if (prev == nullptr) {
LogPrint(BCLog::FINALIZATION, "Cannot find parent state (%s) for %s\n",
index->pprev->GetBlockHash().GetHex(),
index->GetBlockHash().GetHex());
return {nullptr, false};
}
return &it->second;
LOCK(cs_storage);
auto it =
m_states.emplace(index->GetBlockHash(), FinalizationState(*prev)).first;
return {&it->second, false};
}

void FinalizationState::Storage::Init(
const esperanza::FinalizationParams &params,
const esperanza::AdminParams &adminParams) {
LOCK(cs_storage);
m_genesis_state.reset(new FinalizationState(params, adminParams));
}

void FinalizationState::Storage::Reset(
const esperanza::FinalizationParams &params,
const esperanza::AdminParams &adminParams) {
LOCK(cs_storage);
m_states.clear();
m_genesis_state.reset(new FinalizationState(params, adminParams));
}

FinalizationState *FinalizationState::Storage::GetGenesisState() {
LOCK(cs_storage);
assert(m_genesis_state != nullptr);
return m_genesis_state.get();
}

FinalizationState *FinalizationState::GetState(const CBlockIndex *blockIndex) {
if (blockIndex == nullptr) {
blockIndex = chainActive.Tip();
}
return m_storage.FindOrCreate(blockIndex);
if (blockIndex == nullptr) {
return m_storage.GetGenesisState();
}
assert(blockIndex != nullptr);
return m_storage.Find(blockIndex);
}

uint32_t FinalizationState::GetEpoch(const CBlockIndex *blockIndex) {
Expand Down Expand Up @@ -954,15 +985,13 @@ bool FinalizationState::ValidateDepositAmount(CAmount amount) {
void FinalizationState::Init(const esperanza::FinalizationParams &params,
const esperanza::AdminParams &adminParams) {
LOCK(cs_init_lock);

if (!esperanzaState) {
esperanzaState = std::make_shared<FinalizationState>(params, adminParams);
}
m_storage.Init(params, adminParams);
}

void FinalizationState::Reset(const esperanza::FinalizationParams &params,
const esperanza::AdminParams &adminParams) {
esperanzaState = std::make_shared<FinalizationState>(params, adminParams);
LOCK(cs_init_lock);
m_storage.Reset(params, adminParams);
}

/**
Expand All @@ -975,11 +1004,22 @@ void FinalizationState::Reset(const esperanza::FinalizationParams &params,
bool FinalizationState::ProcessNewTip(const CBlockIndex &blockIndex,
const CBlock &block) {

FinalizationState *state = GetState(&blockIndex);

LogPrint(BCLog::FINALIZATION, "%s: Processing block %d with hash %s.\n",
__func__, blockIndex.nHeight, block.GetHash().GetHex());

FinalizationState *state;
bool found;
std::tie(state, found) = m_storage.FindOrCreate(&blockIndex);
if (found) {
LogPrint(BCLog::FINALIZATION, "It's already processed\n");
return true; // This block should be already processed
}

if (state == nullptr) {
LogPrint(BCLog::FINALIZATION, "Cannot create FinalizationState.\n");
return false;
}

// Used to apply hardcoded parameters for a given block
state->OnBlock(blockIndex.nHeight);

Expand Down Expand Up @@ -1062,6 +1102,7 @@ bool FinalizationState::ProcessNewTip(const CBlockIndex &blockIndex,

return true;
}

// Private accessors used to avoid map's operator[] potential side effects.
ufp64::ufp64_t FinalizationState::GetDepositScaleFactor(uint32_t epoch) const {
auto it = m_depositScaleFactor.find(epoch);
Expand All @@ -1086,4 +1127,8 @@ Checkpoint &FinalizationState::GetCheckpoint(uint32_t epoch) {
return it->second;
}

int FinalizationState::GetBlockHeightForEpoch(uint32_t epoch) const {
return static_cast<int>(epoch * m_settings.m_epochLength);
}

} // namespace esperanza
25 changes: 22 additions & 3 deletions src/esperanza/finalizationstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ class FinalizationState : public FinalizationStateData {

uint256 GetCheckpointHash(uint32_t epoch) const;

int GetBlockHeightForEpoch(uint32_t epoch) const;

std::vector<Validator> GetValidators() const;
const Validator *GetValidator(const uint256 &validatorIndex) const;

Expand Down Expand Up @@ -231,10 +233,27 @@ class FinalizationState : public FinalizationStateData {

mutable CCriticalSection cs_esperanza;

struct Storage {
std::map<uint256, FinalizationState> states;
FinalizationState *FindOrCreate(const CBlockIndex *index);
class Storage {
public:
/** Find or create FinalizationState for the `index`.
* If found, return { state, true }
* If not found but created, return { newstate, false } where newstate is a
* copy of `index`->pprev, and supposed to be processed by
* `ProcessNewTip()`. If not found, return { nullptr, false }
*/
FinalizationState *Find(const CBlockIndex *index);
std::tuple<FinalizationState *, bool> FindOrCreate(
const CBlockIndex *index);
void Init(const esperanza::FinalizationParams &params,
const esperanza::AdminParams &adminParams);
void Reset(const esperanza::FinalizationParams &params,
const esperanza::AdminParams &adminParams);
FinalizationState *GetGenesisState();

private:
std::map<uint256, FinalizationState> m_states;
CCriticalSection cs_storage;
std::unique_ptr<FinalizationState> m_genesis_state;
};
static Storage m_storage;

Expand Down
2 changes: 1 addition & 1 deletion src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1379,8 +1379,8 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
// etc), and not just the duplicate-invalid case.
pfrom->fDisconnect = true;
}
return error("invalid header received");
}
return error("invalid header received");
}

{
Expand Down
4 changes: 2 additions & 2 deletions src/test/esperanza/finalizationstate_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(constructor) {

// InitializeEpoch tests

BOOST_AUTO_TEST_CASE(initialize_epcoh_wrong_height_passed) {
BOOST_AUTO_TEST_CASE(initialize_epoch_wrong_height_passed) {

FinalizationStateSpy state;

Expand All @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(initialize_epcoh_wrong_height_passed) {
BOOST_CHECK_EQUAL(0, state.GetLastJustifiedEpoch());
}

BOOST_AUTO_TEST_CASE(initialize_epcoh_insta_finalize) {
BOOST_AUTO_TEST_CASE(initialize_epoch_insta_finalize) {

FinalizationStateSpy spy;

Expand Down
2 changes: 1 addition & 1 deletion src/test/esperanza/validation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const int64_t EPOCH_LENGTH = 50;
BOOST_FIXTURE_TEST_SUITE(finalization_validation_tests, TestingSetup)

BOOST_AUTO_TEST_CASE(isvoteexpired) {

FinalizationState *esperanza = FinalizationState::GetState();
assert(esperanza != nullptr);

uint256 validatorIndex = GetRandHash();

Expand Down
Loading

0 comments on commit a96f996

Please sign in to comment.