From 804cd9f75fc8f9a905c832fcc39de68d7c969356 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Fri, 31 May 2019 12:39:55 -0400 Subject: [PATCH] Update PAK internals, helper functions --- src/primitives/pak.cpp | 126 +++++++++++++++++++---------------------- src/primitives/pak.h | 39 +++++-------- src/rpc/misc.cpp | 18 ++---- src/validation.cpp | 77 ------------------------- src/validation.h | 3 - 5 files changed, 76 insertions(+), 187 deletions(-) diff --git a/src/primitives/pak.cpp b/src/primitives/pak.cpp index 430e26ccc1..997fd0cd70 100644 --- a/src/primitives/pak.cpp +++ b/src/primitives/pak.cpp @@ -4,6 +4,7 @@ #include #include +#include // ELEMENTS @@ -33,73 +34,9 @@ public: static CSecp256k1Init instance_of_csecp256k1; } -CScript CPAKList::Magic() -{ - CScript scriptPubKey; - scriptPubKey.resize(6); - scriptPubKey[0] = OP_RETURN; - scriptPubKey[1] = 0x04; - scriptPubKey[2] = 0xab; - scriptPubKey[3] = 0x22; - scriptPubKey[4] = 0xaa; - scriptPubKey[5] = 0xee; - return scriptPubKey; -} - -std::vector CPAKList::GenerateCoinbasePAKCommitments() const -{ - std::vector commitments; - CScript scriptPubKey = CPAKList::Magic(); - - for (unsigned int i = 0; i < m_offline_keys.size(); i++) { - CScript scriptCommitment(scriptPubKey); - unsigned char pubkey[33]; - size_t outputlen = 33; - secp256k1_ec_pubkey_serialize(secp256k1_ctx_pak, pubkey, &outputlen, &m_offline_keys[i], SECP256K1_EC_COMPRESSED); - assert(outputlen == 33); - scriptCommitment << std::vector(pubkey, pubkey+outputlen); - secp256k1_ec_pubkey_serialize(secp256k1_ctx_pak, pubkey, &outputlen, &m_online_keys[i], SECP256K1_EC_COMPRESSED); - assert(outputlen == 33); - scriptCommitment << std::vector(pubkey, pubkey+outputlen); - commitments.push_back(scriptCommitment); - } - - return commitments; -} - -std::vector CPAKList::GenerateCoinbasePAKReject() const -{ - CScript scriptPubKey = CPAKList::Magic(); - - std::vector reject; - reject.push_back('R'); - reject.push_back('E'); - reject.push_back('J'); - reject.push_back('E'); - reject.push_back('C'); - reject.push_back('T'); - - scriptPubKey << reject; - - std::vector commitment; - commitment.push_back(scriptPubKey); - return commitment; -} - -void CPAKList::CreateCommitments(std::vector &commitments) const -{ - if(reject) { - commitments = GenerateCoinbasePAKReject(); - } else { - commitments = GenerateCoinbasePAKCommitments(); - } -} - bool CPAKList::operator==(const CPAKList &other) const { - if (this->reject != other.reject) { - return false; - } else if (this->m_offline_keys.size() != other.m_offline_keys.size()) { + if (this->m_offline_keys.size() != other.m_offline_keys.size()) { return false; } else { for (unsigned int i = 0; i < this->m_offline_keys.size(); i++) { @@ -112,7 +49,7 @@ bool CPAKList::operator==(const CPAKList &other) const return true; } -bool CPAKList::FromBytes(CPAKList &paklist, std::vector >& offline_keys_bytes, std::vector >& online_keys_bytes, bool is_reject) +bool CPAKList::FromBytes(CPAKList &paklist, const std::vector >& offline_keys_bytes, const std::vector >& online_keys_bytes) { if(offline_keys_bytes.size() != online_keys_bytes.size() || offline_keys_bytes.size() > SECP256K1_WHITELIST_MAX_N_KEYS) { @@ -134,11 +71,11 @@ bool CPAKList::FromBytes(CPAKList &paklist, std::vector >& offline_keys, std::vector >& online_keys, bool &is_reject) const +void CPAKList::ToBytes(std::vector >& offline_keys, std::vector >& online_keys) const { offline_keys.resize(0); online_keys.resize(0); @@ -151,7 +88,6 @@ void CPAKList::ToBytes(std::vector >& offline_keys, s secp256k1_ec_pubkey_serialize(secp256k1_ctx_pak, pubkey, &outputlen, &m_online_keys[i], SECP256K1_EC_COMPRESSED); online_keys.push_back(std::vector(pubkey, pubkey+outputlen)); } - is_reject = reject; } // Proof follows the OP_RETURN @@ -243,3 +179,55 @@ bool ScriptHasValidPAKProof(const CScript& script, const uint256& genesis_hash) return true; } + +CPAKList CreatePAKListFromExtensionSpace(const std::vector>& extension_space) +{ + std::vector> offline_keys; + std::vector> online_keys; + for (const auto& entry : extension_space) { + // As soon as we find something that is possibly not 2 serialized pubkeys + // we stop looking. CPAKList::FromBytes does pubkey validation itself. + if (entry.size() != 66) { + break; + } + offline_keys.emplace_back(entry.begin(), entry.begin()+33); + online_keys.emplace_back(entry.begin()+33, entry.end()); + // Allow additional data, just ignore + if (offline_keys.size() == SECP256K1_WHITELIST_MAX_N_KEYS) { + break; + } + } + CPAKList paklist; + if (!CPAKList::FromBytes(paklist, offline_keys, online_keys)) { + return CPAKList(); + } + return paklist; +} + +CPAKList GetActivePAKList(const CBlockIndex* pblockindex, const Consensus::Params& params) +{ + assert(pblockindex); + + return CreatePAKListFromExtensionSpace(ComputeNextBlockFullCurrentParameters(pblockindex, params).m_extension_space); +} + +bool IsPAKValidOutput(const CTxOut& txout, const CPAKList& paklist) +{ + const CChainParams& params = Params(); + if (txout.scriptPubKey.IsPegoutScript(params.ParentGenesisBlockHash()) && + txout.nAsset.IsExplicit() && txout.nAsset.GetAsset() == params.GetConsensus().pegged_asset && + (!ScriptHasValidPAKProof(txout.scriptPubKey, params.ParentGenesisBlockHash(), paklist))) { + return false; + } + return true; +} + +bool IsPAKValidTx(const CTransaction& tx, const CPAKList& paklist) +{ + for (const auto& txout : tx.vout) { + if (!IsPAKValidOutput(txout, paklist)) { + return false; + } + } + return true; +} diff --git a/src/primitives/pak.h b/src/primitives/pak.h index 3191e4790c..35add8ee26 100644 --- a/src/primitives/pak.h +++ b/src/primitives/pak.h @@ -8,28 +8,22 @@ #include