Skip to content

Commit

Permalink
Verified betting token configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
watto-engineer committed Feb 17, 2023
1 parent c59fd49 commit e056498
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 31 deletions.
4 changes: 3 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ BITCOIN_CORE_H = \
betting/bet_v2.h \
betting/bet_v3.h \
betting/bet_v4.h \
betting/oracles.h \
betting/events.h \
betting/oracles.h \
betting/quickgames/dice.h \
betting/quickgames/qgview.h \
bip39.h \
Expand Down Expand Up @@ -784,6 +785,7 @@ libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_common_a_SOURCES = \
base58.cpp \
bech32.cpp \
betting/events.cpp \
betting/quickgames/dice.cpp \
bip39.cpp \
wagerraddrenc.cpp \
Expand Down
61 changes: 61 additions & 0 deletions src/betting/events.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2023 The Wagerr developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <betting/events.h>

#include <betting/bet_db.h>

bool CreateBetEventFromDB(const CBettingsView& bettingsViewCache, const uint32_t nEventId, CBetEvent& event) {
EventKey eventKey{nEventId};
CPeerlessExtendedEventDB peerlessEventDBItem;
if (bettingsViewCache.events->Read(eventKey, peerlessEventDBItem)) {
event = CBetEvent(BetEventType::PEERLESS, nEventId);
return true;
}
CFieldEventDB fieldEventDBItem;
if (bettingsViewCache.fieldEvents->Read(eventKey, fieldEventDBItem)) {
event = CBetEvent(BetEventType::FIELD, nEventId);
return true;
}
return false;
}

bool CBetEvent::IsOpen(const CBettingsView& bettingsViewCache, uint32_t nTime) {
switch (type)
{
case BetEventType::PEERLESS:
{
if (bettingsViewCache.results->Exists(ResultKey{nEventId})) {
return error("result for event already posted");
}
EventKey eventKey{nEventId};
CPeerlessExtendedEventDB eventDBItem;
if (!bettingsViewCache.events->Read(eventKey, eventDBItem)) {
return false;
}
if (eventDBItem.nStartTime >= nTime) {
return error("past event start time");
}
break;
}
case BetEventType::FIELD:
{
if (bettingsViewCache.fieldResults->Exists(FieldResultKey{nEventId})) {
return error("result for event already posted");
}
EventKey eventKey{nEventId};
CFieldEventDB eventDBItem;
if (!bettingsViewCache.fieldEvents->Read(eventKey, eventDBItem)) {
return false;
}
if (eventDBItem.nStartTime >= nTime) {
return error("past event start time");
}
break;
}
default:
return false;
}
return true;
}
51 changes: 51 additions & 0 deletions src/betting/events.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023 The Wagerr developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef WAGERR_BET_EVENT_H
#define WAGERR_BET_EVENT_H

#include <betting/bet_common.h>
#include <betting/bet_tx.h>

#include <array>
#include <string_view>

class CBettingsView;

enum class BetEventType : uint8_t {
UNKNOWN = 0x00,
PEERLESS = 0x01,
FIELD = 0x02,
LAST = FIELD
};
template<> struct is_serializable_enum<BetEventType> : std::true_type {};

constexpr std::array<std::string_view, static_cast<uint8_t>(BetEventType::LAST)+1> makeBetEventTypeDefs() {
std::array<std::string_view, static_cast<uint8_t>(BetEventType::LAST)+1> arr = {
"UNKNOWN",
"PEERLESS",
"FIELD"
};
return arr;
}
[[maybe_unused]] static constexpr auto betEventTypeDefs = makeBetEventTypeDefs();

class CBetEvent
{
public:
BetEventType type;
uint32_t nEventId;

CBetEvent() : type(BetEventType::UNKNOWN), nEventId(0) {};
CBetEvent(const CPeerlessEventTx eventTx) : type(BetEventType::PEERLESS), nEventId(eventTx.nEventId) { };
CBetEvent(const CFieldEventTx eventTx) : type(BetEventType::FIELD), nEventId(eventTx.nEventId) { };
CBetEvent(const BetEventType type, const uint32_t nEventId) : type(type), nEventId(nEventId) { };

bool IsOpen(const CBettingsView& bettingsViewCache, uint32_t nTime);

};

bool CreateBetEventFromDB(const CBettingsView& bettingsViewCache, const uint32_t nEventId, CBetEvent& event);

#endif // WAGERR_BET_EVENT_H
17 changes: 7 additions & 10 deletions src/evo/specialtxman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <primitives/block.h>
#include <validation.h>

bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs)
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, const CBettingsView& bettingsViewCache, bool check_sigs)
{
AssertLockHeld(cs_main);

Expand Down Expand Up @@ -48,16 +48,11 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
case TRANSACTION_GROUP_CREATION_REGULAR:
return CheckGroupConfigurationTxRegular(tx, pindexPrev, state, view);
case TRANSACTION_GROUP_CREATION_MGT:
if (!CheckGroupConfigurationTxMGT(tx, pindexPrev, state, view))
{
CheckGroupConfigurationTxMGT(tx, pindexPrev, state, view);
return false;
}
return true;
return CheckGroupConfigurationTxMGT(tx, pindexPrev, state, view);
case TRANSACTION_GROUP_CREATION_NFT:
return CheckGroupConfigurationTxNFT(tx, pindexPrev, state, view);
case TRANSACTION_GROUP_CREATION_BETTING:
return CheckGroupConfigurationTxBetting(tx, pindexPrev, state, view);
return CheckGroupConfigurationTxBetting(tx, pindexPrev, state, view, bettingsViewCache);
case TRANSACTION_MNHF_SIGNAL:
return pindexPrev->nHeight + 1 >= Params().GetConsensus().DIP0024Height && CheckMNHFTx(tx, pindexPrev, state);
}
Expand Down Expand Up @@ -88,6 +83,7 @@ bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValida
case TRANSACTION_GROUP_CREATION_REGULAR:
case TRANSACTION_GROUP_CREATION_MGT:
case TRANSACTION_GROUP_CREATION_NFT:
case TRANSACTION_GROUP_CREATION_BETTING:
return true; // handled per block
case TRANSACTION_MNHF_SIGNAL:
return true; // handled per block
Expand Down Expand Up @@ -115,6 +111,7 @@ bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
case TRANSACTION_GROUP_CREATION_REGULAR:
case TRANSACTION_GROUP_CREATION_MGT:
case TRANSACTION_GROUP_CREATION_NFT:
case TRANSACTION_GROUP_CREATION_BETTING:
return true; // handled per block
case TRANSACTION_MNHF_SIGNAL:
return true; // handled per block
Expand All @@ -124,7 +121,7 @@ bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
}

bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor,
CValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots)
CValidationState& state, const CCoinsViewCache& view, const CBettingsView& bettingsViewCache, bool fJustCheck, bool fCheckCbTxMerleRoots)
{
AssertLockHeld(cs_main);

Expand All @@ -137,7 +134,7 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
int64_t nTime1 = GetTimeMicros();

for (const auto& ptr_tx : block.vtx) {
if (!CheckSpecialTx(*ptr_tx, pindex->pprev, state, view, fCheckCbTxMerleRoots)) {
if (!CheckSpecialTx(*ptr_tx, pindex->pprev, state, view, bettingsViewCache, fCheckCbTxMerleRoots)) {
// pass the state returned by the function above
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions src/evo/specialtxman.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
#include <sync.h>
#include <threadsafety.h>

class CBettingsView;
class CBlock;
class CBlockIndex;
class CCoinsViewCache;
class CValidationState;

extern CCriticalSection cs_main;

bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, const CBettingsView& bettingsViewCache, bool check_sigs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor,
CValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CValidationState& state, const CCoinsViewCache& view, const CBettingsView& bettingsViewCache, bool fJustCheck, bool fCheckCbTxMerleRoots) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

#endif // BITCOIN_EVO_SPECIALTXMAN_H
10 changes: 5 additions & 5 deletions src/evo/verifiable.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
#ifndef BITCOIN_EVO_VERIFIABLE_H
#define BITCOIN_EVO_VERIFIABLE_H

#include <uint256.h>
#include <array>
#include <serialize.h>
#include <string_view>
#include <uint256.h>

class CBLSPublicKey;
class CBLSSignature;
class CValidationState;

enum SignerType : uint8_t {
enum class SignerType : uint8_t {
UNKNOWN = 0x00,
MGT = 0x01,
ORAT = 0x02, // unimplemented
Expand All @@ -22,16 +23,15 @@ enum SignerType : uint8_t {
};
template<> struct is_serializable_enum<SignerType> : std::true_type {};

constexpr std::array<std::string_view, SignerType::LAST+1> makeSignerTypeDefs() {
std::array<std::string_view, SignerType::LAST+1> arr = {
constexpr std::array<std::string_view, static_cast<uint8_t>(SignerType::LAST)+1> makeSignerTypeDefs() {
std::array<std::string_view, static_cast<uint8_t>(SignerType::LAST)+1> arr = {
"UNKNOWN",
"MGT",
"ORAT",
"LLMQ"
};
return arr;
}

[[maybe_unused]] static constexpr auto signerTypeDefs = makeSignerTypeDefs();

class Verifiable {
Expand Down
3 changes: 2 additions & 1 deletion src/rpc/rpcevo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,8 @@ static std::string SignAndSendSpecialTx(const JSONRPCRequest& request, const CMu
LOCK(cs_main);

CValidationState state;
if (!CheckSpecialTx(CTransaction(tx), ::ChainActive().Tip(), state, ::ChainstateActive().CoinsTip(), true)) {
CBettingsView bettingsViewDummy = CBettingsView();
if (!CheckSpecialTx(CTransaction(tx), ::ChainActive().Tip(), state, ::ChainstateActive().CoinsTip(), bettingsViewDummy, true)) {
throw std::runtime_error(FormatStateMessage(state));
}
} // cs_main
Expand Down
13 changes: 8 additions & 5 deletions src/tokens/tokengroupconfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "tokens/tokengroupconfiguration.h"
#include "tokens/tokengroupmanager.h"

#include <betting/events.h>
#include <chain.h>
#include <consensus/consensus.h>
#include <evo/specialtx.h>
Expand Down Expand Up @@ -328,7 +329,7 @@ bool CheckGroupConfigurationTxNFT(const CTransaction& tx, const CBlockIndex* pin
return true;
}

bool CheckGroupConfigurationTxBetting(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view)
bool CheckGroupConfigurationTxBetting(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, const CBettingsView& bettingsView)
{
if (!CheckGroupConfigurationTxBase(tx, pindexPrev, state, view)) {
return false;
Expand All @@ -342,11 +343,13 @@ bool CheckGroupConfigurationTxBetting(const CTransaction& tx, const CBlockIndex*
if (!GetTxPayload(tx, tgDesc)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "grp-bad-protx-payload");
}
/*
if (!tgDesc.vchData.size() > MAX_TX_NFT_DATA) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "grp-bad-data");
CBetEvent event;
if (!CreateBetEventFromDB(bettingsView, tgDesc.nEventId, event)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "grp-bad-event");
};
if (!event.IsOpen(bettingsView, pindexPrev->nTime)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "grp-bad-event");
}
*/

if (tgDesc.nVersion == 0 || tgDesc.nVersion > CTokenGroupDescriptionBetting::CURRENT_VERSION) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "grp-bad-version");
Expand Down
3 changes: 2 additions & 1 deletion src/tokens/tokengroupconfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <unordered_map>

class CBlockIndex;
class CBettingsView;

class CTokenGroupStatus
{
Expand Down Expand Up @@ -96,6 +97,6 @@ bool CreateTokenGroup(const CTransactionRef tx, const uint256& blockHash, CToken
bool CheckGroupConfigurationTxRegular(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view);
bool CheckGroupConfigurationTxMGT(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view);
bool CheckGroupConfigurationTxNFT(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view);
bool CheckGroupConfigurationTxBetting(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view);
bool CheckGroupConfigurationTxBetting(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, const CBettingsView& bettingsView);

#endif
10 changes: 5 additions & 5 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// DoS scoring a node for non-critical errors, e.g. duplicate keys because a TX is received that was already
// mined
// NOTE: we use UTXO here and do NOT allow mempool txes as masternode collaterals
if (!CheckSpecialTx(tx, ::ChainActive().Tip(), state, ::ChainstateActive().CoinsTip(), true))
if (!CheckSpecialTx(tx, ::ChainActive().Tip(), state, ::ChainstateActive().CoinsTip(), bettingsViewCache, true))
return false;

if (pool.existsProviderTxConflict(tx)) {
Expand Down Expand Up @@ -2247,7 +2247,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
bool fV18Active_context = pindex->nHeight >= Params().GetConsensus().V18DeploymentHeight;

// MUST process special txes before updating UTXO to ensure consistency between mempool and block processing
if (!ProcessSpecialTxsInBlock(block, pindex, *m_quorum_block_processor, state, view, fJustCheck, fScriptChecks)) {
if (!ProcessSpecialTxsInBlock(block, pindex, *m_quorum_block_processor, state, view, bettingsViewCache, fJustCheck, fScriptChecks)) {
return error("ConnectBlock(WAGERR): ProcessSpecialTxsInBlock for block %s failed with %s",
pindex->GetBlockHash().ToString(), FormatStateMessage(state));
}
Expand Down Expand Up @@ -5025,7 +5025,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}

/** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params)
bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, CBettingsView& bettingsViewCache, const CChainParams& params)
{
assert(m_quorum_block_processor);

Expand All @@ -5037,7 +5037,7 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i

// MUST process special txes before updating UTXO to ensure consistency between mempool and block processing
CValidationState state;
if (!ProcessSpecialTxsInBlock(block, pindex, *m_quorum_block_processor, state, inputs, false /*fJustCheck*/, false /*fScriptChecks*/)) {
if (!ProcessSpecialTxsInBlock(block, pindex, *m_quorum_block_processor, state, inputs, bettingsViewCache, false /*fJustCheck*/, false /*fScriptChecks*/)) {
return error("RollforwardBlock(WAGERR): ProcessSpecialTxsInBlock for block %s failed with %s",
pindex->GetBlockHash().ToString(), FormatStateMessage(state));
}
Expand Down Expand Up @@ -5120,7 +5120,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
const CBlockIndex* pindex = pindexNew->GetAncestor(nHeight);
LogPrintf("Rolling forward %s (%i)\n", pindex->GetBlockHash().ToString(), nHeight);
uiInterface.ShowProgress(_("Replaying blocks...").translated, (int) ((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)) , false);
if (!RollforwardBlock(pindex, cache, params)) return false;
if (!RollforwardBlock(pindex, cache, bettingsViewCache, params)) return false;
}

cache.SetBestBlock(pindexNew->GetBlockHash());
Expand Down
2 changes: 1 addition & 1 deletion src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ class CChainState
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);


bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, CBettingsView& bettingsViewCache, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

//! Mark a block as conflicting
bool MarkConflictingBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
Expand Down

0 comments on commit e056498

Please sign in to comment.