From f49c0a68468e5ac12db12d674c7734a6439d71d2 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Fri, 31 May 2019 10:57:36 -0400 Subject: [PATCH] Define dynamic federations primitives --- src/primitives/block.cpp | 26 +++++++++ src/primitives/block.h | 110 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index fe72ff037f..707dc68d40 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -40,3 +40,29 @@ std::string CBlock::ToString() const } return s.str(); } + +uint256 ConsensusParamEntry::CalculateRoot() const +{ + if (IsNull()) { + return uint256(); + } + + std::vector leaves; + leaves.push_back(SerializeHash(m_signblockscript, SER_GETHASH, 0)); + leaves.push_back(SerializeHash(m_sbs_wit_limit, SER_GETHASH, 0)); + leaves.push_back(SerializeHash(m_fedpegscript, SER_GETHASH, 0)); + leaves.push_back(SerializeHash(m_extension_space, SER_GETHASH, 0)); + return ComputeFastMerkleRoot(leaves); +} + +uint256 DynaFedParams::CalculateRoot() const +{ + if (IsNull()) { + return uint256(); + } + + std::vector leaves; + leaves.push_back(m_current.CalculateRoot()); + leaves.push_back(m_proposed.CalculateRoot()); + return ComputeFastMerkleRoot(leaves); +} diff --git a/src/primitives/block.h b/src/primitives/block.h index 62aa50e644..4551200d74 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -52,6 +52,116 @@ public: std::string ToString() const; }; + +class ConsensusParamEntry +{ +public: + unsigned char m_serialize_type; // Determines how it is serialized, defaults to null + CScript m_signblockscript; + uint32_t m_sbs_wit_limit; // Max block signature witness serialized size + CScript m_fedpegscript; + // No consensus meaning to the particular bytes, currently we interpret as PAK keys, details in pak.h + std::vector> m_extension_space; + + // Each constructor sets its own serialization type implicitly based on which + // arguments are given + ConsensusParamEntry() { m_sbs_wit_limit = 0; m_serialize_type = 0; }; + ConsensusParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in) : m_signblockscript(signblockscript_in), m_sbs_wit_limit(sbs_wit_limit_in) { m_serialize_type = 1; }; + ConsensusParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in, const CScript& fedpegscript_in, const std::vector> extension_space_in) : m_signblockscript(signblockscript_in), m_sbs_wit_limit(sbs_wit_limit_in), m_fedpegscript(fedpegscript_in), m_extension_space(extension_space_in) { m_serialize_type = 2; }; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(m_serialize_type); + switch(m_serialize_type) { + case 0: + /* Null entry, used to signal "no vote" proposal */ + break; + case 1: + READWRITE(m_signblockscript); + READWRITE(m_sbs_wit_limit); + break; + case 2: + READWRITE(m_signblockscript); + READWRITE(m_sbs_wit_limit); + READWRITE(m_fedpegscript); + READWRITE(m_extension_space); + break; + default: + throw std::ios_base::failure("Invalid consensus parameter entry type"); + } + } + + uint256 CalculateRoot() const; + + bool IsNull() const + { + return m_serialize_type == 0 && + m_signblockscript.empty() && + m_sbs_wit_limit == 0 && + m_fedpegscript.empty() && + m_extension_space.empty(); + + } + + void SetNull() + { + m_serialize_type = 0; + m_signblockscript = CScript(); + m_sbs_wit_limit = 0; + m_fedpegscript = CScript(); + m_extension_space.clear(); + } + + bool operator==(const ConsensusParamEntry &other) const + { + return m_serialize_type == other.m_serialize_type && + m_signblockscript == other.m_signblockscript && + m_sbs_wit_limit == other.m_sbs_wit_limit && + m_fedpegscript == other.m_fedpegscript && + m_extension_space == other.m_extension_space; + } + bool operator!=(const ConsensusParamEntry &other) const + { + return !(*this == other); + } +}; + +class DynaFedParams +{ +public: + + // Currently enforced by network, not all fields may be known + ConsensusParamEntry m_current; + // Proposed rules for next epoch + ConsensusParamEntry m_proposed; + + DynaFedParams() {}; + DynaFedParams(const ConsensusParamEntry& current, const ConsensusParamEntry& proposed) : m_current(current), m_proposed(proposed) {}; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(m_current); + READWRITE(m_proposed); + } + + uint256 CalculateRoot() const; + + bool IsNull() const + { + return m_current.IsNull() && m_proposed.IsNull(); + } + + void SetNull() + { + m_current.SetNull(); + m_proposed.SetNull(); + } +}; + /** Nodes collect new transactions into a block, hash them into a hash tree, * and scan through nonce values to make the block's hash satisfy proof-of-work * requirements. When they solve the proof-of-work, they broadcast the block