Skip to content

Commit

Permalink
Initial development of order book (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mixa84 committed Mar 19, 2021
1 parent cfdda81 commit 11ad243
Show file tree
Hide file tree
Showing 12 changed files with 1,003 additions and 76 deletions.
7 changes: 5 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ DEFI_CORE_H = \
masternodes/masternodes.h \
masternodes/mn_checks.h \
masternodes/mn_rpc.h \
masternodes/order.h \
masternodes/res.h \
masternodes/rewardhistoryold.h \
masternodes/tokens.h \
Expand Down Expand Up @@ -376,10 +377,12 @@ libdefi_server_a_SOURCES = \
masternodes/mn_rpc.cpp \
masternodes/rpc_masternodes.cpp \
masternodes/rpc_accounts.cpp \
masternodes/rpc_tokens.cpp \
masternodes/rpc_orderbook.cpp \
masternodes/rpc_poolpair.cpp \
masternodes/tokens.cpp \
masternodes/rpc_tokens.cpp \
masternodes/order.cpp \
masternodes/poolpairs.cpp \
masternodes/tokens.cpp \
masternodes/undos.cpp \
miner.cpp \
net.cpp \
Expand Down
2 changes: 2 additions & 0 deletions src/masternodes/masternodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <masternodes/accountshistory.h>
#include <masternodes/anchors.h>
#include <masternodes/incentivefunding.h>
#include <masternodes/order.h>
#include <masternodes/tokens.h>
#include <masternodes/undos.h>
#include <masternodes/poolpairs.h>
Expand Down Expand Up @@ -224,6 +225,7 @@ class CCustomCSView
, public CPoolPairView
, public CGovView
, public CAnchorConfirmsView
, public COrderView
{
public:
CCustomCSView() = default;
Expand Down
145 changes: 145 additions & 0 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@ Res ApplyCustomTx(CCustomCSView & base_mnview, CCoinsViewCache const & coins, CT
case CustomTxType::AnyAccountsToAccounts:
res = ApplyAnyAccountsToAccountsTx(mnview, coins, tx, height, metadata, consensusParams, skipAuth);
break;
case CustomTxType::CreateOrder:
res = ApplyCreateOrderTx(mnview, coins, tx, height, metadata, consensusParams, skipAuth);
break;
case CustomTxType::FulfillOrder:
res = ApplyFulfillOrderTx(mnview, coins, tx, height, metadata, consensusParams, skipAuth);
break;
case CustomTxType::CloseOrder:
res = ApplyCloseOrderTx(mnview, coins, tx, height, metadata, consensusParams, skipAuth);
break;
default:
return Res::Ok(); // not "custom" tx
}
Expand Down Expand Up @@ -1510,3 +1519,139 @@ bool IsMempooledCustomTxCreate(const CTxMemPool & pool, const uint256 & txid)
}
return false;
}

Res ApplyCreateOrderTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth, UniValue *rpcInfo)
{
// Check quick conditions first
if (tx.vout.size() !=2) {
return Res::Err("%s: %s", __func__, "malformed tx vouts (wrong number of vouts)");
}

COrderImplemetation order;
CDataStream ss(metadata, SER_NETWORK, PROTOCOL_VERSION);
ss >> static_cast<COrder &>(order);
if (!ss.empty()) {
return Res::Err("%s: deserialization failed: excess %d bytes", __func__, ss.size());
}

order.creationTx=tx.GetHash();
order.creationHeight = height;

CTxDestination ownerDest = DecodeDestination(order.ownerAddress);
if (ownerDest.which() == 0) {
return Res::Err("%s: %s", __func__, "ownerAdress (" + order.ownerAddress + ") does not refer to any valid address");
}

auto tokenFrom = mnview.GetToken(order.idTokenFrom);
if (!tokenFrom) {
return Res::Err("%s: token %s does not exist!", tokenFrom->symbol);
}
auto tokenTo = mnview.GetToken(order.idTokenTo);
if (!tokenTo) {
return Res::Err("%s: token %s does not exist!", tokenTo->symbol);
}

// Return here to avoid already exist error
if (rpcInfo) {
rpcInfo->pushKV("creationTx", order.creationTx.GetHex());
rpcInfo->pushKV("ownerAddress", order.ownerAddress);
rpcInfo->pushKV("tokenFrom", order.tokenFrom);
rpcInfo->pushKV("tokenTo", order.tokenTo);
rpcInfo->pushKV("amountFrom", order.amountFrom);
rpcInfo->pushKV("orderPrice", order.orderPrice);
rpcInfo->pushKV("expiry", static_cast<int>(order.expiry));

return Res::Ok();
}

auto res = mnview.CreateOrder(order);
if (!res.ok) {
return Res::Err("%s %s: %s", __func__, order.creationTx.GetHex(), res.msg);
}

return Res::Ok();
}

Res ApplyFulfillOrderTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth, UniValue *rpcInfo)
{
// Check quick conditions first
if (tx.vout.size() !=2) {
return Res::Err("%s: %s", __func__, "malformed tx vouts (wrong number of vouts)");
}

CFulfillOrderImplemetation fillorder;
CDataStream ss(metadata, SER_NETWORK, PROTOCOL_VERSION);
ss >> static_cast<CFulfillOrder &>(fillorder);
if (!ss.empty()) {
return Res::Err("%s: deserialization failed: excess %d bytes", __func__, ss.size());
}

fillorder.creationTx=tx.GetHash();
fillorder.creationHeight = height;

CTxDestination ownerDest = DecodeDestination(fillorder.ownerAddress);
if (ownerDest.which() == 0) {
return Res::Err("%s: %s", __func__, "ownerAdress (" + fillorder.ownerAddress + ") does not refer to any valid address");
}
if (!mnview.GetOrderByCreationTx(fillorder.orderTx)) {
return Res::Err("order with creation tx %s does not exists!", fillorder.orderTx.GetHex());
}

// Return here to avoid already exist error
if (rpcInfo) {
rpcInfo->pushKV("ownerAddress", fillorder.ownerAddress);
rpcInfo->pushKV("orderTx", fillorder.orderTx.GetHex());
rpcInfo->pushKV("amount", fillorder.amount);
return Res::Ok();
}

auto res = mnview.FulfillOrder(fillorder);
if (!res.ok) {
return Res::Err("%s %s: %s", __func__, fillorder.creationTx.GetHex(), res.msg);
}

return Res::Ok();
}

Res ApplyCloseOrderTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth, UniValue *rpcInfo)
{
// Check quick conditions first
if (tx.vout.size() !=2) {
return Res::Err("%s: %s", __func__, "malformed tx vouts (wrong number of vouts)");
}

CCloseOrderImplemetation closeorder;
CDataStream ss(metadata, SER_NETWORK, PROTOCOL_VERSION);
ss >> static_cast<CCloseOrder &>(closeorder);
if (!ss.empty()) {
return Res::Err("%s: deserialization failed: excess %d bytes", __func__, ss.size());
}

closeorder.creationTx=tx.GetHash();
closeorder.creationHeight = height;

std::unique_ptr<COrderImplemetation> order;
if (!(order=mnview.GetOrderByCreationTx(closeorder.orderTx))) {
return Res::Err("order with creation tx %s does not exists!", closeorder.orderTx.GetHex());
}

order->closeTx=closeorder.creationTx;
order->closeHeight=closeorder.creationHeight;

// Return here to avoid already exist error
if (rpcInfo) {
rpcInfo->pushKV("orderTx", closeorder.orderTx.GetHex());
return Res::Ok();
}

// auto res = mnview.CloseOrder(closeorder);
// if (!res.ok) {
// return Res::Err("%s %s: %s", __func__, closeorder.creationTx.GetHex(), res.msg);
// }
// res = mnview.CloseOrderTx(*order);
// if (!res.ok) {
// return Res::Err("%s %s: %s", __func__, closeorder.creationTx.GetHex(), res.msg);
// }

return Res::Ok();
}
15 changes: 11 additions & 4 deletions src/masternodes/mn_checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ enum class CustomTxType : unsigned char
UpdateToken = 'N', // previous type, only DAT flag triggers
UpdateTokenAny = 'n', // new type of token's update with any flags/fields possible
// dex orders - just not to overlap in future
// CreateOrder = 'O',
// DestroyOrder = 'E',
// MatchOrders = 'A',
CreateOrder = 'O',
FulfillOrder = 'F',
CloseOrder = 'S',
//poolpair
CreatePoolPair = 'p',
UpdatePoolPair = 'u',
Expand All @@ -59,7 +59,7 @@ enum class CustomTxType : unsigned char
};

inline CustomTxType CustomTxCodeToType(unsigned char ch) {
char const txtypes[] = "CRTMNnpuslrUbBaGA";
char const txtypes[] = "CRTMNnOFSpuslrUbBaGA";
if (memchr(txtypes, ch, strlen(txtypes)))
return static_cast<CustomTxType>(ch);
else
Expand All @@ -86,6 +86,9 @@ inline std::string ToString(CustomTxType type) {
case CustomTxType::AnyAccountsToAccounts: return "AnyAccountsToAccounts";
case CustomTxType::SetGovVariable: return "SetGovVariable";
case CustomTxType::AutoAuthPrep: return "AutoAuth";
case CustomTxType::CreateOrder: return "CreateOrder";
case CustomTxType::FulfillOrder: return "FulfillOrder";
case CustomTxType::CloseOrder: return "CloseOrder";
default: return "None";
}
}
Expand Down Expand Up @@ -131,6 +134,10 @@ Res ApplyAccountToUtxosTx(CCustomCSView & mnview, CCoinsViewCache const & coins,
Res ApplyAccountToAccountTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth = false, UniValue* rpcInfo = nullptr);
Res ApplyAnyAccountsToAccountsTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth = false, UniValue* rpcInfo = nullptr);

Res ApplyCreateOrderTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth = false, UniValue* rpcInfo = nullptr);
Res ApplyFulfillOrderTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth = false, UniValue* rpcInfo = nullptr);
Res ApplyCloseOrderTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth = false, UniValue *rpcInfo = nullptr);

Res ApplySetGovernanceTx(CCustomCSView & mnview, CCoinsViewCache const & coins, CTransaction const & tx, uint32_t height, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams, bool skipAuth = false, UniValue* rpcInfo = nullptr);

ResVal<uint256> ApplyAnchorRewardTx(CCustomCSView & mnview, CTransaction const & tx, int height, uint256 const & prevStakeModifier, std::vector<unsigned char> const & metadata, Consensus::Params const & consensusParams);
Expand Down
73 changes: 73 additions & 0 deletions src/masternodes/mn_rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,79 @@ CWallet* GetWallet(const JSONRPCRequest& request) {
return pwallet;
}

bool GetCustomTXInfo(const int nHeight, const CTransactionRef tx, CustomTxType& guess, Res& res, UniValue& txResults)
{
std::vector<unsigned char> metadata;
guess = GuessCustomTxType(*tx, metadata);
CCustomCSView mnview_dummy(*pcustomcsview);

switch (guess)
{
case CustomTxType::CreateMasternode:
res = ApplyCreateMasternodeTx(mnview_dummy, *tx, nHeight, metadata, &txResults);
break;
case CustomTxType::ResignMasternode:
res = ApplyResignMasternodeTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, true, &txResults);
break;
case CustomTxType::CreateToken:
res = ApplyCreateTokenTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::UpdateToken:
res = ApplyUpdateTokenTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::UpdateTokenAny:
res = ApplyUpdateTokenAnyTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::MintToken:
res = ApplyMintTokenTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::CreatePoolPair:
res = ApplyCreatePoolPairTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::UpdatePoolPair:
res = ApplyUpdatePoolPairTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::PoolSwap:
res = ApplyPoolSwapTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::AddPoolLiquidity:
res = ApplyAddPoolLiquidityTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::RemovePoolLiquidity:
res = ApplyRemovePoolLiquidityTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::UtxosToAccount:
res = ApplyUtxosToAccountTx(mnview_dummy, *tx, nHeight, metadata, Params().GetConsensus(), &txResults);
break;
case CustomTxType::AccountToUtxos:
res = ApplyAccountToUtxosTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::AccountToAccount:
res = ApplyAccountToAccountTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::SetGovVariable:
res = ApplySetGovernanceTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::AnyAccountsToAccounts:
res = ApplyAnyAccountsToAccountsTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::AutoAuthPrep:
res.ok = true;
res.msg = "AutoAuth";
break;
case CustomTxType::CreateOrder:
res = ApplyCreateOrderTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
case CustomTxType::FulfillOrder:
res = ApplyFulfillOrderTx(mnview_dummy, ::ChainstateActive().CoinsTip(), *tx, nHeight, metadata, Params().GetConsensus(), true, &txResults);
break;
default:
return false;
}

return true;
}

UniValue setgov(const JSONRPCRequest& request) {
CWallet* const pwallet = GetWallet(request);

Expand Down
1 change: 1 addition & 0 deletions src/masternodes/mn_rpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ CTransactionRef sign(CMutableTransaction& mtx, CWallet* const pwallet, CTransact
CTransactionRef send(CTransactionRef tx, CTransactionRef optAuthTx);
CTransactionRef signsend(CMutableTransaction& mtx, CWallet* const pwallet, CTransactionRef optAuthTx /* = {}*/);
CWallet* GetWallet(const JSONRPCRequest& request);
bool GetCustomTXInfo(const int nHeight, const CTransactionRef tx, CustomTxType& guess, Res& res, UniValue& txResults);
std::vector<CTxIn> GetAuthInputsSmart(CWallet* const pwallet, int32_t txVersion, std::set<CScript>& auths, bool needFounderAuth, CTransactionRef& optAuthTx, UniValue const& explicitInputs);
std::string ScriptToString(CScript const& script);
CAccounts GetAllMineAccounts(CWallet* const pwallet);
Expand Down
Loading

0 comments on commit 11ad243

Please sign in to comment.